]> xenbits.xensource.com Git - people/vhanquez/xen.git/commitdiff
VMX: add EPT 2M super page feature detection
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 4 Jun 2010 09:20:33 +0000 (10:20 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 4 Jun 2010 09:20:33 +0000 (10:20 +0100)
Signed-off-by: Xin Li <xin.li@intel.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/mm/p2m.c
xen/include/asm-x86/hvm/hvm.h
xen/include/asm-x86/hvm/vmx/vmcs.h
xen/include/asm-x86/msr-index.h

index 3cee3349baa232b135ef0cc1d1573ed05e5aa877..58a68ee1c0c3c9d53d37c36f5809e4cf73a3a41d 100644 (file)
@@ -906,6 +906,8 @@ void start_svm(struct cpuinfo_x86 *c)
 
     svm_function_table.hap_supported = cpu_has_svm_npt;
 
+    svm_function_table.hap_capabilities = HVM_HAP_SUPERPAGE_2MB;
+
     hvm_enable(&svm_function_table);
 }
 
index b27d9eaec4dc3ed5369fcf4cfedd3156d534ee80..6cd6e9eb7c840b47d9da452d355c47d6348e6875 100644 (file)
@@ -47,6 +47,7 @@ u32 vmx_cpu_based_exec_control __read_mostly;
 u32 vmx_secondary_exec_control __read_mostly;
 u32 vmx_vmexit_control __read_mostly;
 u32 vmx_vmentry_control __read_mostly;
+u64 vmx_ept_vpid_cap __read_mostly;
 bool_t cpu_has_vmx_ins_outs_instr_info __read_mostly;
 
 static DEFINE_PER_CPU(struct vmcs_struct *, host_vmcs);
@@ -72,6 +73,9 @@ static void __init vmx_display_features(void)
 
     if ( !printed )
         printk(" - none\n");
+
+    if ( cpu_has_vmx_ept_2mb )
+        printk("EPT supports 2MB super page.\n");
 }
 
 static u32 adjust_vmx_controls(u32 ctl_min, u32 ctl_opt, u32 msr)
@@ -95,6 +99,7 @@ static void vmx_init_vmcs_config(void)
     u32 _vmx_pin_based_exec_control;
     u32 _vmx_cpu_based_exec_control;
     u32 _vmx_secondary_exec_control = 0;
+    u64 _vmx_ept_vpid_cap = 0;
     u32 _vmx_vmexit_control;
     u32 _vmx_vmentry_control;
 
@@ -159,6 +164,11 @@ static void vmx_init_vmcs_config(void)
             _vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
     }
 
+    /* The IA32_VMX_EPT_VPID_CAP MSR exists only when EPT or VPID available */
+    if ( _vmx_secondary_exec_control &
+         (SECONDARY_EXEC_ENABLE_EPT | SECONDARY_EXEC_ENABLE_VPID) )
+        rdmsrl(MSR_IA32_VMX_EPT_VPID_CAP, _vmx_ept_vpid_cap);
+
 #if defined(__i386__)
     /* If we can't virtualise APIC accesses, the TPR shadow is pointless. */
     if ( !(_vmx_secondary_exec_control &
@@ -186,6 +196,7 @@ static void vmx_init_vmcs_config(void)
         vmx_pin_based_exec_control = _vmx_pin_based_exec_control;
         vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control;
         vmx_secondary_exec_control = _vmx_secondary_exec_control;
+        vmx_ept_vpid_cap           = _vmx_ept_vpid_cap;
         vmx_vmexit_control         = _vmx_vmexit_control;
         vmx_vmentry_control        = _vmx_vmentry_control;
         cpu_has_vmx_ins_outs_instr_info = !!(vmx_basic_msr_high & (1U<<22));
@@ -198,6 +209,7 @@ static void vmx_init_vmcs_config(void)
         BUG_ON(vmx_pin_based_exec_control != _vmx_pin_based_exec_control);
         BUG_ON(vmx_cpu_based_exec_control != _vmx_cpu_based_exec_control);
         BUG_ON(vmx_secondary_exec_control != _vmx_secondary_exec_control);
+        BUG_ON(vmx_ept_vpid_cap != _vmx_ept_vpid_cap);
         BUG_ON(vmx_vmexit_control != _vmx_vmexit_control);
         BUG_ON(vmx_vmentry_control != _vmx_vmentry_control);
         BUG_ON(cpu_has_vmx_ins_outs_instr_info !=
index 24cce89805fb5d3649334042724d0b8cfda5875c..54249b8d9597ec827c602ae2ea2a051442a63edf 100644 (file)
@@ -1419,6 +1419,10 @@ void start_vmx(void)
     {
         printk("VMX: EPT is available.\n");
         vmx_function_table.hap_supported = 1;
+        vmx_function_table.hap_capabilities = 0;
+
+        if ( cpu_has_vmx_ept_2mb )
+            vmx_function_table.hap_capabilities |= HVM_HAP_SUPERPAGE_2MB;
     }
 
     if ( cpu_has_vmx_vpid )
index a4aac5f0aa21a8cf96efbab544ce12168e3a2edc..8793546d695de773bdcc60a01a5ec83259217fc3 100644 (file)
@@ -1504,7 +1504,9 @@ int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
 
     while ( todo )
     {
-        order = (((gfn | mfn_x(mfn) | todo) & (SUPERPAGE_PAGES - 1)) == 0) ? 9 : 0;
+        order = ((((gfn | mfn_x(mfn) | todo) & (SUPERPAGE_PAGES - 1)) == 0) &&
+                 hvm_hap_has_2mb(d)) ? 9 : 0;
+
         rc = d->arch.p2m->set_entry(d, gfn, mfn, order, p2mt);
         gfn += 1ul << order;
         if ( mfn_x(mfn) != INVALID_MFN )
index 3855f53f7a5a6c9357973554b9319c4685a57146..ee2071302a1578f684ac75e22958ce6525e30480 100644 (file)
@@ -55,6 +55,12 @@ enum hvm_intblk {
 #define HVM_INTR_SHADOW_SMI    0x00000004
 #define HVM_INTR_SHADOW_NMI    0x00000008
 
+/*
+ * HAP super page capabilities:
+ * bit0: if 2MB super page is allowed?
+ */
+#define HVM_HAP_SUPERPAGE_2MB   0x00000001
+
 /*
  * The hardware virtual machine (HVM) interface abstracts away from the
  * x86/x86_64 CPU virtualization assist specifics. Currently this interface
@@ -66,6 +72,9 @@ struct hvm_function_table {
     /* Support Hardware-Assisted Paging? */
     int hap_supported;
 
+    /* Indicate HAP capabilities. */
+    int hap_capabilities;
+
     /*
      * Initialise/destroy HVM domain/vcpu resources
      */
@@ -163,6 +172,9 @@ u64 hvm_get_guest_time(struct vcpu *v);
 #define hvm_nx_enabled(v) \
     (!!((v)->arch.hvm_vcpu.guest_efer & EFER_NX))
 
+#define hvm_hap_has_2mb(d) \
+    (hvm_funcs.hap_capabilities & HVM_HAP_SUPERPAGE_2MB)
+
 #ifdef __x86_64__
 #define hvm_long_mode_enabled(v) \
     ((v)->arch.hvm_vcpu.guest_efer & EFER_LMA)
index 80640e0d5a0575d268acfeb3e021eff768f28486..64cde9a320f58c28e2f09bdcbd1f2e07360ec5c3 100644 (file)
@@ -174,6 +174,10 @@ extern u32 vmx_secondary_exec_control;
 
 extern bool_t cpu_has_vmx_ins_outs_instr_info;
 
+extern u64 vmx_ept_vpid_cap;
+
+#define VMX_EPT_SUPERPAGE_2MB                   0x00010000
+
 #define cpu_has_wbinvd_exiting \
     (vmx_secondary_exec_control & SECONDARY_EXEC_WBINVD_EXITING)
 #define cpu_has_vmx_virtualize_apic_accesses \
@@ -188,6 +192,8 @@ extern bool_t cpu_has_vmx_ins_outs_instr_info;
     (vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
 #define cpu_has_vmx_ept \
     (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT)
+#define cpu_has_vmx_ept_2mb \
+    (vmx_ept_vpid_cap & VMX_EPT_SUPERPAGE_2MB)
 #define cpu_has_vmx_vpid \
     (vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID)
 #define cpu_has_monitor_trap_flag \
index ab3b2a62fb4ba76fc1720d8064bafe55d7c1aba5..51a4c24479b3132caafac928cafdf98f047e8917 100644 (file)
 #define MSR_IA32_VMX_CR4_FIXED0                 0x488
 #define MSR_IA32_VMX_CR4_FIXED1                 0x489
 #define MSR_IA32_VMX_PROCBASED_CTLS2            0x48b
+#define MSR_IA32_VMX_EPT_VPID_CAP               0x48c
 #define MSR_IA32_VMX_TRUE_PINBASED_CTLS         0x48d
 #define MSR_IA32_VMX_TRUE_PROCBASED_CTLS        0x48e
 #define MSR_IA32_VMX_TRUE_EXIT_CTLS             0x48f