This insn differs from WRMSR solely in the lack of serialization. Hence
the code used there can simply be used here as well, plus a feature
check of course. As there's no other infrastructure needed beyond
permitting the insn for PV privileged-op emulation (in particular no
separate new VMEXIT) we can expose the insn to guests right away.

Signed-off-by: Jan Beulich <jbeul...@suse.com>

--- a/tools/tests/x86_emulator/predicates.c
+++ b/tools/tests/x86_emulator/predicates.c
@@ -341,6 +341,7 @@ static const struct {
     /*{ 0x01, 0xc3 }, { 2, 2 }, F, R }, vmresume */
     { { 0x01, 0xc4 }, { 2, 2 }, F, N }, /* vmxoff */
     { { 0x01, 0xc5 }, { 2, 2 }, F, N }, /* pconfig */
+    { { 0x01, 0xc6 }, { 2, 2 }, F, N }, /* wrmsrns */
     { { 0x01, 0xc8 }, { 2, 2 }, F, N }, /* monitor */
     { { 0x01, 0xc9 }, { 2, 2 }, F, N }, /* mwait */
     { { 0x01, 0xca }, { 2, 2 }, F, N }, /* clac */
--- a/tools/tests/x86_emulator/x86-emulate.c
+++ b/tools/tests/x86_emulator/x86-emulate.c
@@ -87,6 +87,7 @@ bool emul_test_init(void)
     cp.feat.avx512pf = cp.feat.avx512f;
     cp.feat.rdpid = true;
     cp.feat.lkgs = true;
+    cp.feat.wrmsrns = true;
     cp.extd.clzero = true;
 
     if ( cpu_has_xsave )
--- a/xen/arch/x86/pv/emul-priv-op.c
+++ b/xen/arch/x86/pv/emul-priv-op.c
@@ -1252,8 +1252,11 @@ static int cf_check validate(
     {
         unsigned int modrm_rm, modrm_reg;
 
-        if ( x86_insn_modrm(state, &modrm_rm, &modrm_reg) != 3 ||
-             (modrm_rm & 7) != 1 )
+        if ( x86_insn_modrm(state, &modrm_rm, &modrm_reg) != 3 )
+            break;
+        if ( (modrm_rm & 7) == 6 && !(modrm_reg & 7) ) /* wrmsrns, 
{rd,wr}msrlist */
+            return X86EMUL_OKAY;
+        if ( (modrm_rm & 7) != 1 )
             break;
         switch ( modrm_reg & 7 )
         {
--- a/xen/arch/x86/x86_emulate/0f01.c
+++ b/xen/arch/x86/x86_emulate/0f01.c
@@ -43,6 +43,20 @@ int x86emul_0f01(struct x86_emulate_stat
         struct segment_register sreg;
         uint64_t msr_val;
 
+    case 0xc6:
+        switch ( s->vex.pfx )
+        {
+        case vex_none: /* wrmsrns */
+            vcpu_must_have(wrmsrns);
+            generate_exception_if(!mode_ring0(), X86_EXC_GP, 0);
+            fail_if(!ops->write_msr);
+            rc = ops->write_msr(regs->ecx,
+                                ((uint64_t)regs->r(dx) << 32) | regs->eax,
+                                ctxt);
+            goto done;
+        }
+        generate_exception(X86_EXC_UD);
+
     case 0xca: /* clac */
     case 0xcb: /* stac */
         vcpu_must_have(smap);
--- a/xen/arch/x86/x86_emulate/private.h
+++ b/xen/arch/x86/x86_emulate/private.h
@@ -595,6 +595,7 @@ amd_like(const struct x86_emulate_ctxt *
 #define vcpu_has_avx_vnni()    (ctxt->cpuid->feat.avx_vnni)
 #define vcpu_has_avx512_bf16() (ctxt->cpuid->feat.avx512_bf16)
 #define vcpu_has_lkgs()        (ctxt->cpuid->feat.lkgs)
+#define vcpu_has_wrmsrns()     (ctxt->cpuid->feat.wrmsrns)
 
 #define vcpu_must_have(feat) \
     generate_exception_if(!vcpu_has_##feat(), X86_EXC_UD)
--- a/xen/include/public/arch-x86/cpufeatureset.h
+++ b/xen/include/public/arch-x86/cpufeatureset.h
@@ -283,7 +283,7 @@ XEN_CPUFEATURE(FSRS,         10*32+11) /
 XEN_CPUFEATURE(FSRCS,        10*32+12) /*A  Fast Short REP CMPSB/SCASB */
 XEN_CPUFEATURE(FRED,         10*32+17) /*   Flexible Return and Event Delivery 
*/
 XEN_CPUFEATURE(LKGS,         10*32+18) /*S  Load Kernel GS Base */
-XEN_CPUFEATURE(WRMSRNS,      10*32+19) /*   WRMSR Non-Serialising */
+XEN_CPUFEATURE(WRMSRNS,      10*32+19) /*A  WRMSR Non-Serialising */
 
 /* AMD-defined CPU features, CPUID level 0x80000021.eax, word 11 */
 XEN_CPUFEATURE(LFENCE_DISPATCH,    11*32+ 2) /*A  LFENCE always serializing */


Reply via email to