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

[Xen-changelog] [xen master] x86emul: centralize put_fpu() invocations



commit 9b7c3fabbc942624dead58e3743556b7af4910be
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Mar 21 15:10:25 2017 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Mar 21 15:10:25 2017 +0100

    x86emul: centralize put_fpu() invocations
    
    ..., splitting parts of it into check_*() macros. This is in
    preparation of making ->put_fpu() do further adjustments to register
    state. (Some of the check_xmm() invocations could be avoided, as in
    some of the cases no insns handled there can actually raise #XM, but I
    think we're better off keeping them to avoid later additions of further
    insn patterns rendering the lack of the check a bug.)
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/x86_emulate/x86_emulate.c | 81 +++++++++++++++++++---------------
 xen/arch/x86/x86_emulate/x86_emulate.h |  4 +-
 2 files changed, 48 insertions(+), 37 deletions(-)

diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c 
b/xen/arch/x86/x86_emulate/x86_emulate.c
index 038f558..ce725d8 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -937,6 +937,7 @@ do {                                                        
            \
 
 struct fpu_insn_ctxt {
     uint8_t insn_bytes;
+    uint8_t type;
     int8_t exn_raised;
 };
 
@@ -956,15 +957,16 @@ static int _get_fpu(
 {
     int rc;
 
-    fic->exn_raised = -1;
-
     fail_if(!ops->get_fpu);
+    ASSERT(type != X86EMUL_FPU_none);
     rc = ops->get_fpu(fpu_handle_exception, fic, type, ctxt);
 
     if ( rc == X86EMUL_OKAY )
     {
         unsigned long cr0;
 
+        fic->type = type;
+
         fail_if(!ops->read_cr);
         if ( type >= X86EMUL_FPU_xmm )
         {
@@ -1006,22 +1008,32 @@ do {                                                    
        \
     rc = _get_fpu(_type, _fic, ctxt, ops);                      \
     if ( rc ) goto done;                                        \
 } while (0)
-#define _put_fpu()                                              \
+
+#define check_fpu_exn(fic)                                      \
 do {                                                            \
-    if ( ops->put_fpu != NULL )                                 \
-        (ops->put_fpu)(ctxt);                                   \
+    generate_exception_if((fic)->exn_raised >= 0,               \
+                          (fic)->exn_raised);                   \
 } while (0)
-#define put_fpu(_fic)                                           \
+
+#define check_xmm_exn(fic)                                      \
 do {                                                            \
-    _put_fpu();                                                 \
-    if ( (_fic)->exn_raised == EXC_XM && ops->read_cr &&        \
+    if ( (fic)->exn_raised == EXC_XM && ops->read_cr &&         \
          ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY &&         \
-         !(cr4 & X86_CR4_OSXMMEXCPT) )                         \
-        (_fic)->exn_raised = EXC_UD;                            \
-    generate_exception_if((_fic)->exn_raised >= 0,              \
-                          (_fic)->exn_raised);                  \
+         !(cr4 & X86_CR4_OSXMMEXCPT) )                          \
+        (fic)->exn_raised = EXC_UD;                             \
+    check_fpu_exn(fic);                                         \
 } while (0)
 
+static void put_fpu(
+    struct fpu_insn_ctxt *fic,
+    struct x86_emulate_ctxt *ctxt,
+    const struct x86_emulate_ops *ops)
+{
+    if ( fic->type != X86EMUL_FPU_none && ops->put_fpu )
+        ops->put_fpu(ctxt);
+    fic->type = X86EMUL_FPU_none;
+}
+
 static inline bool fpu_check_write(void)
 {
     uint16_t fsw;
@@ -3033,7 +3045,7 @@ x86_emulate(
     struct operand dst = { .reg = PTR_POISON };
     unsigned long cr4;
     enum x86_swint_type swint_type;
-    struct fpu_insn_ctxt fic;
+    struct fpu_insn_ctxt fic = { .type = X86EMUL_FPU_none, .exn_raised = -1 };
     struct x86_emulate_stub stub = {};
     DECLARE_ALIGNED(mmval_t, mmval);
 
@@ -3726,7 +3738,7 @@ x86_emulate(
         host_and_vcpu_must_have(fpu);
         get_fpu(X86EMUL_FPU_wait, &fic);
         asm volatile ( "fwait" ::: "memory" );
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0x9c: /* pushf */
@@ -4171,7 +4183,7 @@ x86_emulate(
                 break;
             }
         }
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0xd9: /* FPU 0xd9 */
@@ -4260,7 +4272,7 @@ x86_emulate(
             if ( dst.type == OP_MEM && dst.bytes == 4 && !fpu_check_write() )
                 dst.type = OP_NONE;
         }
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0xda: /* FPU 0xda */
@@ -4311,7 +4323,7 @@ x86_emulate(
                 break;
             }
         }
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0xdb: /* FPU 0xdb */
@@ -4383,7 +4395,7 @@ x86_emulate(
             if ( dst.type == OP_MEM && !fpu_check_write() )
                 dst.type = OP_NONE;
         }
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0xdc: /* FPU 0xdc */
@@ -4434,7 +4446,7 @@ x86_emulate(
                 break;
             }
         }
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0xdd: /* FPU 0xdd */
@@ -4493,7 +4505,7 @@ x86_emulate(
             if ( dst.type == OP_MEM && dst.bytes == 8 && !fpu_check_write() )
                 dst.type = OP_NONE;
         }
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0xde: /* FPU 0xde */
@@ -4541,7 +4553,7 @@ x86_emulate(
                 break;
             }
         }
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0xdf: /* FPU 0xdf */
@@ -4623,7 +4635,7 @@ x86_emulate(
             if ( dst.type == OP_MEM && !fpu_check_write() )
                 dst.type = OP_NONE;
         }
-        put_fpu(&fic);
+        check_fpu_exn(&fic);
         break;
 
     case 0xe0 ... 0xe2: /* loop{,z,nz} */ {
@@ -5685,7 +5697,7 @@ x86_emulate(
                             : "c" (mmvalp), "m" (*mmvalp));
 
         put_stub(stub);
-        put_fpu(&fic);
+        check_xmm_exn(&fic);
 
         state->simd_size = simd_none;
         break;
@@ -5737,7 +5749,7 @@ x86_emulate(
                       [mask] "i" (EFLAGS_MASK));
 
         put_stub(stub);
-        put_fpu(&fic);
+        check_xmm_exn(&fic);
 
         ASSERT(!state->simd_size);
         break;
@@ -5921,7 +5933,7 @@ x86_emulate(
         invoke_stub("", "", "=a" (dst.val) : [dummy] "i" (0));
 
         put_stub(stub);
-        put_fpu(&fic);
+        check_xmm_exn(&fic);
 
         ASSERT(!state->simd_size);
         dst.bytes = 4;
@@ -6129,7 +6141,7 @@ x86_emulate(
         dst.val = src.val;
 
         put_stub(stub);
-        put_fpu(&fic);
+        check_xmm_exn(&fic);
 
         ASSERT(!state->simd_size);
         break;
@@ -6271,7 +6283,7 @@ x86_emulate(
         invoke_stub("", "", [dummy_out] "=g" (dummy) : [dummy_in] "i" (0) );
 
         put_stub(stub);
-        put_fpu(&fic);
+        check_xmm_exn(&fic);
 
         ASSERT(!state->simd_size);
         break;
@@ -6341,8 +6353,6 @@ x86_emulate(
                     asm volatile ( ".byte 0xc5,0xc1,0xeb,0xff" );
                 }
 
-                put_fpu(&fic);
-
                 ASSERT(!state->simd_size);
                 break;
             }
@@ -7090,10 +7100,7 @@ x86_emulate(
 
         put_stub(stub);
         if ( !ea.val )
-        {
-            put_fpu(&fic);
             goto complete_insn;
-        }
 
         opc = init_prefixes(stub);
         opc[0] = b;
@@ -7241,7 +7248,7 @@ x86_emulate(
         emulate_stub("+m" (*mmvalp), "a" (mmvalp));
 
         put_stub(stub);
-        put_fpu(&fic);
+        check_xmm_exn(&fic);
 
         state->simd_size = simd_none;
         dst.type = OP_NONE;
@@ -7545,7 +7552,7 @@ x86_emulate(
         invoke_stub("", "", "=m" (dst.val) : "a" (&dst.val));
 
         put_stub(stub);
-        put_fpu(&fic);
+        check_xmm_exn(&fic);
 
         ASSERT(!state->simd_size);
         dst.bytes = dst.type == OP_REG || b == 0x17 ? 4 : 1 << (b & 3);
@@ -7861,7 +7868,7 @@ x86_emulate(
             invoke_stub("", "", "+m" (*mmvalp) : "D" (mmvalp));
 
         put_stub(stub);
-        put_fpu(&fic);
+        check_xmm_exn(&fic);
     }
 
     switch ( dst.type )
@@ -7903,6 +7910,8 @@ x86_emulate(
     }
 
  complete_insn: /* Commit shadow register state. */
+    put_fpu(&fic, ctxt, ops);
+
     /* Zero the upper 32 bits of %rip if not in 64-bit mode. */
     if ( !mode_64bit() )
         _regs.r(ip) = _regs.eip;
@@ -7925,7 +7934,7 @@ x86_emulate(
     ctxt->regs->eflags &= ~X86_EFLAGS_RF;
 
  done:
-    _put_fpu();
+    put_fpu(&fic, ctxt, ops);
     put_stub(stub);
     return rc;
 #undef state
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h 
b/xen/arch/x86/x86_emulate/x86_emulate.h
index 6e98453..3d92a47 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -161,7 +161,9 @@ enum x86_emulate_fpu_type {
     X86EMUL_FPU_wait, /* WAIT/FWAIT instruction */
     X86EMUL_FPU_mmx, /* MMX instruction set (%mm0-%mm7) */
     X86EMUL_FPU_xmm, /* SSE instruction set (%xmm0-%xmm7/15) */
-    X86EMUL_FPU_ymm  /* AVX/XOP instruction set (%ymm0-%ymm7/15) */
+    X86EMUL_FPU_ymm, /* AVX/XOP instruction set (%ymm0-%ymm7/15) */
+    /* This sentinel will never be passed to ->get_fpu(). */
+    X86EMUL_FPU_none
 };
 
 struct cpuid_leaf
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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