From: Patrick G. Bridges Date: Fri, 1 Oct 2010 21:36:23 +0000 (-0600) Subject: Time configuration parameters added. More time control code prototyped, X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=40e3dd3f222e2638dbdae0eadaf505e1f7a82ecc Time configuration parameters added. More time control code prototyped, but no robust control in place yet. --- diff --git a/Kconfig b/Kconfig index 1049045..9092a67 100644 --- a/Kconfig +++ b/Kconfig @@ -189,7 +189,6 @@ endmenu source "Kconfig.stdlibs" - menu "Virtual Paging" config SHADOW_PAGING @@ -217,6 +216,38 @@ config DEBUG_SHDW_PG_VTLB endmenu +menu "Time Management" + + +config TIME_VIRTUALIZE_TSC + bool "Virtualize guest TSC" + default n + help + Virtualize the processor time stamp counter in the guest, + generally increasing consistency between various time sources + but also potentially making guest time run slightly slower + than real time. + +config TIME_VIRTUAL_TSC_CONTROL + bool "Adjust virtual TSC towards real time when possible" + default y + depends on TIME_VIRTUALIZE_TSC + help + Enables control of TSC virtualization so that the TSC + attempts to catch up with real time when possible + +config TIME_MASK_OVERHEAD + bool "Hide virtualization overhead from guest timing" + default n + depends on TIME_VIRTUALIZE_TSC + help + Try to mask the overhead of virtualization from guests + by not including it in the time updates. Can dramatically + slow virtual time compared to real time if VIRTUAL_TSC_CONTROL + is not enabled. + +endmenu + menu "Symbiotic Functions" config SYMBIOTIC diff --git a/palacios/include/palacios/vmm_time.h b/palacios/include/palacios/vmm_time.h index 3f6bbac..0a25833 100644 --- a/palacios/include/palacios/vmm_time.h +++ b/palacios/include/palacios/vmm_time.h @@ -31,14 +31,10 @@ struct guest_info; struct vm_time { uint32_t cpu_freq; // in kHZ - // Last time (in guest time) the timers were updated - uint64_t last_update; - - // Cache value to help calculate the guest_tsc - uint64_t pause_time; - - // Offset of guest time from host time. - sint64_t host_offset; + uint64_t last_update; // Last time (in guest time) the timers were updated + uint64_t pause_time; // Cache value to help calculate the guest_tsc + sint64_t host_offset; // Offset of guest time from host time. + sint64_t offset_sum; // Sum of past and current host_offsets // Installed Timers uint_t num_timers; @@ -80,7 +76,8 @@ static inline uint64_t v3_get_host_time(struct vm_time *t) { } static inline uint64_t v3_get_guest_time(struct vm_time *t) { - return v3_get_host_time(t) + t->host_offset; + if (t->pause_time) return t->pause_time; + else return v3_get_host_time(t) + t->host_offset; } #endif // !__V3VEE__ diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 55e591e..dc2b660 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -471,14 +471,17 @@ int v3_svm_enter(struct guest_info * info) { v3_update_timers(info); v3_resume_time(info); + +#ifdef CONFIG_TIME_TSC_OFFSET guest_ctrl->TSC_OFFSET = info->time_state.host_offset; +#endif //V3_Print("Calling v3_svm_launch\n"); v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[info->cpu_id]); v3_pause_time(info); -#ifdef OPTION_TIME_MASK_OVERHEAD +#ifdef CONFIG_TIME_MASK_OVERHEAD v3_offset_time(info, -SVM_ENTRY_OVERHEAD); #endif diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index 7814acb..e7d5cfe 100644 --- a/palacios/src/palacios/vmm_time.c +++ b/palacios/src/palacios/vmm_time.c @@ -47,7 +47,8 @@ void v3_init_time(struct guest_info * info) { time_state->pause_time = 0; time_state->last_update = 0; time_state->host_offset = 0; - + time_state->offset_sum = 0; + INIT_LIST_HEAD(&(time_state->timers)); time_state->num_timers = 0; @@ -73,14 +74,43 @@ int v3_pause_time(struct guest_info * info) { return 0; } +/* Use a control-theoretic approach, specifically a PI control approach, + * to adjust host_offset towards 0. Overall control documentation in + * palacios/docs/time_control.tex Control parameters are P and I, + * broken into rational numbers + */ + +/* These numbers need to be actually determined by pole placement work. They're + * just blind guesses for now, which is a really bad idea. :) */ +#define P_NUM 1 +#define P_DENOM 2 +#define I_NUM 1 +#define I_DENOM 20 + +void adjust_time_offset(struct guest_info * info) { + /* Set point for control: Desired offset = 0; + * Error = host_offset - 0 = host_offset */ + + sint64_t adjust; + + /* Update the integral of the errror */ + info->time_state.offset_sum += info->time_state.host_offset; + adjust = (P_NUM * info->time_state.host_offset) / P_DENOM + + (I_NUM * info->time_state.offset_sum) / I_DENOM; + + /* We may want to constrain *adjust* because of + * resolution/accuracy constraints. Explore that later. */ + info->time_state.host_offset -= adjust; + return; +} + int v3_resume_time(struct guest_info * info) { uint64_t t = v3_get_host_time(&info->time_state); V3_ASSERT(info->time_state.pause_time != 0); info->time_state.host_offset = (sint64_t)info->time_state.pause_time - (sint64_t)t; #ifdef CONFIG_TIME_TSC_OFFSET_ADJUST - /* XXX Adjust host_offset towards zero based on resolution/accuracy - * constraints. */ + adjust_time_offset(info); #endif info->time_state.pause_time = 0; PrintDebug("Time resumed paused at guest time as %llu " diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index 9a2e859..16fc5cd 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -225,6 +225,9 @@ static int init_vmcs_bios(struct guest_info * info, struct vmx_data * vmx_state) vmx_state->pri_proc_ctrls.invlpg_exit = 1; vmx_state->pri_proc_ctrls.use_msr_bitmap = 1; vmx_state->pri_proc_ctrls.pause_exit = 1; +#ifdef CONFIG_TIME_TSC_OFFSET + vmx_state->pri_proc_ctrls.tsc_offset = 1; +#endif vmx_ret |= check_vmcs_write(VMCS_IO_BITMAP_A_ADDR, (addr_t)V3_PAddr(info->vm_info->io_map.arch_data)); vmx_ret |= check_vmcs_write(VMCS_IO_BITMAP_B_ADDR, @@ -696,7 +699,7 @@ int v3_vmx_enter(struct guest_info * info) { } v3_pause_time(info); -#ifdef OPTION_TIME_MASK_OVERHEAD +#ifdef CONFIG_TIME_MASK_OVERHEAD v3_offset_time(info, -VMX_ENTRY_OVERHEAD); #endif