[PATCH 1/2] x86emul: latch XCR0 early during decode

Jan Beulich <[email protected]>
Newsgroups org.xenproject.lists.xen-devel
Message-ID <[email protected]>
We'll need to consult it to decide whether to treat 0xD5 as a REX2
prefix, and whether to recognize extended EVEX encodings.

Utilize this in adjust_bnd() right away, but leave leveraging in
x86emul_get_fpu() for a separate change.

Signed-off-by: Jan Beulich <[email protected]>
---
While not directly relevant in this series, should we perhaps latch CR4
into the state structure as well right away, since we need to read it
here anyway?

--- a/xen/arch/x86/x86_emulate/decode.c
+++ b/xen/arch/x86/x86_emulate/decode.c
@@ -1036,6 +1036,24 @@ int x86emul_decode(struct x86_emulate_st
 #endif
     }
 
+    /* Latch XCR0, if available. */
+    if ( ops->read_cr && ops->read_xcr )
+    {
+        unsigned long cr4;
+
+        rc = ops->read_cr(4, &cr4, ctxt);
+        if ( rc == X86EMUL_OKAY && (cr4 & X86_CR4_OSXSAVE) &&
+             ops->read_xcr(0, &s->xcr0, ctxt) != X86EMUL_OKAY )
+            s->xcr0 = 0;
+
+        /*
+         * To ease consuming, strip 64-bit-only state right away for non-64-bit
+         * environments.
+         */
+        if ( !mode_64bit() )
+            s->xcr0 &= ~(X86_XCR0_TILE_CFG | X86_XCR0_TILE_DATA);
+    }
+
     /* Prefix bytes. */
     for ( ; ; )
     {
--- a/xen/arch/x86/x86_emulate/private.h
+++ b/xen/arch/x86/x86_emulate/private.h
@@ -334,6 +334,8 @@ struct x86_emulate_state {
 
     unsigned long ip;
 
+    uint64_t xcr0;
+
     struct stub_exn *stub_exn;
 
 #ifndef NDEBUG
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1234,17 +1234,17 @@ static bool is_branch_step(struct x86_em
     return debugctl & IA32_DEBUGCTLMSR_BTF;
 }
 
-static void adjust_bnd(struct x86_emulate_ctxt *ctxt,
+static void adjust_bnd(const struct x86_emulate_state *s,
+                       struct x86_emulate_ctxt *ctxt,
                        const struct x86_emulate_ops *ops, enum vex_pfx pfx)
 {
-    uint64_t xcr0, bndcfg;
+    uint64_t bndcfg;
     int rc;
 
     if ( pfx == vex_f2 || !cpu_has_mpx || !vcpu_has_mpx() )
         return;
 
-    if ( !ops->read_xcr || ops->read_xcr(0, &xcr0, ctxt) != X86EMUL_OKAY ||
-         !(xcr0 & X86_XCR0_BNDREGS) || !(xcr0 & X86_XCR0_BNDCSR) )
+    if ( !(s->xcr0 & X86_XCR0_BNDREGS) || !(s->xcr0 & X86_XCR0_BNDCSR) )
     {
         ASSERT(!ctxt->event_pending);
         return;
@@ -1952,7 +1952,7 @@ x86_emulate(
     case 0x70 ... 0x7f: /* jcc (short) */
         if ( test_cc(b, _regs.eflags) )
             jmp_rel((int32_t)src.val);
-        adjust_bnd(ctxt, ops, vex.pfx);
+        adjust_bnd(state, ctxt, ops, vex.pfx);
         break;
 
     case 0x80: case 0x81: case 0x82: case 0x83: /* Grp1 */
@@ -2363,7 +2363,7 @@ x86_emulate(
              (rc = ops->insn_fetch(dst.val, NULL, 0, ctxt)) )
             goto done;
         _regs.r(ip) = dst.val;
-        adjust_bnd(ctxt, ops, vex.pfx);
+        adjust_bnd(state, ctxt, ops, vex.pfx);
         break;
 
     case 0xc4: /* les */
@@ -2594,7 +2594,7 @@ x86_emulate(
         op_bytes = ((op_bytes == 4) && mode_64bit()) ? 8 : op_bytes;
         src.val = _regs.r(ip);
         jmp_rel(rel);
-        adjust_bnd(ctxt, ops, vex.pfx);
+        adjust_bnd(state, ctxt, ops, vex.pfx);
         goto push;
     }
 
@@ -2602,7 +2602,7 @@ x86_emulate(
     case 0xeb: /* jmp (short) */
         jmp_rel((int32_t)src.val);
         if ( !(b & 2) )
-            adjust_bnd(ctxt, ops, vex.pfx);
+            adjust_bnd(state, ctxt, ops, vex.pfx);
         break;
 
     case 0xea: /* jmp (far, absolute) */
@@ -2885,14 +2885,14 @@ x86_emulate(
                 goto done;
             _regs.r(ip) = src.val;
             src.val = dst.val;
-            adjust_bnd(ctxt, ops, vex.pfx);
+            adjust_bnd(state, ctxt, ops, vex.pfx);
             goto push;
         case 4: /* jmp (near) */
             if ( (rc = ops->insn_fetch(src.val, NULL, 0, ctxt)) )
                 goto done;
             _regs.r(ip) = src.val;
             dst.type = OP_NONE;
-            adjust_bnd(ctxt, ops, vex.pfx);
+            adjust_bnd(state, ctxt, ops, vex.pfx);
             break;
         case 3: /* call (far, absolute indirect) */
         case 5: /* jmp (far, absolute indirect) */
@@ -4981,7 +4981,7 @@ x86_emulate(
     case X86EMUL_OPC(0x0f, 0x80) ... X86EMUL_OPC(0x0f, 0x8f): /* jcc (near) */
         if ( test_cc(b, _regs.eflags) )
             jmp_rel((int32_t)src.val);
-        adjust_bnd(ctxt, ops, vex.pfx);
+        adjust_bnd(state, ctxt, ops, vex.pfx);
         break;
 
     case X86EMUL_OPC(0x0f, 0x90) ... X86EMUL_OPC(0x0f, 0x9f): /* setcc */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.