[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 3/3] x86emul: consolidate CR4 handling



Now that there's an almost unconditional CR4 read right at the beginning
of x86_emulate(), centralize its reading there and use result and value
everywhere else without further invoking the hook.

Subsequently we may want to consider having the callers provide
whichever value they deem appropriate in their contexts, to avoid
invoking the hook altogether for this purpose.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1163,10 +1163,19 @@ do {
     ops->write_segment(x86_seg_cs, cs, ctxt);                           \
 })
 
+#define check_cr4() ({                      \
+    if ( unlikely(cr4_rc != X86EMUL_OKAY) ) \
+    {                                       \
+        rc = cr4_rc;                        \
+        goto done;                          \
+    }                                       \
+})
+
 static int _get_fpu(
     enum x86_emulate_fpu_type type,
     struct x86_emulate_ctxt *ctxt,
-    const struct x86_emulate_ops *ops)
+    const struct x86_emulate_ops *ops,
+    unsigned long cr4, int cr4_rc)
 {
     uint64_t xcr0;
     int rc;
@@ -1208,11 +1217,7 @@ static int _get_fpu(
         fail_if(!ops->read_cr);
         if ( type >= X86EMUL_FPU_xmm )
         {
-            unsigned long cr4;
-
-            rc = ops->read_cr(4, &cr4, ctxt);
-            if ( rc != X86EMUL_OKAY )
-                return rc;
+            check_cr4();
             generate_exception_if(!(cr4 & ((type == X86EMUL_FPU_xmm)
                                            ? X86_CR4_OSFXSR : 
X86_CR4_OSXSAVE)),
                                   EXC_UD);
@@ -1243,7 +1248,7 @@ static int _get_fpu(
 
 #define get_fpu(type)                                           \
 do {                                                            \
-    rc = _get_fpu(fpu_type = (type), ctxt, ops);                \
+    rc = _get_fpu(fpu_type = (type), ctxt, ops, cr4, cr4_rc);   \
     if ( rc ) goto done;                                        \
 } while (0)
 
@@ -1603,13 +1608,9 @@ _mode_iopl(
     _iopl;                                      \
 })
 #define mode_vif() ({                                        \
-    cr4 = 0;                                                 \
-    if ( ops->read_cr && get_cpl(ctxt, ops) == 3 )           \
-    {                                                        \
-        rc = ops->read_cr(4, &cr4, ctxt);                    \
-        if ( rc != X86EMUL_OKAY ) goto done;                 \
-    }                                                        \
-    !!(cr4 & (_regs.eflags & X86_EFLAGS_VM ? X86_CR4_VME : X86_CR4_PVI)); \
+    check_cr4();                                             \
+    get_cpl(ctxt, ops) == 3 &&                               \
+    (cr4 & (_regs.eflags & X86_EFLAGS_VM ? X86_CR4_VME : X86_CR4_PVI)); \
 })
 
 static int ioport_access_check(
@@ -2185,14 +2186,11 @@ static bool is_branch_step(struct x86_em
 }
 
 static bool umip_active(struct x86_emulate_ctxt *ctxt,
-                        const struct x86_emulate_ops *ops)
+                        const struct x86_emulate_ops *ops,
+                        unsigned long cr4)
 {
-    unsigned long cr4;
-
     /* Intentionally not using mode_ring0() here to avoid its fail_if(). */
-    return get_cpl(ctxt, ops) > 0 &&
-           ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY &&
-           (cr4 & X86_CR4_UMIP);
+    return get_cpl(ctxt, ops) > 0 && (cr4 & X86_CR4_UMIP);
 }
 
 static void adjust_bnd(struct x86_emulate_ctxt *ctxt,
@@ -3226,7 +3224,7 @@ x86_emulate(
     /* Shadow copy of register state. Committed on successful emulation. */
     struct cpu_user_regs _regs = *ctxt->regs;
     struct x86_emulate_state state;
-    int rc;
+    int rc, cr4_rc;
     uint8_t b, d, *opc = NULL;
     unsigned int first_byte = 0, insn_bytes = 0;
     bool singlestep = (_regs.eflags & X86_EFLAGS_TF) &&
@@ -3234,7 +3232,7 @@ x86_emulate(
     bool sfence = false;
     struct operand src = { .reg = PTR_POISON };
     struct operand dst = { .reg = PTR_POISON };
-    unsigned long cr4;
+    unsigned long cr4 = 0;
     enum x86_emulate_fpu_type fpu_type = X86EMUL_FPU_none;
     struct x86_emulate_stub stub = {};
     DECLARE_ALIGNED(mmval_t, mmval);
@@ -3247,6 +3245,8 @@ x86_emulate(
 
     ASSERT(ops->read);
 
+    cr4_rc = ops->read_cr ? ops->read_cr(4, &cr4, ctxt) : X86EMUL_OKAY;
+
     generate_exception_if((mode_vif() &&
                            (_regs.eflags & X86_EFLAGS_VIF) &&
                            (_regs.eflags & X86_EFLAGS_VIP)),
@@ -4000,13 +4000,8 @@ x86_emulate(
         if ( (_regs.eflags & X86_EFLAGS_VM) &&
              MASK_EXTR(_regs.eflags, X86_EFLAGS_IOPL) != 3 )
         {
-            cr4 = 0;
-            if ( op_bytes == 2 && ops->read_cr )
-            {
-                rc = ops->read_cr(4, &cr4, ctxt);
-                if ( rc != X86EMUL_OKAY )
-                    goto done;
-            }
+            if ( op_bytes == 2 )
+                check_cr4();
             generate_exception_if(!(cr4 & X86_CR4_VME), EXC_GP, 0);
             src.val = (_regs.flags & ~X86_EFLAGS_IF) | X86_EFLAGS_IOPL;
             if ( _regs.eflags & X86_EFLAGS_VIF )
@@ -4019,17 +4014,12 @@ x86_emulate(
     case 0x9d: /* popf */ {
         uint32_t mask = X86_EFLAGS_VIP | X86_EFLAGS_VIF | X86_EFLAGS_VM;
 
-        cr4 = 0;
         if ( !mode_ring0() )
         {
             if ( _regs.eflags & X86_EFLAGS_VM )
             {
-                if ( op_bytes == 2 && ops->read_cr )
-                {
-                    rc = ops->read_cr(4, &cr4, ctxt);
-                    if ( rc != X86EMUL_OKAY )
-                        goto done;
-                }
+                if ( op_bytes == 2 )
+                    check_cr4();
                 generate_exception_if(!(cr4 & X86_CR4_VME) &&
                                       MASK_EXTR(_regs.eflags, X86_EFLAGS_IOPL) 
!= 3,
                                       EXC_GP, 0);
@@ -5113,7 +5103,7 @@ x86_emulate(
         switch ( modrm_reg & 6 )
         {
         case 0: /* sldt / str */
-            generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0);
+            generate_exception_if(umip_active(ctxt, ops, cr4), EXC_GP, 0);
             goto store_selector;
         case 2: /* lldt / ltr */
             generate_exception_if(!mode_ring0(), EXC_GP, 0);
@@ -5168,11 +5158,10 @@ x86_emulate(
             break;
 
         case 0xd0: /* xgetbv */
-            generate_exception_if(vex.pfx, EXC_UD);
-            if ( !ops->read_cr || !ops->read_xcr ||
-                 ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY )
-                cr4 = 0;
-            generate_exception_if(!(cr4 & X86_CR4_OSXSAVE), EXC_UD);
+            generate_exception_if((vex.pfx || !ops->read_xcr ||
+                                   cr4_rc != X86EMUL_OKAY ||
+                                   !(cr4 & X86_CR4_OSXSAVE)),
+                                  EXC_UD);
             rc = ops->read_xcr(_regs.ecx, &msr_val, ctxt);
             if ( rc != X86EMUL_OKAY )
                 goto done;
@@ -5181,11 +5170,10 @@ x86_emulate(
             break;
 
         case 0xd1: /* xsetbv */
-            generate_exception_if(vex.pfx, EXC_UD);
-            if ( !ops->read_cr || !ops->write_xcr ||
-                 ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY )
-                cr4 = 0;
-            generate_exception_if(!(cr4 & X86_CR4_OSXSAVE), EXC_UD);
+            generate_exception_if((vex.pfx || !ops->write_xcr ||
+                                   cr4_rc != X86EMUL_OKAY ||
+                                   !(cr4 & X86_CR4_OSXSAVE)),
+                                  EXC_UD);
             generate_exception_if(!mode_ring0(), EXC_GP, 0);
             rc = ops->write_xcr(_regs.ecx,
                                 _regs.eax | ((uint64_t)_regs.edx << 32), ctxt);
@@ -5309,7 +5297,7 @@ x86_emulate(
         case GRP7_MEM(0): /* sgdt */
         case GRP7_MEM(1): /* sidt */
             ASSERT(ea.type == OP_MEM);
-            generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0);
+            generate_exception_if(umip_active(ctxt, ops, cr4), EXC_GP, 0);
             fail_if(!ops->read_segment || !ops->write);
             if ( (rc = ops->read_segment(seg, &sreg, ctxt)) )
                 goto done;
@@ -5348,7 +5336,7 @@ x86_emulate(
             break;
 
         case GRP7_ALL(4): /* smsw */
-            generate_exception_if(umip_active(ctxt, ops), EXC_GP, 0);
+            generate_exception_if(umip_active(ctxt, ops, cr4), EXC_GP, 0);
             if ( ea.type == OP_MEM )
             {
                 fail_if(!ops->write);
@@ -5931,8 +5919,7 @@ x86_emulate(
         if ( !mode_ring0() )
         {
             fail_if(ops->read_cr == NULL);
-            if ( (rc = ops->read_cr(4, &cr4, ctxt)) )
-                goto done;
+            check_cr4();
             generate_exception_if(cr4 & X86_CR4_TSD, EXC_GP, 0);
         }
         fail_if(ops->read_msr == NULL);
@@ -6968,8 +6955,6 @@ x86_emulate(
         fail_if(modrm_mod != 3);
         generate_exception_if((modrm_reg & 4) || !mode_64bit(), EXC_UD);
         fail_if(!ops->read_cr);
-        if ( (rc = ops->read_cr(4, &cr4, ctxt)) != X86EMUL_OKAY )
-            goto done;
         generate_exception_if(!(cr4 & X86_CR4_FSGSBASE), EXC_UD);
         seg = modrm_reg & 1 ? x86_seg_gs : x86_seg_fs;
         fail_if(!ops->read_segment);
@@ -8960,13 +8945,8 @@ x86_emulate(
  emulation_stub_failure:
     generate_exception_if(stub_exn.info.fields.trapnr == EXC_MF, EXC_MF);
     if ( stub_exn.info.fields.trapnr == EXC_XM )
-    {
-        unsigned long cr4;
-
-        if ( !ops->read_cr || ops->read_cr(4, &cr4, ctxt) != X86EMUL_OKAY )
-            cr4 = X86_CR4_OSXMMEXCPT;
-        generate_exception(cr4 & X86_CR4_OSXMMEXCPT ? EXC_XM : EXC_UD);
-    }
+        generate_exception(!ops->read_cr || cr4_rc != X86EMUL_OKAY ||
+                           cr4 & X86_CR4_OSXMMEXCPT ? EXC_XM : EXC_UD);
     gprintk(XENLOG_WARNING,
             "exception %u (ec=%04x) in emulation stub (line %u)\n",
             stub_exn.info.fields.trapnr, stub_exn.info.fields.ec,




_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.