Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Added TSC passthrough specification to time handling
Patrick G. Bridges [Tue, 15 May 2012 18:16:41 +0000 (12:16 -0600)]
palacios/include/palacios/vmm_time.h
palacios/src/palacios/svm.c
palacios/src/palacios/vmm_time.c
palacios/src/palacios/vmx.c

index 4a35cc2..9293329 100644 (file)
@@ -37,7 +37,8 @@ struct v3_time {
     int flags;
     uint32_t td_num, td_denom; 
 };
-#define V3_TIME_SLAVE_HOST (1 << 1)
+#define V3_TIME_SLAVE_HOST (1 << 0)
+#define V3_TIME_TSC_PASSTHROUGH (1 << 1)
 
 /* Per-core time information */
 struct vm_core_time {
@@ -65,8 +66,9 @@ struct vm_core_time {
 
 };
 
-#define VM_TIME_TRAP_RDTSC (1 << 0)
-#define VM_TIME_SLAVE_HOST (1 << 1)
+#define VM_TIME_SLAVE_HOST (1 << 0)
+#define VM_TIME_TSC_PASSTHROUGH (1 << 1)
+#define VM_TIME_TRAP_RDTSC (1 << 2)
 
 struct v3_timer_ops {
     void (*update_timer)(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data);
@@ -120,7 +122,7 @@ static inline uint64_t v3_get_guest_tsc(struct vm_core_time *t) {
 // Returns offset of guest TSC from host TSC
 static inline sint64_t v3_tsc_host_offset(struct vm_core_time *time_state) {
     uint64_t host_time = v3_get_host_time(time_state);
-    return ((sint64_t)time_state->guest_cycles - (sint64_t)host_time) + time_state->tsc_guest_offset;
+    return (sint64_t)v3_get_guest_tsc(time_state) - (sint64_t)host_time;
 }
 
 // Functions for handling exits on the TSC when fully virtualizing 
index 9d17949..4d148e9 100644 (file)
@@ -529,7 +529,11 @@ v3_svm_config_tsc_virtualization(struct guest_info * info) {
     } else {
        ctrl_area->instrs.RDTSC = 0;
        ctrl_area->svm_instrs.RDTSCP = 0;
-        ctrl_area->TSC_OFFSET = v3_tsc_host_offset(&info->time_state);
+       if (info->time_state.flags & VM_TIME_TSC_PASSTHROUGH) {
+               ctrl_area->TSC_OFFSET = 0;
+       } else {
+               ctrl_area->TSC_OFFSET = v3_tsc_host_offset(&info->time_state);
+       }
     }
     return 0;
 }
index ce89b21..5b3bfe7 100644 (file)
@@ -314,7 +314,7 @@ static int tsc_msr_write_hook(struct guest_info *info, uint_t msr_num,
 
 static int
 handle_time_configuration(struct v3_vm_info * vm, v3_cfg_tree_t *cfg) {
-    char *source, *dilation;
+    char *source, *dilation, *tsc;
 
     vm->time_state.flags = V3_TIME_SLAVE_HOST;
     vm->time_state.td_num = vm->time_state.td_denom = 1;
@@ -332,6 +332,19 @@ handle_time_configuration(struct v3_vm_info * vm, v3_cfg_tree_t *cfg) {
        }
     }
 
+    // Should we make a separate TSC device that handles this sort of thing?
+    tsc = v3_cfg_val(cfg, "tsc");
+    if (tsc) {
+       if (strcasecmp(tsc, "host") == 0) {
+           if (!(vm->time_state.flags & V3_TIME_SLAVE_HOST)) {
+               PrintError("WARNING: Guest TSC set to passthrough host TSC, but guest time not slaved to host time.");
+           }
+           vm->time_state.flags |= V3_TIME_TSC_PASSTHROUGH;
+       } else if (strcasecmp(source, "guest") != 0) {
+           PrintError("ERROR: Unknown TSC configuration in time configuration.\n");
+       }
+    }
+
     dilation = v3_cfg_val(cfg, "dilation");
     if (dilation) {
         if (!(vm->time_state.flags & VM_TIME_SLAVE_HOST)) {
@@ -450,10 +463,18 @@ void v3_init_time_core(struct guest_info * info) {
     if (info->vm_info->time_state.flags & V3_TIME_SLAVE_HOST) {
        time_state->flags |= VM_TIME_SLAVE_HOST;
     }
+    if (info->vm_info->time_state.flags & V3_TIME_TSC_PASSTHROUGH) {
+       time_state->flags |= VM_TIME_TSC_PASSTHROUGH;
+    }
+
     if ((time_state->clock_ratio_denom != 1) ||
        (time_state->clock_ratio_num != 1) ||
        (info->vm_info->time_state.td_num != 1) || 
        (info->vm_info->time_state.td_denom != 1)) { 
+       if (time_state->flags | VM_TIME_TSC_PASSTHROUGH) {
+           PrintError("WARNING: Cannot use reqested passthrough TSC with clock or time modification also requested.\n");
+           time_state->flags &= ~VM_TIME_TSC_PASSTHROUGH;
+       }
        time_state->flags |= VM_TIME_TRAP_RDTSC;
     }
 
@@ -466,9 +487,11 @@ void v3_init_time_core(struct guest_info * info) {
               info->vm_info->time_state.td_denom, 
               time_state->clock_ratio_num, time_state->clock_ratio_denom,
               time_state->ipc_ratio_num, time_state->ipc_ratio_denom);
-    PrintDebug("    source = %s, rdtsc trapping = %s\n", 
+    PrintDebug("    time source = %s, tsc handling =  %s\n", 
               (time_state->flags & VM_TIME_SLAVE_HOST) ? "host" : "none",
-              (time_state->flags & VM_TIME_TRAP_RDTSC) ? "true" : "false");
+              (time_state->flags & VM_TIME_TSC_PASSTHROUGH) ? "passthrough" 
+                  : (time_state->flags & VM_TIME_TRAP_RDTSC) ? "trapping" 
+                      : "offsettting");
 
     time_state->guest_cycles = 0;
     time_state->tsc_guest_offset = 0;
index b29673f..6fa3bed 100644 (file)
@@ -886,7 +886,11 @@ v3_vmx_config_tsc_virtualization(struct guest_info * info) {
            check_vmcs_write(VMCS_PROC_CTRLS, vmx_info->pri_proc_ctrls.value);
        }
 
-        tsc_offset = v3_tsc_host_offset(&info->time_state);
+       if (info->time_state.flags & VM_TIME_TSC_PASSTHROUGH) {
+           tsc_offset = 0;
+       } else {
+            tsc_offset = v3_tsc_host_offset(&info->time_state);
+       }
         tsc_offset_high = (uint32_t)(( tsc_offset >> 32) & 0xffffffff);
         tsc_offset_low = (uint32_t)(tsc_offset & 0xffffffff);