X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_time.c;h=7cf7853cd4ff97a10a2e6c1ba9b82e9e1f8e3d88;hb=46255dee5894bc5e3be5f54a5866c0c4b30b3896;hp=cdd9040ca4097d519727b95a0a636a4a5a650426;hpb=c36e3174fd73fbdb8af835a44e2e3f0e5d75ca37;p=palacios.releases.git diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index cdd9040..7cf7853 100644 --- a/palacios/src/palacios/vmm_time.c +++ b/palacios/src/palacios/vmm_time.c @@ -84,6 +84,16 @@ static int handle_cpufreq_hcall(struct guest_info * info, uint_t hcall_id, void return 0; } +static int handle_rdhtsc_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) { + struct vm_core_time * time_state = &(info->time_state); + + info->vm_regs.rbx = v3_get_host_time(time_state); + + // PrintDebug("Guest request host TSC: return %ld\n", (long)info->vm_regs.rbx); + + return 0; +} + int v3_start_time(struct guest_info * info) { @@ -129,7 +139,7 @@ int v3_advance_time(struct guest_info * info, uint64_t *host_cycles) { uint64_t guest_cycles; - if (info->flags & VM_TIME_SLAVE_HOST) { + if (info->time_state.flags & VM_TIME_SLAVE_HOST) { struct v3_time *vm_ts = &(info->vm_info->time_state); uint64_t ht = v3_get_host_time(&info->time_state); uint64_t host_elapsed = ht - info->time_state.initial_host_time; @@ -211,6 +221,7 @@ int v3_rdtsc(struct guest_info * info) { } int v3_handle_rdtsc(struct guest_info * info) { + PrintDebug("Handling virtual RDTSC call.\n"); v3_rdtsc(info); info->vm_regs.rax &= 0x00000000ffffffffLL; @@ -246,7 +257,7 @@ int v3_rdtscp(struct guest_info * info) { int v3_handle_rdtscp(struct guest_info * info) { - PrintDebug("Handling virtual RDTSCP call.\n"); + PrintDebug("Handling virtual RDTSCP call.\n"); v3_rdtscp(info); @@ -287,6 +298,7 @@ static int tsc_msr_read_hook(struct guest_info *info, uint_t msr_num, struct v3_msr *msr_val, void *priv) { uint64_t time = v3_get_guest_tsc(&info->time_state); + PrintDebug("Handling virtual TSC MSR read call.\n"); V3_ASSERT(msr_num == TSC_MSR); msr_val->hi = time >> 32; @@ -300,18 +312,19 @@ static int tsc_msr_write_hook(struct guest_info *info, uint_t msr_num, struct vm_core_time * time_state = &(info->time_state); uint64_t guest_time, new_tsc; - V3_ASSERT(msr_num == TSC_MSR); + PrintDebug("Handling virtual TSC MSR write call.\n"); + V3_ASSERT(msr_num == TSC_MSR); - new_tsc = (((uint64_t)msr_val.hi) << 32) | (uint64_t)msr_val.lo; - guest_time = v3_get_guest_time(time_state); - time_state->tsc_guest_offset = (sint64_t)(new_tsc - guest_time); + new_tsc = (((uint64_t)msr_val.hi) << 32) | (uint64_t)msr_val.lo; + guest_time = v3_get_guest_time(time_state); + time_state->tsc_guest_offset = (sint64_t)(new_tsc - guest_time); - return 0; - } + return 0; +} 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; @@ -329,6 +342,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)) { @@ -377,6 +403,9 @@ int v3_init_time_vm(struct v3_vm_info * vm) { PrintDebug("Registering TIME_CPUFREQ hypercall.\n"); ret = v3_register_hypercall(vm, TIME_CPUFREQ_HCALL, handle_cpufreq_hcall, NULL); + PrintDebug("Registering TIME_RDHTSC hypercall.\n"); + ret = v3_register_hypercall(vm, TIME_RDHTSC_HCALL, + handle_rdhtsc_hcall, NULL); handle_time_configuration(vm, v3_cfg_subtree(cfg_tree, "time")); @@ -447,8 +476,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)) { + (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; } @@ -461,9 +500,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;