{"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},
{"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},
{
[ 0] = "clzero",
+ /* [ 8] */ [ 9] = "wbnoinvd",
+
[12] = "ibpb",
};
/* fall through */
case x86emul_invd:
case x86emul_wbinvd:
+ case x86emul_wbnoinvd:
alternative_vcall(hvm_funcs.wbinvd_intercept);
break;
}
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) )
* newer linux uses this in some start-of-day timing loops.
*/
;
+ else if ( op == x86emul_wbnoinvd /* && cpu_has_wbnoinvd */ )
+ wbnoinvd();
else
wbinvd();
#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)
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 )
x86emul_clwb,
x86emul_invd,
x86emul_wbinvd,
+ x86emul_wbnoinvd,
};
struct x86_emulate_state;
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) );
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 */
/* 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 */