]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
x86emul: support WBNOINVD
authorJan Beulich <jbeulich@suse.com>
Tue, 3 Sep 2019 12:48:19 +0000 (14:48 +0200)
committerJan Beulich <jbeulich@suse.com>
Tue, 3 Sep 2019 12:48:19 +0000 (14:48 +0200)
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>
tools/libxl/libxl_cpuid.c
tools/misc/xen-cpuid.c
xen/arch/x86/hvm/emulate.c
xen/arch/x86/pv/emul-priv-op.c
xen/arch/x86/x86_emulate/x86_emulate.c
xen/arch/x86/x86_emulate/x86_emulate.h
xen/include/asm-x86/system.h
xen/include/public/arch-x86/cpufeatureset.h

index a8d07fac50c6fcfefd0b5ede60b84a635f78cc12..f1c6ce2076e150662c3135cfd65671001082a797 100644 (file)
@@ -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},
index b0db0525a9d001d472917a80e1bf62e745ca9291..be6a8d27a5d2c3640910be4d3ba960d1e9ce38aa 100644 (file)
@@ -146,6 +146,8 @@ static const char *const str_e8b[32] =
 {
     [ 0] = "clzero",
 
+    /* [ 8] */            [ 9] = "wbnoinvd",
+
     [12] = "ibpb",
 };
 
index e4b3f330a8a89b838dec7b53165447f1b30e07a9..b61faf704b4a315787cfa0c25e463fdf820be3d5 100644 (file)
@@ -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;
     }
index 305d5a3c2786ef625d905521ad6cccfdd92a09af..e24b84f46aa6d789fb0f2815b50a26d81be56545 100644 (file)
@@ -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();
 
index 8cc98677bf1b4285a2dddcf920f7163840bf0063..648a95d5ec0177d061c6be6605128a7698e84eb7 100644 (file)
@@ -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 )
index c54b803e97536a8430c138aa85f41d0bd873c401..6b22c536f5e4ab2e5bb3a884b52726d8feaad911 100644 (file)
@@ -182,6 +182,7 @@ enum x86emul_cache_op {
     x86emul_clwb,
     x86emul_invd,
     x86emul_wbinvd,
+    x86emul_wbnoinvd,
 };
 
 struct x86_emulate_state;
index 8f7e614d69accd65a9f178aa0c490fbdae509388..069f422f0dd5e13151dd00961f857dae02718d1c 100644 (file)
@@ -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) );
index e2c82a4554ebab47af0a04f2bb0ac65a8529d617..f2ec4701792244d5516445e183d36009ae6e1642 100644 (file)
@@ -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 */