From: Patrick G. Bridges Date: Wed, 23 Feb 2011 16:57:43 +0000 (-0700) Subject: Simplified interface to timekeeping API, added to VMX code X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=e02cc15e36e8f5d7ee66390986351748dd9a16a1;p=palacios.git Simplified interface to timekeeping API, added to VMX code --- diff --git a/palacios/include/palacios/vmm_time.h b/palacios/include/palacios/vmm_time.h index 6513e30..3255aca 100644 --- a/palacios/include/palacios/vmm_time.h +++ b/palacios/include/palacios/vmm_time.h @@ -42,7 +42,8 @@ struct vm_time { // timers were updated uint64_t initial_time; // Time when VMM started. - uint64_t pause_time; // Host time when VM entered and paused. + uint64_t enter_time; // Host time the guest was last entered + uint64_t exit_time; // Host time the the VM was exited to struct v3_msr tsc_aux; // Auxilliary MSR for RDTSCP // Installed Timers slaved off of the guest monotonic TSC @@ -71,10 +72,11 @@ void v3_deinit_time_vm(struct v3_vm_info * vm); int v3_start_time(struct guest_info * core); +int v3_time_enter_vm(struct guest_info * core); +int v3_time_exit_vm(struct guest_info * core); + int v3_adjust_time(struct guest_info * core); -int v3_pause_time(struct guest_info * core); int v3_offset_time(struct guest_info * core, sint64_t offset); -int v3_restart_time(struct guest_info * core); // Basic functions for attaching timers to the passage of time struct v3_timer * v3_add_timer(struct guest_info * info, struct v3_timer_ops * ops, void * private_data); @@ -90,11 +92,15 @@ static inline uint64_t v3_get_host_time(struct vm_time *t) { // Returns *monotonic* guest time. static inline uint64_t v3_get_guest_time(struct vm_time *t) { - if (t->pause_time) { - return t->pause_time + t->guest_host_offset; +#ifdef CONFIG_TIME_HIDE_VM_COST + if (t->exit_time) { + return t->exit_time + t->guest_host_offset; } else { return v3_get_host_time(t) + t->guest_host_offset; } +#else + return v3_get_host_time(t) + t->guest_host_offset; +#endif } // Returns the TSC value seen by the guest diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 384b355..89e33d3 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -509,9 +509,7 @@ int v3_svm_enter(struct guest_info * info) { } #endif -#ifdef CONFIG_TIME_HIDE_VM_COST - v3_restart_time(info); -#endif + v3_time_enter_vm(info); guest_ctrl->TSC_OFFSET = v3_tsc_host_offset(&info->time_state); //V3_Print("Calling v3_svm_launch\n"); @@ -522,15 +520,9 @@ int v3_svm_enter(struct guest_info * info) { v3_last_exit = (uint32_t)(guest_ctrl->exit_code); -#ifdef CONFIG_TIME_HIDE_VM_COST - v3_pause_time(info); -#ifdef CONFIG_TIME_HIDE_EXIT_COST - v3_offset_time(info, -CONFIG_TIME_EXIT_COST_ADJUST); -#endif -#endif + // Immediate exit from VM time bookkeeping + v3_time_exit_vm(info); - //PrintDebug("SVM Returned\n"); - info->num_exits++; // Save Guest state from VMCB diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index 789f399..8844dee 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -349,7 +349,7 @@ static int pre_config_core(struct guest_info * info, v3_cfg_tree_t * core_cfg) { PrintError("Invalid host core %d requested by" " virtual cpu %d - ignored.\n", req_id, info->cpu_id); } else { - PrintDebug("Assigned host core %d to virtual core %d.\n", info->cpu_id, req_id, hcpu); + PrintDebug("Assigned host core %d to virtual core %d.\n", info->cpu_id, req_id); info->host_cpu_id = req_id; } } diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index 6b5fc13..06bb27c 100644 --- a/palacios/src/palacios/vmm_time.c +++ b/palacios/src/palacios/vmm_time.c @@ -86,11 +86,8 @@ int v3_start_time(struct guest_info * info) { uint64_t t = v3_get_host_time(&info->time_state); PrintDebug("Starting initial guest time as %llu\n", t); -#ifdef CONFIG_TIME_HIDE_VM_COST - info->time_state.pause_time = t; -#else - info->time_state.pause_time = 0; -#endif + info->time_state.enter_time = 0; + info->time_state.exit_time = t; info->time_state.last_update = t; info->time_state.initial_time = t; info->yield_start_cycle = t; @@ -135,32 +132,38 @@ int v3_adjust_time(struct guest_info * info) { return 0; } +/* Called immediately upon entry in the the VMM */ int -v3_pause_time( struct guest_info * info ) +v3_time_exit_vm( struct guest_info * info ) { struct vm_time * time_state = &(info->time_state); - if (time_state->pause_time == 0) { - time_state->pause_time = v3_get_host_time(time_state); -// PrintDebug("Pausing at host time %llu.\n", time_state->pause_time); - } else { - PrintError("Palacios timekeeping paused when already paused.\n"); - } + + time_state->exit_time = v3_get_host_time(time_state); + +#ifdef CONFIG_TIME_HIDE_EXIT_COST + // XXX should make the cost adjustment a runtime parameter + // so it can be set by the config file and/or tuned dynamically + v3_offset_time(info, -CONFIG_TIME_EXIT_COST_ADJUST); +#endif return 0; } +/* Called immediately prior to entry to the VM */ int -v3_restart_time( struct guest_info * info ) +v3_time_enter_vm( struct guest_info * info ) { struct vm_time * time_state = &(info->time_state); - if (time_state->pause_time) { - sint64_t pause_diff = (v3_get_host_time(time_state) - time_state->pause_time); + time_state->enter_time = v3_get_host_time(time_state); +#ifdef CONFIG_TIME_HIDE_VM_COST + if (time_state->exit_time) { + sint64_t pause_diff = time_state->enter_time - time_state->exit_time; time_state->guest_host_offset -= pause_diff; - time_state->pause_time = 0; -// PrintDebug("Resuming time after %lld cycles with offset %lld.\n", pause_diff, time_state->guest_host_offset); } else { - PrintError( "Palacios time keeping restarted when not paused."); + PrintError( "Time at which guest exited to VM not recorded!\n" ); } +#endif + time_state->exit_time = 0; return 0; } @@ -206,9 +209,6 @@ void v3_update_timers(struct guest_info * info) { time_state->last_update = v3_get_guest_time(time_state); cycles = time_state->last_update - old_time; - // PrintDebug("Updating timer for %lld elapsed cycles (pt=%llu, offset=%lld).\n", - // cycles, time_state->pause_time, time_state->guest_host_offset); - list_for_each_entry(tmp_timer, &(time_state->timers), timer_link) { tmp_timer->ops->update_timer(info, cycles, time_state->guest_cpu_freq, tmp_timer->private_data); } diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index f71df0a..ef0f614 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -662,11 +663,11 @@ int v3_vmx_enter(struct guest_info * info) { // Conditionally yield the CPU if the timeslice has expired v3_yield_cond(info); - /* If this guest is frequency-lagged behind host time, wait - * for the appropriate host time before resuming the guest. */ + // Perform any additional yielding needed for time adjustment v3_adjust_time(info); - // v3_print_guest_state(info); + // Update timer devices prior to entering VM. + v3_update_timers(info); // disable global interrupts for vm state transition v3_disable_ints(); @@ -688,7 +689,8 @@ int v3_vmx_enter(struct guest_info * info) { vmcs_write(VMCS_GUEST_CR3, guest_cr3); } - v3_update_timers(info); + // Perform last-minute time bookkeeping prior to entering the VM + v3_time_enter_vm(info); tsc_offset_high = (uint32_t)((v3_tsc_host_offset(&info->time_state) >> 32) & 0xffffffff); tsc_offset_low = (uint32_t)(v3_tsc_host_offset(&info->time_state) & 0xffffffff); @@ -713,6 +715,9 @@ int v3_vmx_enter(struct guest_info * info) { return -1; } + // Immediate exit from VM time bookkeeping + v3_time_exit_vm(info); + info->num_exits++; /* Update guest state */