diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-06-15 11:30:37 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-06-15 11:30:37 +0100 |
commit | e05e559c568156d82d4f11c60194a54c216ee8b6 (patch) | |
tree | 8ead6039a5c9fe2cdf7a5b1fffd9d6ab6359b897 | |
parent | fc88f23b65533b62b80af3d94b34c31424e1f3ff (diff) | |
download | xen-e05e559c568156d82d4f11c60194a54c216ee8b6.tar.gz xen-e05e559c568156d82d4f11c60194a54c216ee8b6.tar.bz2 xen-e05e559c568156d82d4f11c60194a54c216ee8b6.zip |
VMX: enforce EPT paging structure memory type and page-walk length check.
Also use a macro to get EPT walk length.
Signed-off-by: Xin Li <xin.li@intel.com>
xen-unstable changeset: 21591:def12332b19c
xen-unstable date: Thu Jun 10 11:18:02 2010 +0100
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmcs.c | 25 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmx.c | 8 | ||||
-rw-r--r-- | xen/arch/x86/mm/hap/p2m-ept.c | 10 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vmx/vmcs.h | 21 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vmx/vmx.h | 12 |
5 files changed, 53 insertions, 23 deletions
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 7fd9bf03e5..940dc4e79e 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -172,6 +172,26 @@ static void vmx_init_vmcs_config(void) min, opt, MSR_IA32_VMX_PROCBASED_CTLS2); } + /* 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); + + /* + * Additional sanity checking before using EPT: + * 1) the CPU we are running on must support EPT WB, as we will set + * ept paging structures memory type to WB; + * 2) the CPU must support the EPT page-walk length of 4 according to + * Intel SDM 25.2.2. + * + * Or we just don't use EPT. + */ + if ( !(_vmx_ept_vpid_cap & VMX_EPT_MEMORY_TYPE_WB) || + !(_vmx_ept_vpid_cap & VMX_EPT_WALK_LENGTH_4_SUPPORTED) ) + _vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; + } + if ( _vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT ) { /* @@ -190,11 +210,6 @@ static void vmx_init_vmcs_config(void) SECONDARY_EXEC_UNRESTRICTED_GUEST); } - /* 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 ) { diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 5fbf26c740..1472cb3f01 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -78,8 +78,12 @@ static int vmx_domain_initialise(struct domain *d) { int rc; - d->arch.hvm_domain.vmx.ept_control.etmt = EPT_DEFAULT_MT; - d->arch.hvm_domain.vmx.ept_control.gaw = EPT_DEFAULT_GAW; + /* Set the memory type used when accessing EPT paging structures. */ + d->arch.hvm_domain.vmx.ept_control.ept_mt = EPT_DEFAULT_MT; + + /* set EPT page-walk length, now it's actual walk length - 1, i.e. 3 */ + d->arch.hvm_domain.vmx.ept_control.ept_wl = 3; + d->arch.hvm_domain.vmx.ept_control.asr = pagetable_get_pfn(d->arch.phys_table); diff --git a/xen/arch/x86/mm/hap/p2m-ept.c b/xen/arch/x86/mm/hap/p2m-ept.c index 445d1380e2..89dddf8ad4 100644 --- a/xen/arch/x86/mm/hap/p2m-ept.c +++ b/xen/arch/x86/mm/hap/p2m-ept.c @@ -200,7 +200,7 @@ ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, ASSERT(table != NULL); - for ( i = EPT_DEFAULT_GAW; i > walk_level; i-- ) + for ( i = ept_get_wl(d); i > walk_level; i-- ) { ret = ept_next_level(d, 0, &table, &gfn_remainder, i * EPT_TABLE_ORDER); if ( !ret ) @@ -394,7 +394,7 @@ static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t, /* Should check if gfn obeys GAW here. */ - for ( i = EPT_DEFAULT_GAW; i > 0; i-- ) + for ( i = ept_get_wl(d); i > 0; i-- ) { retry: ret = ept_next_level(d, 1, &table, &gfn_remainder, @@ -484,7 +484,7 @@ static ept_entry_t ept_get_entry_content(struct domain *d, unsigned long gfn) if ( gfn > d->arch.p2m->max_mapped_pfn ) goto out; - for ( i = EPT_DEFAULT_GAW; i > 0; i-- ) + for ( i = ept_get_wl(d); i > 0; i-- ) { ret = ept_next_level(d, 1, &table, &gfn_remainder, i * EPT_TABLE_ORDER); @@ -522,7 +522,7 @@ void ept_walk_table(struct domain *d, unsigned long gfn) goto out; } - for ( i = EPT_DEFAULT_GAW; i >= 0; i-- ) + for ( i = ept_get_wl(d); i >= 0; i-- ) { ept_entry_t *ept_entry, *next; u32 index; @@ -647,8 +647,6 @@ static void ept_change_entry_type_global(struct domain *d, p2m_type_t ot, if ( pagetable_get_pfn(d->arch.phys_table) == 0 ) return; - BUG_ON(EPT_DEFAULT_GAW != 3); - l4e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); for (i4 = 0; i4 < EPT_PAGETABLE_ENTRIES; i4++ ) { diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index 85b37b3213..9b6699d2e0 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -54,23 +54,25 @@ struct vmx_msr_state { unsigned long msrs[VMX_MSR_COUNT]; }; -#define EPT_DEFAULT_MT 6 -#define EPT_DEFAULT_GAW 3 +#define EPT_DEFAULT_MT MTRR_TYPE_WRBACK struct vmx_domain { unsigned long apic_access_mfn; union { struct { - u64 etmt :3, - gaw :3, - rsvd :6, - asr :52; + u64 ept_mt :3, + ept_wl :3, + rsvd :6, + asr :52; }; u64 eptp; } ept_control; cpumask_t ept_synced; }; +#define ept_get_wl(d) \ + ((d)->arch.hvm_domain.vmx.ept_control.ept_wl) + struct arch_vmx_struct { /* Virtual address of VMCS. */ struct vmcs_struct *vmcs; @@ -176,8 +178,9 @@ 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_WALK_LENGTH_4_SUPPORTED 0x00000040 +#define VMX_EPT_MEMORY_TYPE_UC 0x00000100 +#define VMX_EPT_MEMORY_TYPE_WB 0x00004000 #define VMX_EPT_SUPERPAGE_2MB 0x00010000 #define cpu_has_wbinvd_exiting \ @@ -194,8 +197,6 @@ extern u64 vmx_ept_vpid_cap; (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 \ diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h index 038b6d29d6..073ba60454 100644 --- a/xen/include/asm-x86/hvm/vmx/vmx.h +++ b/xen/include/asm-x86/hvm/vmx/vmx.h @@ -184,6 +184,18 @@ void vmx_update_debug_state(struct vcpu *v); #define MODRM_EAX_07 ".byte 0x38\n" /* [EAX], with reg/opcode: /7 */ #define MODRM_EAX_ECX ".byte 0xc1\n" /* EAX, ECX */ +extern u64 vmx_ept_vpid_cap; + +#define cpu_has_vmx_ept_wl4_supported \ + (vmx_ept_vpid_cap & VMX_EPT_WALK_LENGTH_4_SUPPORTED) +#define cpu_has_vmx_ept_mt_uc \ + (vmx_ept_vpid_cap & VMX_EPT_MEMORY_TYPE_UC) +#define cpu_has_vmx_ept_mt_wb \ + (vmx_ept_vpid_cap & VMX_EPT_MEMORY_TYPE_WB) +#define cpu_has_vmx_ept_2mb \ + (vmx_ept_vpid_cap & VMX_EPT_SUPERPAGE_2MB) + + static inline void __vmptrld(u64 addr) { asm volatile ( VMPTRLD_OPCODE |