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

[Xen-changelog] [xen-unstable] x86_emulate: Emulate MMX movq instructions.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1208425614 -3600
# Node ID d178c5ee6822a269e365d206da74e9704f059fa1
# Parent  a38a41de0800cefca755ffb600d6d5e96f084697
x86_emulate: Emulate MMX movq instructions.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/emulate.c             |   19 +++++++-
 xen/arch/x86/x86_emulate/x86_emulate.c |   77 ++++++++++++++++++++++++++-------
 xen/arch/x86/x86_emulate/x86_emulate.h |    9 +++
 3 files changed, 87 insertions(+), 18 deletions(-)

diff -r a38a41de0800 -r d178c5ee6822 xen/arch/x86/hvm/emulate.c
--- a/xen/arch/x86/hvm/emulate.c        Wed Apr 16 16:42:47 2008 +0100
+++ b/xen/arch/x86/hvm/emulate.c        Thu Apr 17 10:46:54 2008 +0100
@@ -674,16 +674,33 @@ static int hvmemul_inject_sw_interrupt(
     return X86EMUL_OKAY;
 }
 
-static void hvmemul_get_fpu(
+static int hvmemul_get_fpu(
     void (*exception_callback)(void *, struct cpu_user_regs *),
     void *exception_callback_arg,
+    enum x86_emulate_fpu_type type,
     struct x86_emulate_ctxt *ctxt)
 {
     struct vcpu *curr = current;
+
+    switch ( type )
+    {
+    case X86EMUL_FPU_fpu:
+        break;
+    case X86EMUL_FPU_mmx:
+        if ( !cpu_has_mmx )
+            return X86EMUL_UNHANDLEABLE;
+        break;
+    default:
+        return X86EMUL_UNHANDLEABLE;
+    }
+
     if ( !curr->fpu_dirtied )
         hvm_funcs.fpu_dirty_intercept();
+
     curr->arch.hvm_vcpu.fpu_exception_callback = exception_callback;
     curr->arch.hvm_vcpu.fpu_exception_callback_arg = exception_callback_arg;
+
+    return X86EMUL_OKAY;
 }
 
 static void hvmemul_put_fpu(
diff -r a38a41de0800 -r d178c5ee6822 xen/arch/x86/x86_emulate/x86_emulate.c
--- a/xen/arch/x86/x86_emulate/x86_emulate.c    Wed Apr 16 16:42:47 2008 +0100
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c    Thu Apr 17 10:46:54 2008 +0100
@@ -195,9 +195,9 @@ static uint8_t twobyte_table[256] = {
     /* 0x50 - 0x5F */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x60 - 0x6F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM,
     /* 0x70 - 0x7F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM,
     /* 0x80 - 0x87 */
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -558,41 +558,48 @@ static void fpu_handle_exception(void *_
     regs->eip += fic->insn_bytes;
 }
 
+#define get_fpu(_type, _fic)                                    \
+do{ (_fic)->exn_raised = 0;                                     \
+    fail_if(ops->get_fpu == NULL);                              \
+    rc = ops->get_fpu(fpu_handle_exception, _fic, _type, ctxt); \
+    if ( rc ) goto done;                                        \
+} while (0)
+#define put_fpu(_fic)                                           \
+do{                                                             \
+    if ( ops->put_fpu != NULL )                                 \
+        ops->put_fpu(ctxt);                                     \
+    generate_exception_if((_fic)->exn_raised, EXC_MF, -1);      \
+} while (0)
+
 #define emulate_fpu_insn(_op)                           \
-do{ struct fpu_insn_ctxt fic = { 0 };                   \
-    fail_if(ops->get_fpu == NULL);                      \
-    ops->get_fpu(fpu_handle_exception, &fic, ctxt);     \
+do{ struct fpu_insn_ctxt fic;                           \
+    get_fpu(X86EMUL_FPU_fpu, &fic);                     \
     asm volatile (                                      \
         "movb $2f-1f,%0 \n"                             \
         "1: " _op "     \n"                             \
         "2:             \n"                             \
         : "=m" (fic.insn_bytes) : : "memory" );         \
-    ops->put_fpu(ctxt);                                 \
-    generate_exception_if(fic.exn_raised, EXC_MF, -1);  \
+    put_fpu(&fic);                                      \
 } while (0)
 
 #define emulate_fpu_insn_memdst(_op, _arg)              \
-do{ struct fpu_insn_ctxt fic = { 0 };                   \
-    fail_if(ops->get_fpu == NULL);                      \
-    ops->get_fpu(fpu_handle_exception, &fic, ctxt);     \
+do{ struct fpu_insn_ctxt fic;                           \
+    get_fpu(X86EMUL_FPU_fpu, &fic);                     \
     asm volatile (                                      \
         "movb $2f-1f,%0 \n"                             \
         "1: " _op " %1  \n"                             \
         "2:             \n"                             \
         : "=m" (fic.insn_bytes), "=m" (_arg)            \
         : : "memory" );                                 \
-    ops->put_fpu(ctxt);                                 \
-    generate_exception_if(fic.exn_raised, EXC_MF, -1);  \
+    put_fpu(&fic);                                      \
 } while (0)
 
 #define emulate_fpu_insn_stub(_bytes...)                                \
 do{ uint8_t stub[] = { _bytes, 0xc3 };                                  \
     struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 };        \
-    fail_if(ops->get_fpu == NULL);                                      \
-    ops->get_fpu(fpu_handle_exception, &fic, ctxt);                     \
+    get_fpu(X86EMUL_FPU_fpu, &fic);                                     \
     (*(void(*)(void))stub)();                                           \
-    ops->put_fpu(ctxt);                                                 \
-    generate_exception_if(fic.exn_raised, EXC_MF, -1);                  \
+    put_fpu(&fic);                                                      \
 } while (0)
 
 static unsigned long __get_rep_prefix(
@@ -3369,6 +3376,44 @@ x86_emulate(
         break;
     }
 
+    case 0x6f: /* movq mm/m64,mm */ {
+        uint8_t stub[] = { 0x0f, 0x6f, modrm, 0xc3 };
+        struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 };
+        uint64_t val;
+        if ( ea.type == OP_MEM )
+        {
+            unsigned long lval, hval;
+            if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &lval, 4, ctxt)) ||
+                 (rc = ops->read(ea.mem.seg, ea.mem.off+4, &hval, 4, ctxt)) )
+                goto done;
+            val = ((uint64_t)hval << 32) | (uint32_t)lval;
+            stub[2] = modrm & 0x38; /* movq (%eax),%mmN */
+        }
+        get_fpu(X86EMUL_FPU_mmx, &fic);
+        asm volatile ( "call *%0" : : "r" (stub), "a" (&val) : "memory" );
+        put_fpu(&fic);
+        break;
+    }
+
+    case 0x7f: /* movq mm,mm/m64 */ {
+        uint8_t stub[] = { 0x0f, 0x7f, modrm, 0xc3 };
+        struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 };
+        uint64_t val;
+        if ( ea.type == OP_MEM )
+            stub[2] = modrm & 0x38; /* movq %mmN,(%eax) */
+        get_fpu(X86EMUL_FPU_mmx, &fic);
+        asm volatile ( "call *%0" : : "r" (stub), "a" (&val) : "memory" );
+        put_fpu(&fic);
+        if ( ea.type == OP_MEM )
+        {
+            unsigned long lval = (uint32_t)val, hval = (uint32_t)(val >> 32);
+            if ( (rc = ops->write(ea.mem.seg, ea.mem.off+0, lval, 4, ctxt)) ||
+                 (rc = ops->write(ea.mem.seg, ea.mem.off+4, hval, 4, ctxt)) )
+                goto done;
+        }
+        break;
+    }
+
     case 0x80 ... 0x8f: /* jcc (near) */ {
         int rel = (((op_bytes == 2) && !mode_64bit())
                    ? (int32_t)insn_fetch_type(int16_t)
diff -r a38a41de0800 -r d178c5ee6822 xen/arch/x86/x86_emulate/x86_emulate.h
--- a/xen/arch/x86/x86_emulate/x86_emulate.h    Wed Apr 16 16:42:47 2008 +0100
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h    Thu Apr 17 10:46:54 2008 +0100
@@ -95,6 +95,12 @@ struct segment_register {
  /* (cmpxchg accessor): CMPXCHG failed. Maps to X86EMUL_RETRY in caller. */
 #define X86EMUL_CMPXCHG_FAILED 3
 
+/* FPU sub-types which may be requested via ->get_fpu(). */
+enum x86_emulate_fpu_type {
+    X86EMUL_FPU_fpu, /* Standard FPU coprocessor instruction set */
+    X86EMUL_FPU_mmx  /* MMX instruction set (%mm0-%mm7) */
+};
+
 /*
  * These operations represent the instruction emulator's interface to memory.
  * 
@@ -347,9 +353,10 @@ struct x86_emulate_ops
      *  @exn_callback: On any FPU or SIMD exception, pass control to
      *                 (*exception_callback)(exception_callback_arg, regs).
      */
-    void (*get_fpu)(
+    int (*get_fpu)(
         void (*exception_callback)(void *, struct cpu_user_regs *),
         void *exception_callback_arg,
+        enum x86_emulate_fpu_type type,
         struct x86_emulate_ctxt *ctxt);
 
     /* put_fpu: Relinquish the FPU. Unhook from FPU/SIMD exception handlers. */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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