[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] VMX: does EPT capabilities detection strictly according to Intel SDM.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1275398759 -3600
# Node ID 267ecb2ee5bfab4f25b3b5b5cb99f5b1a72fa87c
# Parent  188e3da0aa2746f2f0cecce9f099a03554755125
VMX: does EPT capabilities detection strictly according to Intel SDM.

Signed-off-by: Xin Li <xin.li@xxxxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c         |    4 +--
 xen/arch/x86/hvm/vmx/vmcs.c        |   39 +++++++++++++++----------------------
 xen/arch/x86/hvm/vmx/vmx.c         |   10 +++++++--
 xen/arch/x86/mm/hap/p2m-ept.c      |   11 +++++++---
 xen/arch/x86/mm/p2m.c              |    7 ++----
 xen/include/asm-x86/hvm/hvm.h      |   20 ++++++++++++++----
 xen/include/asm-x86/hvm/vmx/vmcs.h |   14 +++++++------
 7 files changed, 60 insertions(+), 45 deletions(-)

diff -r 188e3da0aa27 -r 267ecb2ee5bf xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Tue Jun 01 13:57:44 2010 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Tue Jun 01 14:25:59 2010 +0100
@@ -935,9 +935,9 @@ struct hvm_function_table * __init start
                          cpuid_edx(0x8000000A) : 0);
 
     svm_function_table.hap_supported = cpu_has_svm_npt;
-    svm_function_table.hap_superpage_level =
+    svm_function_table.hap_capabilities = HVM_HAP_SUPERPAGE_2MB |
         ((CONFIG_PAGING_LEVELS == 4) && (cpuid_edx(0x80000001) & 0x04000000)) ?
-            2 : 1;
+            HVM_HAP_SUPERPAGE_1GB : 0;
 
     return &svm_function_table;
 }
diff -r 188e3da0aa27 -r 267ecb2ee5bf xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Tue Jun 01 13:57:44 2010 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Tue Jun 01 14:25:59 2010 +0100
@@ -64,7 +64,7 @@ u32 vmx_secondary_exec_control __read_mo
 u32 vmx_secondary_exec_control __read_mostly;
 u32 vmx_vmexit_control __read_mostly;
 u32 vmx_vmentry_control __read_mostly;
-u8 vmx_ept_super_page_level_limit __read_mostly;
+u64 vmx_ept_vpid_cap __read_mostly;
 bool_t cpu_has_vmx_ins_outs_instr_info __read_mostly;
 
 static DEFINE_PER_CPU_READ_MOSTLY(struct vmcs_struct *, host_vmcs);
@@ -92,10 +92,10 @@ static void __init vmx_display_features(
     if ( !printed )
         printk(" - none\n");
 
-    if ( vmx_ept_super_page_level_limit )
-        printk("EPT supports %s super page.\n",
-               (vmx_ept_super_page_level_limit == 2) ? "1G" :
-               ((vmx_ept_super_page_level_limit == 1) ? "2M" : "4K"));
+    if ( cpu_has_vmx_ept_1gb )
+        printk("EPT supports 1GB super page.\n");
+    if ( cpu_has_vmx_ept_2mb )
+        printk("EPT supports 2MB super page.\n");
 }
 
 static u32 adjust_vmx_controls(
@@ -132,7 +132,7 @@ static int vmx_init_vmcs_config(void)
     u32 _vmx_pin_based_exec_control;
     u32 _vmx_cpu_based_exec_control;
     u32 _vmx_secondary_exec_control = 0;
-    u8 ept_super_page_level_limit = 0;
+    u64 _vmx_ept_vpid_cap = 0;
     u32 _vmx_vmexit_control;
     u32 _vmx_vmentry_control;
     bool_t mismatch = 0;
@@ -208,16 +208,12 @@ static int vmx_init_vmcs_config(void)
             _vmx_secondary_exec_control &=
                 ~(SECONDARY_EXEC_ENABLE_EPT |
                   SECONDARY_EXEC_UNRESTRICTED_GUEST);
-        if ( _vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT )
-        {
-            uint64_t cap;
-            rdmsrl(MSR_IA32_VMX_EPT_VPID_CAP, cap);
-            if ( cap & VMX_EPT_SUPER_PAGE_1G )
-                ept_super_page_level_limit = 2;
-            else if ( cap & VMX_EPT_SUPER_PAGE_2M )
-                ept_super_page_level_limit = 1;
-        }
-    }
+    }
+
+    /* 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 ( (_vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING) &&
           ple_gap == 0 )
@@ -256,7 +252,7 @@ static int 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_super_page_level_limit = ept_super_page_level_limit;
+        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));
@@ -283,12 +279,9 @@ static int vmx_init_vmcs_config(void)
         mismatch |= cap_check(
             "VMEntry Control",
             vmx_vmentry_control, _vmx_vmentry_control);
-        if ( vmx_ept_super_page_level_limit > ept_super_page_level_limit )
-        {
-            printk("EPT Super Page Limit: saw %u expected >= %u\n",
-                   ept_super_page_level_limit, vmx_ept_super_page_level_limit);
-            mismatch = 1;
-        }
+        mismatch |= cap_check(
+            "EPT Super Page Capability",
+            vmx_ept_vpid_cap, _vmx_ept_vpid_cap);
         if ( cpu_has_vmx_ins_outs_instr_info !=
              !!(vmx_basic_msr_high & (1U<<22)) )
         {
diff -r 188e3da0aa27 -r 267ecb2ee5bf xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Tue Jun 01 13:57:44 2010 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Tue Jun 01 14:25:59 2010 +0100
@@ -1432,10 +1432,16 @@ struct hvm_function_table * __init start
     if ( cpu_has_vmx_ept )
     {
         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_ept_1gb )
+            vmx_function_table.hap_capabilities |= HVM_HAP_SUPERPAGE_1GB;
+
         setup_ept_dump();
     }
-    
-    vmx_function_table.hap_superpage_level = vmx_ept_super_page_level_limit;
 
     setup_vmcs_dump();
 
diff -r 188e3da0aa27 -r 267ecb2ee5bf xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c     Tue Jun 01 13:57:44 2010 +0100
+++ b/xen/arch/x86/mm/hap/p2m-ept.c     Tue Jun 01 14:25:59 2010 +0100
@@ -308,9 +308,14 @@ ept_set_entry(struct domain *d, unsigned
         int num = order / EPT_TABLE_ORDER;
         int level;
         ept_entry_t *split_ept_entry;
-    
-        if ( num >= cpu_vmx_ept_super_page_level_limit )
-            num = cpu_vmx_ept_super_page_level_limit;
+
+        if ( (num >= 2) && hvm_hap_has_1gb(d) )
+            num = 2;
+        else if ( (num >= 1) && hvm_hap_has_2mb(d) )
+            num = 1;
+        else
+            num = 0;
+
         for ( level = split_level; level > num ; level-- )
         {
             rv = ept_split_large_page(d, &table, &index, gfn, level);
diff -r 188e3da0aa27 -r 267ecb2ee5bf xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c     Tue Jun 01 13:57:44 2010 +0100
+++ b/xen/arch/x86/mm/p2m.c     Tue Jun 01 14:25:59 2010 +0100
@@ -1758,10 +1758,9 @@ int set_p2m_entry(struct domain *d, unsi
     {
         if ( is_hvm_domain(d) && paging_mode_hap(d) )
             order = ( (((gfn | mfn_x(mfn) | todo) & ((1ul << 18) - 1)) == 0) &&
-                      (hvm_funcs.hap_superpage_level == 2) &&
-                      opt_hap_1gb ) ? 18 :
-                ((((gfn | mfn_x(mfn) | todo) & ((1ul << 9) - 1)) == 0) &&
-                      (hvm_funcs.hap_superpage_level >= 1)) ? 9 : 0;
+                      hvm_hap_has_1gb(d) && opt_hap_1gb ) ? 18 :
+                      ((((gfn | mfn_x(mfn) | todo) & ((1ul << 9) - 1)) == 0) &&
+                      hvm_hap_has_2mb(d)) ? 9 : 0;
         else
             order = 0;
 
diff -r 188e3da0aa27 -r 267ecb2ee5bf xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Tue Jun 01 13:57:44 2010 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h     Tue Jun 01 14:25:59 2010 +0100
@@ -62,6 +62,14 @@ enum hvm_intblk {
 #define HVM_INTR_SHADOW_NMI    0x00000008
 
 /*
+ * HAP super page capabilities:
+ * bit0: if 2MB super page is allowed?
+ * bit1: if 1GB super page is allowed?
+ */
+#define HVM_HAP_SUPERPAGE_2MB   0x00000001
+#define HVM_HAP_SUPERPAGE_1GB   0x00000002
+
+/*
  * The hardware virtual machine (HVM) interface abstracts away from the
  * x86/x86_64 CPU virtualization assist specifics. Currently this interface
  * supports Intel's VT-x and AMD's SVM extensions.
@@ -72,11 +80,8 @@ struct hvm_function_table {
     /* Support Hardware-Assisted Paging? */
     int hap_supported;
 
-    /*
-     * Indicate HAP super page level.
-     * 0 -- 4KB, 1 -- 2MB, 2 -- 1GB.
-     */
-    int hap_superpage_level;
+    /* Indicate HAP capabilities. */
+    int hap_capabilities;
 
 
     /*
@@ -176,6 +181,11 @@ int hvm_girq_dest_2_vcpu_id(struct domai
 #define hvm_nx_enabled(v) \
     (!!((v)->arch.hvm_vcpu.guest_efer & EFER_NX))
 
+#define hvm_hap_has_1gb(d) \
+    (hvm_funcs.hap_capabilities & HVM_HAP_SUPERPAGE_1GB)
+#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)
diff -r 188e3da0aa27 -r 267ecb2ee5bf xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Tue Jun 01 13:57:44 2010 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Tue Jun 01 14:25:59 2010 +0100
@@ -174,10 +174,10 @@ extern u32 vmx_secondary_exec_control;
 
 extern bool_t cpu_has_vmx_ins_outs_instr_info;
 
-extern u8 vmx_ept_super_page_level_limit;
-
-#define VMX_EPT_SUPER_PAGE_2M              0x00010000
-#define VMX_EPT_SUPER_PAGE_1G              0x00020000
+extern u64 vmx_ept_vpid_cap;
+
+#define VMX_EPT_SUPERPAGE_2MB                   0x00010000
+#define VMX_EPT_SUPERPAGE_1GB                   0x00020000
 
 #define cpu_has_wbinvd_exiting \
     (vmx_secondary_exec_control & SECONDARY_EXEC_WBINVD_EXITING)
@@ -193,6 +193,10 @@ extern u8 vmx_ept_super_page_level_limit
     (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_1gb \
+    (vmx_ept_vpid_cap & VMX_EPT_SUPERPAGE_1GB)
+#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 \
@@ -206,8 +210,6 @@ extern u8 vmx_ept_super_page_level_limit
      SECONDARY_EXEC_UNRESTRICTED_GUEST)
 #define cpu_has_vmx_ple \
     (vmx_secondary_exec_control & SECONDARY_EXEC_PAUSE_LOOP_EXITING)
-#define cpu_vmx_ept_super_page_level_limit  \
-    vmx_ept_super_page_level_limit
 
 /* GUEST_INTERRUPTIBILITY_INFO flags. */
 #define VMX_INTR_SHADOW_STI             0x00000001

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.