diff --git a/tools/libxl/libxl_cpuid.c b/tools/libxl/libxl_cpuid.c index a8d07fac50..f1c6ce2076 100644 --- a/tools/libxl/libxl_cpuid.c +++ b/tools/libxl/libxl_cpuid.c @@ -208,6 +208,7 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str) {"avx512-bitalg",0x00000007, 0, CPUID_REG_ECX, 12, 1}, {"avx512-vpopcntdq",0x00000007,0,CPUID_REG_ECX, 14, 1}, {"rdpid", 0x00000007, 0, CPUID_REG_ECX, 22, 1}, + {"cldemote", 0x00000007, 0, CPUID_REG_ECX, 25, 1}, {"avx512-4vnniw",0x00000007, 0, CPUID_REG_EDX, 2, 1}, {"avx512-4fmaps",0x00000007, 0, CPUID_REG_EDX, 3, 1}, @@ -256,6 +257,7 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str) {"invtsc", 0x80000007, NA, CPUID_REG_EDX, 8, 1}, + {"wbnoinvd", 0x80000008, NA, CPUID_REG_EBX, 9, 1}, {"ibpb", 0x80000008, NA, CPUID_REG_EBX, 12, 1}, {"nc", 0x80000008, NA, CPUID_REG_ECX, 0, 8}, {"apicidsize", 0x80000008, NA, CPUID_REG_ECX, 12, 4}, diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c index b0db0525a9..be6a8d27a5 100644 --- a/tools/misc/xen-cpuid.c +++ b/tools/misc/xen-cpuid.c @@ -146,6 +146,8 @@ static const char *const str_e8b[32] = { [ 0] = "clzero", + /* [ 8] */ [ 9] = "wbnoinvd", + [12] = "ibpb", }; diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index e4b3f330a8..b61faf704b 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -2212,6 +2212,7 @@ static int hvmemul_cache_op( /* fall through */ case x86emul_invd: case x86emul_wbinvd: + case x86emul_wbnoinvd: alternative_vcall(hvm_funcs.wbinvd_intercept); break; } diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c index 305d5a3c27..e24b84f46a 100644 --- a/xen/arch/x86/pv/emul-priv-op.c +++ b/xen/arch/x86/pv/emul-priv-op.c @@ -1120,7 +1120,7 @@ static int write_msr(unsigned int reg, uint64_t val, static int cache_op(enum x86emul_cache_op op, enum x86_segment seg, unsigned long offset, struct x86_emulate_ctxt *ctxt) { - ASSERT(op == x86emul_wbinvd); + ASSERT(op == x86emul_wbinvd || op == x86emul_wbnoinvd); /* Ignore the instruction if unprivileged. */ if ( !cache_flush_permitted(current->domain) ) @@ -1129,6 +1129,8 @@ static int cache_op(enum x86emul_cache_op op, enum x86_segment seg, * newer linux uses this in some start-of-day timing loops. */ ; + else if ( op == x86emul_wbnoinvd /* && cpu_has_wbnoinvd */ ) + wbnoinvd(); else wbinvd(); diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index 8cc98677bf..648a95d5ec 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -1869,6 +1869,7 @@ in_protmode( #define vcpu_has_fma4() (ctxt->cpuid->extd.fma4) #define vcpu_has_tbm() (ctxt->cpuid->extd.tbm) #define vcpu_has_clzero() (ctxt->cpuid->extd.clzero) +#define vcpu_has_wbnoinvd() (ctxt->cpuid->extd.wbnoinvd) #define vcpu_has_bmi1() (ctxt->cpuid->feat.bmi1) #define vcpu_has_hle() (ctxt->cpuid->feat.hle) @@ -5931,10 +5932,13 @@ x86_emulate( break; case X86EMUL_OPC(0x0f, 0x08): /* invd */ - case X86EMUL_OPC(0x0f, 0x09): /* wbinvd */ + case X86EMUL_OPC(0x0f, 0x09): /* wbinvd / wbnoinvd */ generate_exception_if(!mode_ring0(), EXC_GP, 0); fail_if(!ops->cache_op); - if ( (rc = ops->cache_op(b == 0x09 ? x86emul_wbinvd + if ( (rc = ops->cache_op(b == 0x09 ? !repe_prefix() || + !vcpu_has_wbnoinvd() + ? x86emul_wbinvd + : x86emul_wbnoinvd : x86emul_invd, x86_seg_none, 0, ctxt)) != X86EMUL_OKAY ) diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h b/xen/arch/x86/x86_emulate/x86_emulate.h index c54b803e97..6b22c536f5 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.h +++ b/xen/arch/x86/x86_emulate/x86_emulate.h @@ -182,6 +182,7 @@ enum x86emul_cache_op { x86emul_clwb, x86emul_invd, x86emul_wbinvd, + x86emul_wbnoinvd, }; struct x86_emulate_state; diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h index 8f7e614d69..069f422f0d 100644 --- a/xen/include/asm-x86/system.h +++ b/xen/include/asm-x86/system.h @@ -16,6 +16,11 @@ static inline void wbinvd(void) asm volatile ( "wbinvd" ::: "memory" ); } +static inline void wbnoinvd(void) +{ + asm volatile ( "repe; wbinvd" : : : "memory" ); +} + static inline void clflush(const void *p) { asm volatile ( "clflush %0" :: "m" (*(const char *)p) ); diff --git a/xen/include/public/arch-x86/cpufeatureset.h b/xen/include/public/arch-x86/cpufeatureset.h index e2c82a4554..f2ec470179 100644 --- a/xen/include/public/arch-x86/cpufeatureset.h +++ b/xen/include/public/arch-x86/cpufeatureset.h @@ -236,6 +236,7 @@ XEN_CPUFEATURE(AVX512_VNNI, 6*32+11) /*A Vector Neural Network Instrs */ XEN_CPUFEATURE(AVX512_BITALG, 6*32+12) /*A Support for VPOPCNT[B,W] and VPSHUFBITQMB */ XEN_CPUFEATURE(AVX512_VPOPCNTDQ, 6*32+14) /*A POPCNT for vectors of DW/QW */ XEN_CPUFEATURE(RDPID, 6*32+22) /*A RDPID instruction */ +XEN_CPUFEATURE(CLDEMOTE, 6*32+25) /*A CLDEMOTE instruction */ /* AMD-defined CPU features, CPUID level 0x80000007.edx, word 7 */ XEN_CPUFEATURE(ITSC, 7*32+ 8) /* Invariant TSC */ @@ -243,6 +244,7 @@ XEN_CPUFEATURE(EFRO, 7*32+10) /* APERF/MPERF Read Only interface */ /* AMD-defined CPU features, CPUID level 0x80000008.ebx, word 8 */ XEN_CPUFEATURE(CLZERO, 8*32+ 0) /*A CLZERO instruction */ +XEN_CPUFEATURE(WBNOINVD, 8*32+ 9) /* WBNOINVD instruction */ XEN_CPUFEATURE(IBPB, 8*32+12) /*A IBPB support only (no IBRS, used by AMD) */ /* Intel-defined CPU features, CPUID level 0x00000007:0.edx, word 9 */