WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86_emulate: Implement a more dynamic int

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86_emulate: Implement a more dynamic interface for handling FPU
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 22 Apr 2008 07:10:23 -0700
Delivery-date: Tue, 22 Apr 2008 07:11:16 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1208358641 -3600
# Node ID defbab4dba1a40ce08ed5b9331cfaf7a4422853e
# Parent  837ea1f0aa8ab3446cfb8bf3ab9d68e258d08785
x86_emulate: Implement a more dynamic interface for handling FPU
exceptions, which will allow emulation stubs to be built dynamically
in a future patch.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/tests/x86_emulate.c              |    6 --
 xen/arch/x86/Makefile                  |    2 
 xen/arch/x86/hvm/emulate.c             |   23 +++++++--
 xen/arch/x86/traps.c                   |    9 +++
 xen/arch/x86/x86_emulate.c             |   18 -------
 xen/arch/x86/x86_emulate/x86_emulate.c |   82 ++++++++++++++++++++++-----------
 xen/arch/x86/x86_emulate/x86_emulate.h |   14 ++++-
 xen/include/asm-x86/hvm/vcpu.h         |    3 +
 8 files changed, 100 insertions(+), 57 deletions(-)

diff -r 837ea1f0aa8a -r defbab4dba1a tools/tests/x86_emulate.c
--- a/tools/tests/x86_emulate.c Wed Apr 16 13:43:23 2008 +0100
+++ b/tools/tests/x86_emulate.c Wed Apr 16 16:10:41 2008 +0100
@@ -4,10 +4,4 @@
 #include <public/xen.h>
 
 #include "x86_emulate/x86_emulate.h"
-
-#define __emulate_fpu_insn(_op)                 \
-do{ rc = X86EMUL_UNHANDLEABLE;                  \
-    goto done;                                  \
-} while (0)
-
 #include "x86_emulate/x86_emulate.c"
diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile     Wed Apr 16 13:43:23 2008 +0100
+++ b/xen/arch/x86/Makefile     Wed Apr 16 16:10:41 2008 +0100
@@ -52,6 +52,8 @@ obj-y += tboot.o
 
 obj-$(crash_debug) += gdbstub.o
 
+x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
+
 $(TARGET): $(TARGET)-syms boot/mkelf32
        ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \
        `$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'`
diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/hvm/emulate.c
--- a/xen/arch/x86/hvm/emulate.c        Wed Apr 16 13:43:23 2008 +0100
+++ b/xen/arch/x86/hvm/emulate.c        Wed Apr 16 16:10:41 2008 +0100
@@ -674,11 +674,23 @@ static int hvmemul_inject_sw_interrupt(
     return X86EMUL_OKAY;
 }
 
-static void hvmemul_load_fpu_ctxt(
-    struct x86_emulate_ctxt *ctxt)
-{
-    if ( !current->fpu_dirtied )
+static void hvmemul_get_fpu(
+    void (*exception_callback)(void *, struct cpu_user_regs *),
+    void *exception_callback_arg,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct vcpu *curr = current;
+    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;
+}
+
+static void hvmemul_put_fpu(
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct vcpu *curr = current;
+    curr->arch.hvm_vcpu.fpu_exception_callback = NULL;
 }
 
 static int hvmemul_invlpg(
@@ -720,7 +732,8 @@ static struct x86_emulate_ops hvm_emulat
     .cpuid         = hvmemul_cpuid,
     .inject_hw_exception = hvmemul_inject_hw_exception,
     .inject_sw_interrupt = hvmemul_inject_sw_interrupt,
-    .load_fpu_ctxt = hvmemul_load_fpu_ctxt,
+    .get_fpu       = hvmemul_get_fpu,
+    .put_fpu       = hvmemul_put_fpu,
     .invlpg        = hvmemul_invlpg
 };
 
diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Wed Apr 16 13:43:23 2008 +0100
+++ b/xen/arch/x86/traps.c      Wed Apr 16 16:10:41 2008 +0100
@@ -479,6 +479,7 @@ static inline void do_trap(
 static inline void do_trap(
     int trapnr, struct cpu_user_regs *regs, int use_error_code)
 {
+    struct vcpu *curr = current;
     unsigned long fixup;
 
     DEBUGGER_trap_entry(trapnr, regs);
@@ -494,6 +495,14 @@ static inline void do_trap(
         dprintk(XENLOG_ERR, "Trap %d: %p -> %p\n",
                 trapnr, _p(regs->eip), _p(fixup));
         regs->eip = fixup;
+        return;
+    }
+
+    if ( ((trapnr == TRAP_copro_error) || (trapnr == TRAP_simd_error)) &&
+         is_hvm_vcpu(curr) && curr->arch.hvm_vcpu.fpu_exception_callback )
+    {
+        curr->arch.hvm_vcpu.fpu_exception_callback(
+            curr->arch.hvm_vcpu.fpu_exception_callback_arg, regs);
         return;
     }
 
diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Wed Apr 16 13:43:23 2008 +0100
+++ b/xen/arch/x86/x86_emulate.c        Wed Apr 16 16:10:41 2008 +0100
@@ -11,23 +11,7 @@
 
 #include <asm/x86_emulate.h>
 
+/* Avoid namespace pollution. */
 #undef cmpxchg
 
-#define __emulate_fpu_insn(_op)                 \
-do{ int _exn;                                   \
-    asm volatile (                              \
-        "1: " _op "\n"                          \
-        "2: \n"                                 \
-        ".section .fixup,\"ax\"\n"              \
-        "3: mov $1,%0\n"                        \
-        "   jmp 2b\n"                           \
-        ".previous\n"                           \
-        ".section __ex_table,\"a\"\n"           \
-        "   "__FIXUP_ALIGN"\n"                  \
-        "   "__FIXUP_WORD" 1b,3b\n"             \
-        ".previous"                             \
-        : "=r" (_exn) : "0" (0) );              \
-    generate_exception_if(_exn, EXC_MF, -1);    \
-} while (0)
-
 #include "x86_emulate/x86_emulate.c"
diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/x86_emulate/x86_emulate.c
--- a/xen/arch/x86/x86_emulate/x86_emulate.c    Wed Apr 16 13:43:23 2008 +0100
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c    Wed Apr 16 16:10:41 2008 +0100
@@ -544,6 +544,45 @@ do {                                    
     if ( !mode_64bit() )                                                \
         _regs.eip = ((op_bytes == 2)                                    \
                      ? (uint16_t)_regs.eip : (uint32_t)_regs.eip);      \
+} while (0)
+
+struct fpu_insn_ctxt {
+    uint8_t insn_bytes;
+    uint8_t exn_raised;
+};
+
+static void fpu_handle_exception(void *_fic, struct cpu_user_regs *regs)
+{
+    struct fpu_insn_ctxt *fic = _fic;
+    fic->exn_raised = 1;
+    regs->eip += fic->insn_bytes;
+}
+
+#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);     \
+    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);  \
+} 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);     \
+    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);  \
 } while (0)
 
 static unsigned long __get_rep_prefix(
@@ -2399,8 +2438,6 @@ x86_emulate(
     }
 
     case 0x9b:  /* wait/fwait */
-        fail_if(ops->load_fpu_ctxt == NULL);
-        ops->load_fpu_ctxt(ctxt);
         __emulate_fpu_insn("fwait");
         break;
 
@@ -2721,53 +2758,46 @@ x86_emulate(
     }
 
     case 0xd9: /* FPU 0xd9 */
-        fail_if(ops->load_fpu_ctxt == NULL);
-        ops->load_fpu_ctxt(ctxt);
         switch ( modrm )
         {
-        case 0xc0: __emulate_fpu_insn(".byte 0xd9,0xc0"); break;
-        case 0xc1: __emulate_fpu_insn(".byte 0xd9,0xc1"); break;
-        case 0xc2: __emulate_fpu_insn(".byte 0xd9,0xc2"); break;
-        case 0xc3: __emulate_fpu_insn(".byte 0xd9,0xc3"); break;
-        case 0xc4: __emulate_fpu_insn(".byte 0xd9,0xc4"); break;
-        case 0xc5: __emulate_fpu_insn(".byte 0xd9,0xc5"); break;
-        case 0xc6: __emulate_fpu_insn(".byte 0xd9,0xc6"); break;
-        case 0xc7: __emulate_fpu_insn(".byte 0xd9,0xc7"); break;
-        case 0xe0: __emulate_fpu_insn(".byte 0xd9,0xe0"); break;
-        case 0xe8: __emulate_fpu_insn(".byte 0xd9,0xe8"); break;
-        case 0xee: __emulate_fpu_insn(".byte 0xd9,0xee"); break;
+        case 0xc0: __emulate_fpu_insn(".byte 0xd9,0xc0"); break; /* fld %st0 */
+        case 0xc1: __emulate_fpu_insn(".byte 0xd9,0xc1"); break; /* fld %st1 */
+        case 0xc2: __emulate_fpu_insn(".byte 0xd9,0xc2"); break; /* fld %st2 */
+        case 0xc3: __emulate_fpu_insn(".byte 0xd9,0xc3"); break; /* fld %st3 */
+        case 0xc4: __emulate_fpu_insn(".byte 0xd9,0xc4"); break; /* fld %st4 */
+        case 0xc5: __emulate_fpu_insn(".byte 0xd9,0xc5"); break; /* fld %st5 */
+        case 0xc6: __emulate_fpu_insn(".byte 0xd9,0xc6"); break; /* fld %st6 */
+        case 0xc7: __emulate_fpu_insn(".byte 0xd9,0xc7"); break; /* fld %st7 */
+        case 0xe0: __emulate_fpu_insn(".byte 0xd9,0xe0"); break; /* fchs */
+        case 0xe1: __emulate_fpu_insn(".byte 0xd9,0xe1"); break; /* fabs */
+        case 0xe8: __emulate_fpu_insn(".byte 0xd9,0xe8"); break; /* fld1 */
+        case 0xee: __emulate_fpu_insn(".byte 0xd9,0xee"); break; /* fldz */
         default:
             fail_if((modrm_reg & 7) != 7);
             fail_if(modrm >= 0xc0);
             /* fnstcw m2byte */
             ea.bytes = 2;
             dst = ea;
-            asm volatile ( "fnstcw %0" : "=m" (dst.val) );
+            __emulate_fpu_insn_memdst("fnstcw", dst.val);
         }
         break;
 
     case 0xdb: /* FPU 0xdb */
-        fail_if(ops->load_fpu_ctxt == NULL);
-        ops->load_fpu_ctxt(ctxt);
         fail_if(modrm != 0xe3);
         /* fninit */
-        asm volatile ( "fninit" );
+        __emulate_fpu_insn("fninit");
         break;
 
     case 0xdd: /* FPU 0xdd */
-        fail_if(ops->load_fpu_ctxt == NULL);
-        ops->load_fpu_ctxt(ctxt);
         fail_if((modrm_reg & 7) != 7);
         fail_if(modrm >= 0xc0);
         /* fnstsw m2byte */
         ea.bytes = 2;
         dst = ea;
-        asm volatile ( "fnstsw %0" : "=m" (dst.val) );
+        __emulate_fpu_insn_memdst("fnstsw", dst.val);
         break;
 
     case 0xde: /* FPU 0xde */
-        fail_if(ops->load_fpu_ctxt == NULL);
-        ops->load_fpu_ctxt(ctxt);
         switch ( modrm )
         {
         case 0xd9: __emulate_fpu_insn(".byte 0xde,0xd9"); break;
@@ -2784,14 +2814,12 @@ x86_emulate(
         break;
 
     case 0xdf: /* FPU 0xdf */
-        fail_if(ops->load_fpu_ctxt == NULL);
-        ops->load_fpu_ctxt(ctxt);
         fail_if(modrm != 0xe0);
         /* fnstsw %ax */
         dst.bytes = 2;
         dst.type = OP_REG;
         dst.reg = (unsigned long *)&_regs.eax;
-        asm volatile ( "fnstsw %0" : "=m" (dst.val) );
+        __emulate_fpu_insn_memdst("fnstsw", dst.val);
         break;
 
     case 0xe0 ... 0xe2: /* loop{,z,nz} */ {
diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/x86_emulate/x86_emulate.h
--- a/xen/arch/x86/x86_emulate/x86_emulate.h    Wed Apr 16 13:43:23 2008 +0100
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h    Wed Apr 16 16:10:41 2008 +0100
@@ -342,8 +342,18 @@ struct x86_emulate_ops
         uint8_t insn_len,
         struct x86_emulate_ctxt *ctxt);
 
-    /* load_fpu_ctxt: Load emulated environment's FPU state onto processor. */
-    void (*load_fpu_ctxt)(
+    /*
+     * get_fpu: Load emulated environment's FPU state onto processor.
+     *  @exn_callback: On any FPU or SIMD exception, pass control to
+     *                 (*exception_callback)(exception_callback_arg, regs).
+     */
+    void (*get_fpu)(
+        void (*exception_callback)(void *, struct cpu_user_regs *),
+        void *exception_callback_arg,
+        struct x86_emulate_ctxt *ctxt);
+
+    /* put_fpu: Relinquish the FPU. Unhook from FPU/SIMD exception handlers. */
+    void (*put_fpu)(
         struct x86_emulate_ctxt *ctxt);
 
     /* invlpg: Invalidate paging structures which map addressed byte. */
diff -r 837ea1f0aa8a -r defbab4dba1a xen/include/asm-x86/hvm/vcpu.h
--- a/xen/include/asm-x86/hvm/vcpu.h    Wed Apr 16 13:43:23 2008 +0100
+++ b/xen/include/asm-x86/hvm/vcpu.h    Wed Apr 16 16:10:41 2008 +0100
@@ -83,6 +83,9 @@ struct hvm_vcpu {
      */
     unsigned long       mmio_gva;
     unsigned long       mmio_gpfn;
+
+    void (*fpu_exception_callback)(void *, struct cpu_user_regs *);
+    void *fpu_exception_callback_arg;
 };
 
 #endif /* __ASM_X86_HVM_VCPU_H__ */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86_emulate: Implement a more dynamic interface for handling FPU, Xen patchbot-unstable <=