mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
x86emul: support WBNOINVD
Rev 037 of Intel's ISA extensions document does not state intercept behavior for the insn (I've been unofficially told that the distinction is going to be by exit qualification, as I would have assumed considering that this way it's sufficiently transparent to unaware software, as using WBINVD in place of WBNOINVD is always correct, just less efficient). Similarly AMD's PM volume 2 version 3.31 only states that both use the same VMEXIT, but not how to distinugish them (other than by decoding the insn). Therefore in the HVM case for now it'll be backed by the same ->wbinvd_intercept() handlers. Use this occasion and also add the two missing table entries for CLDEMOTE, which doesn't require any further changes to make work. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Paul Durrant <paul.durrant@citrix.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
c0536ed315
commit
ad3abc47dd
8 files changed
+22
-3
No files matched your search
@@ -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},
|
||||
|
||||
@@ -146,6 +146,8 @@ static const char *const str_e8b[32] =
|
||||
{
|
||||
[ 0] = "clzero",
|
||||
|
||||
/* [ 8] */ [ 9] = "wbnoinvd",
|
||||
|
||||
[12] = "ibpb",
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -182,6 +182,7 @@ enum x86emul_cache_op {
|
||||
x86emul_clwb,
|
||||
x86emul_invd,
|
||||
x86emul_wbinvd,
|
||||
x86emul_wbnoinvd,
|
||||
};
|
||||
|
||||
struct x86_emulate_state;
|
||||
|
||||
@@ -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) );
|
||||
|
||||
@@ -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 */
|
||||
|
||||