aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-06-15 11:30:37 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-06-15 11:30:37 +0100
commite05e559c568156d82d4f11c60194a54c216ee8b6 (patch)
tree8ead6039a5c9fe2cdf7a5b1fffd9d6ab6359b897
parentfc88f23b65533b62b80af3d94b34c31424e1f3ff (diff)
downloadxen-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.c25
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c8
-rw-r--r--xen/arch/x86/mm/hap/p2m-ept.c10
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmcs.h21
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmx.h12
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