# 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
|