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

[Xen-changelog] [xen-3.2-testing] x86_emulate: More FPU instructions.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1204734096 0
# Node ID 9e22366fb92a3c3fef9adbe85662653ca5fd4e1d
# Parent  e5e4d92cd8e501f9b894ee047d1d6d799408bb09
x86_emulate: More FPU instructions.

Enables booting OS/2 as a HVM guest on Intel/VT hardware with full
real-mode emulation (no vmxassist).

Signed-off-by: Trolle Selander <trolle.selander@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   17175:a2359114b6cb82966fde343f18cfbe1a5b60cc9c
xen-unstable date:        Mon Mar 03 13:13:55 2008 +0000

x86_emulate: Emit emulated forms of most FPU instructions as '.byte
xx,yy'. This is arguably clearer than using the mnemonic opcode, since
it is more clearly the instruction we have just decoded. Furthermore,
gas likes to reverse FPU operands on some two-operand FPU instructions
for historical reasons. Finally, 'byte xx,yy' is potentially more
amenable to further macro-isation down the road.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   17180:771c7124bf3869493023b78450da71a236debddf
xen-unstable date:        Tue Mar 04 10:32:13 2008 +0000

x86_emulate: Load FPU context before FWAIT.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   17183:96453af916b9351bf8b6f319c4949c77082919fb
xen-unstable date:        Tue Mar 04 13:28:00 2008 +0000
---
 xen/arch/x86/x86_emulate.c |   93 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 85 insertions(+), 8 deletions(-)

diff -r e5e4d92cd8e5 -r 9e22366fb92a xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Wed Mar 05 16:20:29 2008 +0000
+++ b/xen/arch/x86/x86_emulate.c        Wed Mar 05 16:21:36 2008 +0000
@@ -126,7 +126,7 @@ static uint8_t opcode_table[256] = {
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0x98 - 0x9F */
-    ImplicitOps, ImplicitOps, ImplicitOps, 0,
+    ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0xA0 - 0xA7 */
     ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
@@ -159,7 +159,8 @@ static uint8_t opcode_table[256] = {
     ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0xD8 - 0xDF */
-    0, ImplicitOps|ModRM, 0, ImplicitOps|ModRM, 0, ImplicitOps|ModRM, 0, 0,
+    0, ImplicitOps|ModRM|Mov, 0, ImplicitOps|ModRM|Mov,
+    0, ImplicitOps|ModRM|Mov, ImplicitOps|ModRM|Mov, ImplicitOps|ModRM|Mov,
     /* 0xE0 - 0xE7 */
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -308,6 +309,7 @@ struct operand {
 #define EXC_SS 12
 #define EXC_GP 13
 #define EXC_PF 14
+#define EXC_MF 16
 
 /*
  * Instruction emulation:
@@ -474,6 +476,31 @@ do{ asm volatile (                      
 #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)
 #define __emulate_1op_8byte(_op, _dst, _eflags)
 #endif /* __i386__ */
+
+#ifdef __XEN__
+#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)
+#else
+#define __emulate_fpu_insn(_op)                 \
+do{ rc = X86EMUL_UNHANDLEABLE;                  \
+    goto done;                                  \
+} while (0)
+#endif
+
 
 /* Fetch next part of the instruction being emulated. */
 #define insn_fetch_bytes(_size)                                         \
@@ -2349,6 +2376,12 @@ x86_emulate(
         break;
     }
 
+    case 0x9b:  /* wait/fwait */
+        fail_if(ops->load_fpu_ctxt == NULL);
+        ops->load_fpu_ctxt(ctxt);
+        __emulate_fpu_insn("fwait");
+        break;
+
     case 0x9c: /* pushf */
         src.val = _regs.eflags;
         goto push;
@@ -2670,12 +2703,27 @@ x86_emulate(
     case 0xd9: /* FPU 0xd9 */
         fail_if(ops->load_fpu_ctxt == NULL);
         ops->load_fpu_ctxt(ctxt);
-        fail_if((modrm_reg & 7) != 7);
-        fail_if(modrm >= 0xc0);
-        /* fnstcw m2byte */
-        ea.bytes = 2;
-        dst = ea;
-        asm volatile ( "fnstcw %0" : "=m" (dst.val) );
+        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;
+        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) );
+        }
         break;
 
     case 0xdb: /* FPU 0xdb */
@@ -2694,6 +2742,35 @@ x86_emulate(
         /* fnstsw m2byte */
         ea.bytes = 2;
         dst = ea;
+        asm volatile ( "fnstsw %0" : "=m" (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;
+        case 0xf8: __emulate_fpu_insn(".byte 0xde,0xf8"); break;
+        case 0xf9: __emulate_fpu_insn(".byte 0xde,0xf9"); break;
+        case 0xfa: __emulate_fpu_insn(".byte 0xde,0xfa"); break;
+        case 0xfb: __emulate_fpu_insn(".byte 0xde,0xfb"); break;
+        case 0xfc: __emulate_fpu_insn(".byte 0xde,0xfc"); break;
+        case 0xfd: __emulate_fpu_insn(".byte 0xde,0xfd"); break;
+        case 0xfe: __emulate_fpu_insn(".byte 0xde,0xfe"); break;
+        case 0xff: __emulate_fpu_insn(".byte 0xde,0xff"); break;
+        default: goto cannot_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) );
         break;
 

_______________________________________________
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®.