debuggers.hg

changeset 19942:c1541cc7e985

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@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jul 07 14:06:35 2009 +0100 (2009-07-07)
parents 65a68b980cc3
children 7ce4f3675c9b
files xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/vmx/vmcs.h xen/include/asm-x86/perfc_defn.h
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/svm.c	Tue Jul 07 14:01:30 2009 +0100
     1.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Tue Jul 07 14:06:35 2009 +0100
     1.3 @@ -1504,8 +1504,9 @@ asmlinkage void svm_vmexit_handler(struc
     1.4           * The guest is running a contended spinlock and we've detected it.
     1.5           * Do something useful, like reschedule the guest
     1.6           */
     1.7 -       do_sched_op_compat(SCHEDOP_yield, 0);
     1.8 -       break;
     1.9 +        perfc_incr(pauseloop_exits);
    1.10 +        do_sched_op_compat(SCHEDOP_yield, 0);
    1.11 +        break;
    1.12  
    1.13      default:
    1.14      exit_and_crash:
     2.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c	Tue Jul 07 14:01:30 2009 +0100
     2.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c	Tue Jul 07 14:06:35 2009 +0100
     2.3 @@ -44,6 +44,20 @@ boolean_param("vpid", opt_vpid_enabled);
     2.4  static int opt_unrestricted_guest_enabled = 1;
     2.5  boolean_param("unrestricted_guest", opt_unrestricted_guest_enabled);
     2.6  
     2.7 +/*
     2.8 + * These two parameters are used to config the controls for Pause-Loop Exiting:
     2.9 + * ple_gap:    upper bound on the amount of time between two successive
    2.10 + *             executions of PAUSE in a loop.
    2.11 + * ple_window: upper bound on the amount of time a guest is allowed to execute
    2.12 + *             in a PAUSE loop.
    2.13 + * Time is measured based on a counter that runs at the same rate as the TSC,
    2.14 + * refer SDM volume 3b section 21.6.13 & 22.1.3.
    2.15 + */
    2.16 +static unsigned int ple_gap = 41;
    2.17 +integer_param("ple_gap", ple_gap);
    2.18 +static unsigned int ple_window = 4096;
    2.19 +integer_param("ple_window", ple_window);
    2.20 +
    2.21  /* Dynamic (run-time adjusted) execution control flags. */
    2.22  u32 vmx_pin_based_exec_control __read_mostly;
    2.23  u32 vmx_cpu_based_exec_control __read_mostly;
    2.24 @@ -140,7 +154,8 @@ static void vmx_init_vmcs_config(void)
    2.25          min = 0;
    2.26          opt = (SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
    2.27                 SECONDARY_EXEC_WBINVD_EXITING |
    2.28 -               SECONDARY_EXEC_ENABLE_EPT);
    2.29 +               SECONDARY_EXEC_ENABLE_EPT |
    2.30 +               SECONDARY_EXEC_PAUSE_LOOP_EXITING);
    2.31          if ( opt_vpid_enabled )
    2.32              opt |= SECONDARY_EXEC_ENABLE_VPID;
    2.33          if ( opt_unrestricted_guest_enabled )
    2.34 @@ -168,6 +183,13 @@ static void vmx_init_vmcs_config(void)
    2.35                    SECONDARY_EXEC_UNRESTRICTED_GUEST);
    2.36      }
    2.37  
    2.38 +    if ( (_vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING) &&
    2.39 +          ple_gap == 0 )
    2.40 +    {
    2.41 +        printk("Disable Pause-Loop Exiting.\n");
    2.42 +        _vmx_secondary_exec_control &= ~ SECONDARY_EXEC_PAUSE_LOOP_EXITING;
    2.43 +    }
    2.44 +
    2.45  #if defined(__i386__)
    2.46      /* If we can't virtualise APIC accesses, the TPR shadow is pointless. */
    2.47      if ( !(_vmx_secondary_exec_control &
    2.48 @@ -556,6 +578,12 @@ static int construct_vmcs(struct vcpu *v
    2.49      __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control);
    2.50      __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control);
    2.51  
    2.52 +    if ( cpu_has_vmx_ple )
    2.53 +    {
    2.54 +        __vmwrite(PLE_GAP, ple_gap);
    2.55 +        __vmwrite(PLE_WINDOW, ple_window);
    2.56 +    }
    2.57 +
    2.58      if ( cpu_has_vmx_secondary_exec_control )
    2.59          __vmwrite(SECONDARY_VM_EXEC_CONTROL,
    2.60                    v->arch.hvm_vmx.secondary_exec_control);
     3.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Tue Jul 07 14:01:30 2009 +0100
     3.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Tue Jul 07 14:06:35 2009 +0100
     3.3 @@ -2609,13 +2609,16 @@ asmlinkage void vmx_vmexit_handler(struc
     3.4      }
     3.5  
     3.6      case EXIT_REASON_MONITOR_TRAP_FLAG:
     3.7 -    {
     3.8          v->arch.hvm_vmx.exec_control &= ~CPU_BASED_MONITOR_TRAP_FLAG;
     3.9          __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control);
    3.10          if ( v->domain->debugger_attached && v->arch.hvm_vcpu.single_step )
    3.11              domain_pause_for_debugger();
    3.12          break;
    3.13 -    }
    3.14 +
    3.15 +    case EXIT_REASON_PAUSE_INSTRUCTION:
    3.16 +        perfc_incr(pauseloop_exits);
    3.17 +        do_sched_op_compat(SCHEDOP_yield, 0);
    3.18 +        break;
    3.19  
    3.20      default:
    3.21      exit_and_crash:
     4.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h	Tue Jul 07 14:01:30 2009 +0100
     4.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h	Tue Jul 07 14:06:35 2009 +0100
     4.3 @@ -171,6 +171,7 @@ extern u32 vmx_vmentry_control;
     4.4  #define SECONDARY_EXEC_ENABLE_VPID              0x00000020
     4.5  #define SECONDARY_EXEC_WBINVD_EXITING           0x00000040
     4.6  #define SECONDARY_EXEC_UNRESTRICTED_GUEST       0x00000080
     4.7 +#define SECONDARY_EXEC_PAUSE_LOOP_EXITING       0x00000400
     4.8  extern u32 vmx_secondary_exec_control;
     4.9  
    4.10  extern bool_t cpu_has_vmx_ins_outs_instr_info;
    4.11 @@ -200,6 +201,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr
    4.12  #define vmx_unrestricted_guest(v)               \
    4.13      ((v)->arch.hvm_vmx.secondary_exec_control & \
    4.14       SECONDARY_EXEC_UNRESTRICTED_GUEST)
    4.15 +#define cpu_has_vmx_ple \
    4.16 +    (vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING)
    4.17  
    4.18  /* GUEST_INTERRUPTIBILITY_INFO flags. */
    4.19  #define VMX_INTR_SHADOW_STI             0x00000001
    4.20 @@ -279,6 +282,8 @@ enum vmcs_field {
    4.21      VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
    4.22      TPR_THRESHOLD                   = 0x0000401c,
    4.23      SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
    4.24 +    PLE_GAP                         = 0x00004020,
    4.25 +    PLE_WINDOW                      = 0x00004022,
    4.26      VM_INSTRUCTION_ERROR            = 0x00004400,
    4.27      VM_EXIT_REASON                  = 0x00004402,
    4.28      VM_EXIT_INTR_INFO               = 0x00004404,
     5.1 --- a/xen/include/asm-x86/perfc_defn.h	Tue Jul 07 14:01:30 2009 +0100
     5.2 +++ b/xen/include/asm-x86/perfc_defn.h	Tue Jul 07 14:06:35 2009 +0100
     5.3 @@ -130,4 +130,6 @@ PERFCOUNTER(mshv_wrmsr_eoi,             
     5.4  PERFCOUNTER(realmode_emulations, "realmode instructions emulated")
     5.5  PERFCOUNTER(realmode_exits,      "vmexits from realmode")
     5.6  
     5.7 +PERFCOUNTER(pauseloop_exits, "vmexits from Pause-Loop Detection")
     5.8 +
     5.9  /*#endif*/ /* __XEN_PERFC_DEFN_H__ */