From: Patrick G. Bridges Date: Tue, 15 May 2012 18:16:41 +0000 (-0600) Subject: Added TSC passthrough specification to time handling X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=5257ce9721525328a025a443ac086e34e0dc6441;p=palacios.git Added TSC passthrough specification to time handling --- diff --git a/palacios/include/palacios/vmm_time.h b/palacios/include/palacios/vmm_time.h index 4a35cc2..9293329 100644 --- a/palacios/include/palacios/vmm_time.h +++ b/palacios/include/palacios/vmm_time.h @@ -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 diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 9d17949..4d148e9 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -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; } diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index ce89b21..5b3bfe7 100644 --- a/palacios/src/palacios/vmm_time.c +++ b/palacios/src/palacios/vmm_time.c @@ -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; diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index b29673f..6fa3bed 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -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);