X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_time.c;h=7cf7853cd4ff97a10a2e6c1ba9b82e9e1f8e3d88;hb=1c000bda0560742ad6be011722fa226771b656ff;hp=491ceabae4b763db1493c918c3db10e64531d96c;hpb=b114cb5ecaeb5e330511684a1c8d56e23fb2f136;p=palacios.git diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index 491ceab..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; @@ -314,7 +324,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 +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)) { @@ -380,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")); @@ -450,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; } @@ -464,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;