Linux kernel 4.6 and later make use of this instruction and crash if we
do not allow it. It flushes TLB mappings, but only on the caller's
logical CPU.
Signed-off-by: Jan Kiszka <
jan.k...@siemens.com>
---
Grmbl, just wanted to quickly test an "all fresh" box...
hypervisor/arch/x86/include/asm/processor.h | 1 +
hypervisor/arch/x86/include/asm/vmx.h | 1 +
hypervisor/arch/x86/vmx.c | 17 +++++++++--------
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/hypervisor/arch/x86/include/asm/processor.h b/hypervisor/arch/x86/include/asm/processor.h
index 85e41b3..6c50d27 100644
--- a/hypervisor/arch/x86/include/asm/processor.h
+++ b/hypervisor/arch/x86/include/asm/processor.h
@@ -28,6 +28,7 @@
#define X86_FEATURE_HYPERVISOR (1 << 31)
/* leaf 0x07, subleaf 0, EBX */
+#define X86_FEATURE_INVPCID (1 << 10)
#define X86_FEATURE_CAT (1 << 15)
/* leaf 0x80000001, ECX */
diff --git a/hypervisor/arch/x86/include/asm/vmx.h b/hypervisor/arch/x86/include/asm/vmx.h
index 775ef3f..66795c1 100644
--- a/hypervisor/arch/x86/include/asm/vmx.h
+++ b/hypervisor/arch/x86/include/asm/vmx.h
@@ -226,6 +226,7 @@ enum vmx_state { VMXOFF = 0, VMXON, VMCS_READY };
#define SECONDARY_EXEC_ENABLE_EPT (1UL << 1)
#define SECONDARY_EXEC_RDTSCP (1UL << 3)
#define SECONDARY_EXEC_UNRESTRICTED_GUEST (1UL << 7)
+#define SECONDARY_EXEC_INVPCID (1UL << 12)
#define VM_EXIT_HOST_ADDR_SPACE_SIZE (1UL << 9)
#define VM_EXIT_SAVE_IA32_PAT (1UL << 18)
diff --git a/hypervisor/arch/x86/vmx.c b/hypervisor/arch/x86/vmx.c
index f5cd8ca..3fe6e1d 100644
--- a/hypervisor/arch/x86/vmx.c
+++ b/hypervisor/arch/x86/vmx.c
@@ -80,7 +80,7 @@ static u8 __attribute__((aligned(PAGE_SIZE))) msr_bitmap[][0x2000/8] = {
};
static u8 __attribute__((aligned(PAGE_SIZE))) apic_access_page[PAGE_SIZE];
static struct paging ept_paging[EPT_PAGE_DIR_LEVELS];
-static u32 enable_rdtscp;
+static u32 secondary_exec_addon;
static unsigned long cr_maybe1[2], cr_required1[2];
static bool vmxon(struct per_cpu *cpu_data)
@@ -233,12 +233,13 @@ static int vmx_check_features(void)
!(vmx_proc_ctrl2 & SECONDARY_EXEC_UNRESTRICTED_GUEST))
return trace_error(-EIO);
- /* require RDTSCP if present in CPUID */
- if (cpuid_edx(0x80000001, 0) & X86_FEATURE_RDTSCP) {
- enable_rdtscp = SECONDARY_EXEC_RDTSCP;
- if (!(vmx_proc_ctrl2 & SECONDARY_EXEC_RDTSCP))
- return trace_error(-EIO);
- }
+ /* require RDTSCP and INVPCID if present in CPUID */
+ if (cpuid_edx(0x80000001, 0) & X86_FEATURE_RDTSCP)
+ secondary_exec_addon |= SECONDARY_EXEC_RDTSCP;
+ if (cpuid_ebx(0x07, 0) & X86_FEATURE_INVPCID)
+ secondary_exec_addon |= SECONDARY_EXEC_INVPCID;
+ if ((vmx_proc_ctrl2 & secondary_exec_addon) != secondary_exec_addon)
+ return trace_error(-EIO);
/* require PAT and EFER save/restore */
vmx_entry_ctrl = read_msr(MSR_IA32_VMX_ENTRY_CTLS) >> 32;
@@ -565,7 +566,7 @@ static bool vmcs_setup(struct per_cpu *cpu_data)
val = read_msr(MSR_IA32_VMX_PROCBASED_CTLS2);
val |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
SECONDARY_EXEC_ENABLE_EPT | SECONDARY_EXEC_UNRESTRICTED_GUEST |
- enable_rdtscp;
+ secondary_exec_addon;
ok &= vmcs_write32(SECONDARY_VM_EXEC_CONTROL, val);
ok &= vmcs_write64(APIC_ACCESS_ADDR,
--
2.1.4