Li, Xin
2010-May-31 14:26 UTC
[Xen-devel] [PATCH] does EPT capabilities detection strictly according to Intel SDM
VMX: does EPT capabilities detection strictly according to Intel SDM. Signed-off-by: Xin Li <xin.li@intel.com> diff -r 96917cf25bf3 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Fri May 28 10:54:07 2010 +0100 +++ b/xen/arch/x86/hvm/svm/svm.c Sun May 30 19:10:21 2010 -0700 @@ -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 96917cf25bf3 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Fri May 28 10:54:07 2010 +0100 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Sun May 30 19:10:21 2010 -0700 @@ -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 96917cf25bf3 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Fri May 28 10:54:07 2010 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Sun May 30 19:10:21 2010 -0700 @@ -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 96917cf25bf3 xen/arch/x86/mm/hap/p2m-ept.c --- a/xen/arch/x86/mm/hap/p2m-ept.c Fri May 28 10:54:07 2010 +0100 +++ b/xen/arch/x86/mm/hap/p2m-ept.c Sun May 30 19:10:21 2010 -0700 @@ -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 96917cf25bf3 xen/arch/x86/mm/p2m.c --- a/xen/arch/x86/mm/p2m.c Fri May 28 10:54:07 2010 +0100 +++ b/xen/arch/x86/mm/p2m.c Sun May 30 19:10:21 2010 -0700 @@ -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 96917cf25bf3 xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Fri May 28 10:54:07 2010 +0100 +++ b/xen/include/asm-x86/hvm/hvm.h Sun May 30 19:10:21 2010 -0700 @@ -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; /* @@ -175,6 +180,11 @@ int hvm_girq_dest_2_vcpu_id(struct domai (hvm_paging_enabled(v) && ((v)->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PAE)) #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) \ diff -r 96917cf25bf3 xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Fri May 28 10:54:07 2010 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Sun May 30 19:10:21 2010 -0700 @@ -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; +extern u64 vmx_ept_vpid_cap; -#define VMX_EPT_SUPER_PAGE_2M 0x00010000 -#define VMX_EPT_SUPER_PAGE_1G 0x00020000 +#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-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel