X86: implement PCID/INVPCID for hvm
This patch handle PCID/INVPCID for hvm:
For hap hvm, we enable PCID/INVPCID, since no need to intercept INVPCID, and we
just set INVPCID non-root behavior as running natively;
For shadow hvm, we disable PCID/INVPCID, otherwise we need to emulate INVPCID at
vmm by setting INVPCID non-root behavior as vmexit.
Signed-off-by: Liu, Jinsong <jinsong.liu@intel.com>
diff -r c61a5ba8c972 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Tue Nov 22 02:47:51 2011 +0800
+++ b/xen/arch/x86/hvm/hvm.c Tue Nov 22 16:15:19 2011 +0800
@@ -1549,6 +1549,13 @@ int hvm_set_cr0(unsigned long value)
}
else if ( !(value & X86_CR0_PG) && (old_value & X86_CR0_PG)
)
{
+ if ( hvm_pcid_enabled(v) )
+ {
+ HVM_DBG_LOG(DBG_LEVEL_1, "Guest attempts to clear CR0.PG
"
+ "while CR4.PCIDE=1");
+ goto gpf;
+ }
+
/* When CR0.PG is cleared, LMA is cleared immediately. */
if ( hvm_long_mode_enabled(v) )
{
@@ -1663,12 +1670,26 @@ int hvm_set_cr4(unsigned long value)
}
old_cr = v->arch.hvm_vcpu.guest_cr[4];
+
+ if ( (value & X86_CR4_PCIDE) && !(old_cr & X86_CR4_PCIDE)
&&
+ (!hvm_long_mode_enabled(v) || (v->arch.hvm_vcpu.guest_cr[3] &
0xfff)) )
+ {
+ HVM_DBG_LOG(DBG_LEVEL_1, "Guest attempts to change CR4.PCIDE from
"
+ "0 to 1 while either EFER.LMA=0 or
CR3[11:0]!=000H");
+ goto gpf;
+ }
+
v->arch.hvm_vcpu.guest_cr[4] = value;
hvm_update_guest_cr(v, 4);
- /* Modifying CR4.{PSE,PAE,PGE,SMEP} invalidates all TLB entries. */
- if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE |
- X86_CR4_PAE | X86_CR4_SMEP) ) {
+ /*
+ * Modifying CR4.{PSE,PAE,PGE,SMEP}, or clearing CR4.PCIDE
+ * invalidate all TLB entries.
+ */
+ if ( ((old_cr ^ value) &
+ (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE | X86_CR4_SMEP)) ||
+ (!(value & X86_CR4_PCIDE) && (old_cr &
X86_CR4_PCIDE)) )
+ {
if ( !nestedhvm_vmswitch_in_progress(v) &&
nestedhvm_vcpu_in_guestmode(v) )
paging_update_nestedmode(v);
else
@@ -2409,10 +2430,18 @@ void hvm_cpuid(unsigned int input, unsig
if ( xsave_enabled(v) )
*ecx |= (v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE) ?
cpufeat_mask(X86_FEATURE_OSXSAVE) : 0;
+
+ /* Not expose PCID to non-hap hvm */
+ if ( !hap_enabled(d) )
+ *ecx &= ~cpufeat_mask(X86_FEATURE_PCID);
break;
case 0x7:
if ( (count == 0) && !cpu_has_smep )
*ebx &= ~cpufeat_mask(X86_FEATURE_SMEP);
+
+ /* Not expose INVPCID to non-hap hvm */
+ if ( (count == 0) && !hap_enabled(d) )
+ *ebx &= ~cpufeat_mask(X86_FEATURE_INVPCID);
break;
case 0xb:
/* Fix the x2APIC identifier. */
diff -r c61a5ba8c972 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Tue Nov 22 02:47:51 2011 +0800
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Tue Nov 22 16:15:19 2011 +0800
@@ -183,7 +183,8 @@ static int vmx_init_vmcs_config(void)
SECONDARY_EXEC_WBINVD_EXITING |
SECONDARY_EXEC_ENABLE_EPT |
SECONDARY_EXEC_ENABLE_RDTSCP |
- SECONDARY_EXEC_PAUSE_LOOP_EXITING);
+ SECONDARY_EXEC_PAUSE_LOOP_EXITING |
+ SECONDARY_EXEC_ENABLE_INVPCID);
if ( opt_vpid_enabled )
opt |= SECONDARY_EXEC_ENABLE_VPID;
if ( opt_unrestricted_guest_enabled )
@@ -726,7 +727,8 @@ static int construct_vmcs(struct vcpu *v
{
v->arch.hvm_vmx.secondary_exec_control &=
~(SECONDARY_EXEC_ENABLE_EPT |
- SECONDARY_EXEC_UNRESTRICTED_GUEST);
+ SECONDARY_EXEC_UNRESTRICTED_GUEST |
+ SECONDARY_EXEC_ENABLE_INVPCID);
vmexit_ctl &= ~(VM_EXIT_SAVE_GUEST_PAT |
VM_EXIT_LOAD_HOST_PAT);
vmentry_ctl &= ~VM_ENTRY_LOAD_GUEST_PAT;
diff -r c61a5ba8c972 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Tue Nov 22 02:47:51 2011 +0800
+++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Nov 22 16:15:19 2011 +0800
@@ -1004,7 +1004,7 @@ static void vmx_load_pdptrs(struct vcpu
if ( !hvm_pae_enabled(v) || (v->arch.hvm_vcpu.guest_efer & EFER_LMA)
)
return;
- if ( cr3 & 0x1fUL )
+ if ( (cr3 & 0x1fUL) && !hvm_pcid_enabled(v) )
goto crash;
mfn = mfn_x(gfn_to_mfn(v->domain, cr3 >> PAGE_SHIFT, &p2mt));
@@ -2661,6 +2661,7 @@ asmlinkage void vmx_vmexit_handler(struc
case EXIT_REASON_ACCESS_GDTR_OR_IDTR:
case EXIT_REASON_ACCESS_LDTR_OR_TR:
case EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED:
+ case EXIT_REASON_INVPCID:
/* fall through */
default:
exit_and_crash:
diff -r c61a5ba8c972 xen/include/asm-x86/cpufeature.h
--- a/xen/include/asm-x86/cpufeature.h Tue Nov 22 02:47:51 2011 +0800
+++ b/xen/include/asm-x86/cpufeature.h Tue Nov 22 16:15:19 2011 +0800
@@ -224,6 +224,8 @@
#define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC)
+#define cpu_has_pcid boot_cpu_has(X86_FEATURE_PCID)
+
#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
#define cpu_has_lwp boot_cpu_has(X86_FEATURE_LWP)
diff -r c61a5ba8c972 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h Tue Nov 22 02:47:51 2011 +0800
+++ b/xen/include/asm-x86/hvm/hvm.h Tue Nov 22 16:15:19 2011 +0800
@@ -212,6 +212,8 @@ int hvm_girq_dest_2_vcpu_id(struct domai
(!!((v)->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PG))
#define hvm_wp_enabled(v) \
(!!((v)->arch.hvm_vcpu.guest_cr[0] & X86_CR0_WP))
+#define hvm_pcid_enabled(v) \
+ (!!((v)->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PCIDE))
#define hvm_pae_enabled(v) \
(hvm_paging_enabled(v) && ((v)->arch.hvm_vcpu.guest_cr[4] &
X86_CR4_PAE))
#define hvm_smep_enabled(v) \
@@ -334,6 +336,7 @@ static inline int hvm_do_pmu_interrupt(s
(cpu_has_fsgsbase ? X86_CR4_FSGSBASE : 0) | \
((nestedhvm_enabled((_v)->domain) && cpu_has_vmx)\
? X86_CR4_VMXE : 0) | \
+ (cpu_has_pcid ? X86_CR4_PCIDE : 0) | \
(xsave_enabled(_v) ? X86_CR4_OSXSAVE : 0))))
/* These exceptions must always be intercepted. */
diff -r c61a5ba8c972 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Nov 22 02:47:51 2011 +0800
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Nov 22 16:15:19 2011 +0800
@@ -184,6 +184,7 @@ extern u32 vmx_vmentry_control;
#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
#define SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400
+#define SECONDARY_EXEC_ENABLE_INVPCID 0x00001000
extern u32 vmx_secondary_exec_control;
extern bool_t cpu_has_vmx_ins_outs_instr_info;
diff -r c61a5ba8c972 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Tue Nov 22 02:47:51 2011 +0800
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Tue Nov 22 16:15:19 2011 +0800
@@ -129,6 +129,7 @@ void vmx_update_cpu_exec_control(struct
#define EXIT_REASON_INVVPID 53
#define EXIT_REASON_WBINVD 54
#define EXIT_REASON_XSETBV 55
+#define EXIT_REASON_INVPCID 58
/*
* Interruption-information format
diff -r c61a5ba8c972 xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h Tue Nov 22 02:47:51 2011 +0800
+++ b/xen/include/asm-x86/processor.h Tue Nov 22 16:15:19 2011 +0800
@@ -84,6 +84,7 @@
#define X86_CR4_VMXE 0x2000 /* enable VMX */
#define X86_CR4_SMXE 0x4000 /* enable SMX */
#define X86_CR4_FSGSBASE 0x10000 /* enable {rd,wr}{fs,gs}base */
+#define X86_CR4_PCIDE 0x20000 /* enable PCID */
#define X86_CR4_OSXSAVE 0x40000 /* enable XSAVE/XRSTOR */
#define X86_CR4_SMEP 0x100000/* enable SMEP */
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel