VMX: enforce INVVPID checking
Escalate to use a wider context invalidation if the requested context
invalidation is not supported.
signed-off-by: Xin Li <xin.li@xxxxxxxxx>
diff -r 04e81a65d27e xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Thu Jun 10 22:39:52 2010 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Thu Jun 10 10:11:19 2010 -0700
@@ -213,6 +213,15 @@ static int vmx_init_vmcs_config(void)
!(_vmx_ept_vpid_cap & VMX_EPT_WALK_LENGTH_4_SUPPORTED) ||
!(_vmx_ept_vpid_cap & VMX_EPT_INVEPT_ALL_CONTEXT) )
_vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
+
+ /*
+ * the CPU must support INVVPID all context invalidation, because we
+ * will use it as final resort if other types are not supported.
+ *
+ * Or we just don't use VPID.
+ */
+ if ( !(_vmx_ept_vpid_cap & VMX_VPID_INVVPID_ALL_CONTEXT) )
+ _vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
}
if ( _vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT )
@@ -298,7 +307,7 @@ static int vmx_init_vmcs_config(void)
"VMEntry Control",
vmx_vmentry_control, _vmx_vmentry_control);
mismatch |= cap_check(
- "EPT Super Page Capability",
+ "EPT and VPID 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 04e81a65d27e xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Thu Jun 10 22:39:52 2010 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Thu Jun 10 10:11:19 2010 -0700
@@ -188,6 +188,12 @@ extern bool_t cpu_has_vmx_ins_outs_instr
#define VMX_EPT_INVEPT_INSTRUCTION 0x00100000
#define VMX_EPT_INVEPT_SINGLE_CONTEXT 0x02000000
#define VMX_EPT_INVEPT_ALL_CONTEXT 0x04000000
+
+#define VMX_VPID_INVVPID_INSTRUCTION 0x100000000ULL
+#define VMX_VPID_INVVPID_INDIVIDUAL_ADDR 0x10000000000ULL
+#define VMX_VPID_INVVPID_SINGLE_CONTEXT 0x20000000000ULL
+#define VMX_VPID_INVVPID_ALL_CONTEXT 0x40000000000ULL
+#define VMX_VPID_INVVPID_SINGLE_CONTEXT_RETAINING_GLOBAL 0x80000000000ULL
#define cpu_has_wbinvd_exiting \
(vmx_secondary_exec_control & SECONDARY_EXEC_WBINVD_EXITING)
diff -r 04e81a65d27e xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Thu Jun 10 22:39:52 2010 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Thu Jun 10 10:11:19 2010 -0700
@@ -202,6 +202,18 @@ extern u64 vmx_ept_vpid_cap;
#define INVEPT_SINGLE_CONTEXT 1
#define INVEPT_ALL_CONTEXT 2
+#define cpu_has_vmx_vpid_invvpid_individual_addr \
+ (vmx_ept_vpid_cap & VMX_VPID_INVVPID_INDIVIDUAL_ADDR)
+#define cpu_has_vmx_vpid_invvpid_single_context \
+ (vmx_ept_vpid_cap & VMX_VPID_INVVPID_SINGLE_CONTEXT)
+#define cpu_has_vmx_vpid_invvpid_single_context_retaining_global \
+ (vmx_ept_vpid_cap & VMX_VPID_INVVPID_SINGLE_CONTEXT_RETAINING_GLOBAL)
+
+#define INVVPID_INDIVIDUAL_ADDR 0
+#define INVVPID_SINGLE_CONTEXT 1
+#define INVVPID_ALL_CONTEXT 2
+#define INVVPID_SINGLE_CONTEXT_RETAINING_GLOBAL 3
+
static inline void __vmptrld(u64 addr)
{
asm volatile ( VMPTRLD_OPCODE
@@ -307,7 +319,7 @@ static inline void __invept(int type, u6
: "memory" );
}
-static inline void __invvpid(int ext, u16 vpid, u64 gva)
+static inline void __invvpid(int type, u16 vpid, u64 gva)
{
struct {
u64 vpid:16;
@@ -324,7 +336,7 @@ static inline void __invvpid(int ext, u1
" "__FIXUP_WORD" 1b,2b\n"
".previous"
:
- : "a" (&operand), "c" (ext)
+ : "a" (&operand), "c" (type)
: "memory" );
}
@@ -337,12 +349,31 @@ void ept_sync_domain(struct domain *d);
static inline void vpid_sync_vcpu_gva(struct vcpu *v, unsigned long gva)
{
- __invvpid(0, v->arch.hvm_vcpu.asid, (u64)gva);
+ int type = INVVPID_INDIVIDUAL_ADDR;
+
+ /*
+ * If individual address invalidation is not supported, we escalate to
+ * use single context invalidation.
+ */
+ if ( likely(cpu_has_vmx_vpid_invvpid_individual_addr) )
+ goto execute_invvpid;
+
+ type = INVVPID_SINGLE_CONTEXT;
+
+ /*
+ * If single context invalidation is not supported, we escalate to
+ * use all context invalidation.
+ */
+ if ( !cpu_has_vmx_vpid_invvpid_single_context )
+ type = INVVPID_ALL_CONTEXT;
+
+execute_invvpid:
+ __invvpid(type, v->arch.hvm_vcpu.asid, (u64)gva);
}
static inline void vpid_sync_all(void)
{
- __invvpid(2, 0, 0);
+ __invvpid(INVVPID_ALL_CONTEXT, 0, 0);
}
static inline void __vmxoff(void)
enforce_invvpid_checking.patch
Description: enforce_invvpid_checking.patch
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|