[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vmx: Add support for Pause-Loop Exiting
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1246971995 -3600 # Node ID c1541cc7e9855a9bc4cb420b2e599a6c605441f1 # Parent 65a68b980cc3027b150a52c51e9a46fef8bb8a8d vmx: Add support for Pause-Loop Exiting New NHM processors will support Pause-Loop Exiting by adding 2 VM-execution control fields: PLE_Gap - upper bound on the amount of time between two successive executions of PAUSE in a loop. PLE_Window - upper bound on the amount of time a guest is allowed to execute in a PAUSE loop If the time, between this execution of PAUSE and previous one, exceeds the PLE_Gap, processor consider this PAUSE belongs to a new loop. Otherwise, processor determins the the total execution time of this loop(since 1st PAUSE in this loop), and triggers a VM exit if total time exceeds the PLE_Window. * Refer SDM volume 3b section 21.6.13 & 22.1.3. Pause-Loop Exiting can be used to detect Lock-Holder Preemption, where one VP is sched-out after hold a spinlock, then other VPs for same lock are sched-in to waste the CPU time. Our tests indicate that most spinlocks are held for less than 2^12 cycles. Performance tests show that with 2X LP over-commitment we can get +2% perf improvement for kernel build(Even more perf gain with more LPs). Signed-off-by: Zhai Edwin <edwin.zhai@xxxxxxxxx> --- xen/arch/x86/hvm/svm/svm.c | 5 +++-- xen/arch/x86/hvm/vmx/vmcs.c | 30 +++++++++++++++++++++++++++++- xen/arch/x86/hvm/vmx/vmx.c | 7 +++++-- xen/include/asm-x86/hvm/vmx/vmcs.h | 5 +++++ xen/include/asm-x86/perfc_defn.h | 2 ++ 5 files changed, 44 insertions(+), 5 deletions(-) diff -r 65a68b980cc3 -r c1541cc7e985 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Tue Jul 07 14:01:30 2009 +0100 +++ b/xen/arch/x86/hvm/svm/svm.c Tue Jul 07 14:06:35 2009 +0100 @@ -1504,8 +1504,9 @@ asmlinkage void svm_vmexit_handler(struc * The guest is running a contended spinlock and we've detected it. * Do something useful, like reschedule the guest */ - do_sched_op_compat(SCHEDOP_yield, 0); - break; + perfc_incr(pauseloop_exits); + do_sched_op_compat(SCHEDOP_yield, 0); + break; default: exit_and_crash: diff -r 65a68b980cc3 -r c1541cc7e985 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Tue Jul 07 14:01:30 2009 +0100 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Tue Jul 07 14:06:35 2009 +0100 @@ -44,6 +44,20 @@ static int opt_unrestricted_guest_enable static int opt_unrestricted_guest_enabled = 1; boolean_param("unrestricted_guest", opt_unrestricted_guest_enabled); +/* + * These two parameters are used to config the controls for Pause-Loop Exiting: + * ple_gap: upper bound on the amount of time between two successive + * executions of PAUSE in a loop. + * ple_window: upper bound on the amount of time a guest is allowed to execute + * in a PAUSE loop. + * Time is measured based on a counter that runs at the same rate as the TSC, + * refer SDM volume 3b section 21.6.13 & 22.1.3. + */ +static unsigned int ple_gap = 41; +integer_param("ple_gap", ple_gap); +static unsigned int ple_window = 4096; +integer_param("ple_window", ple_window); + /* Dynamic (run-time adjusted) execution control flags. */ u32 vmx_pin_based_exec_control __read_mostly; u32 vmx_cpu_based_exec_control __read_mostly; @@ -140,7 +154,8 @@ static void vmx_init_vmcs_config(void) min = 0; opt = (SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | SECONDARY_EXEC_WBINVD_EXITING | - SECONDARY_EXEC_ENABLE_EPT); + SECONDARY_EXEC_ENABLE_EPT | + SECONDARY_EXEC_PAUSE_LOOP_EXITING); if ( opt_vpid_enabled ) opt |= SECONDARY_EXEC_ENABLE_VPID; if ( opt_unrestricted_guest_enabled ) @@ -166,6 +181,13 @@ static void vmx_init_vmcs_config(void) _vmx_secondary_exec_control &= ~(SECONDARY_EXEC_ENABLE_EPT | SECONDARY_EXEC_UNRESTRICTED_GUEST); + } + + if ( (_vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING) && + ple_gap == 0 ) + { + printk("Disable Pause-Loop Exiting.\n"); + _vmx_secondary_exec_control &= ~ SECONDARY_EXEC_PAUSE_LOOP_EXITING; } #if defined(__i386__) @@ -555,6 +577,12 @@ static int construct_vmcs(struct vcpu *v __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); + + if ( cpu_has_vmx_ple ) + { + __vmwrite(PLE_GAP, ple_gap); + __vmwrite(PLE_WINDOW, ple_window); + } if ( cpu_has_vmx_secondary_exec_control ) __vmwrite(SECONDARY_VM_EXEC_CONTROL, diff -r 65a68b980cc3 -r c1541cc7e985 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Tue Jul 07 14:01:30 2009 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Jul 07 14:06:35 2009 +0100 @@ -2609,13 +2609,16 @@ asmlinkage void vmx_vmexit_handler(struc } case EXIT_REASON_MONITOR_TRAP_FLAG: - { v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG; __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); if ( v->domain->debugger_attached && v->arch.hvm_vcpu.single_step ) domain_pause_for_debugger(); break; - } + + case EXIT_REASON_PAUSE_INSTRUCTION: + perfc_incr(pauseloop_exits); + do_sched_op_compat(SCHEDOP_yield, 0); + break; default: exit_and_crash: diff -r 65a68b980cc3 -r c1541cc7e985 xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Jul 07 14:01:30 2009 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Jul 07 14:06:35 2009 +0100 @@ -171,6 +171,7 @@ extern u32 vmx_vmentry_control; #define SECONDARY_EXEC_ENABLE_VPID 0x00000020 #define SECONDARY_EXEC_WBINVD_EXITING 0x00000040 #define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080 +#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400 extern u32 vmx_secondary_exec_control; extern bool_t cpu_has_vmx_ins_outs_instr_info; @@ -200,6 +201,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr #define vmx_unrestricted_guest(v) \ ((v)->arch.hvm_vmx.secondary_exec_control & \ SECONDARY_EXEC_UNRESTRICTED_GUEST) +#define cpu_has_vmx_ple \ + (vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING) /* GUEST_INTERRUPTIBILITY_INFO flags. */ #define VMX_INTR_SHADOW_STI 0x00000001 @@ -279,6 +282,8 @@ enum vmcs_field { VM_ENTRY_INSTRUCTION_LEN = 0x0000401a, TPR_THRESHOLD = 0x0000401c, SECONDARY_VM_EXEC_CONTROL = 0x0000401e, + PLE_GAP = 0x00004020, + PLE_WINDOW = 0x00004022, VM_INSTRUCTION_ERROR = 0x00004400, VM_EXIT_REASON = 0x00004402, VM_EXIT_INTR_INFO = 0x00004404, diff -r 65a68b980cc3 -r c1541cc7e985 xen/include/asm-x86/perfc_defn.h --- a/xen/include/asm-x86/perfc_defn.h Tue Jul 07 14:01:30 2009 +0100 +++ b/xen/include/asm-x86/perfc_defn.h Tue Jul 07 14:06:35 2009 +0100 @@ -130,4 +130,6 @@ PERFCOUNTER(realmode_emulations, "realmo PERFCOUNTER(realmode_emulations, "realmode instructions emulated") PERFCOUNTER(realmode_exits, "vmexits from realmode") +PERFCOUNTER(pauseloop_exits, "vmexits from Pause-Loop Detection") + /*#endif*/ /* __XEN_PERFC_DEFN_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |