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

[Xen-changelog] [xen-unstable] x86_32: handle x87 opcodes in TLS segment fixups



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1248794118 -3600
# Node ID 95eec4e77c3c60e8f4e53436f6a259613a9094d8
# Parent  8af26fef898c88d1b929e597d3b232673b8e777d
x86_32: handle x87 opcodes in TLS segment fixups

This patch adds support to the TLS fixup code for x87 opcodes.  These
can be treated like 2-byte opcodes with a weird encoding.

The patch includes some extra changes because, now that we have >2
opcode tables and 9 different lead bytes in a two-byte opcode, a
simple boolean code will not be enough to differentiate one- and
two-byte opcodes.  Besides this, the patch is trivial since the
segment fixup code cares about the operands of the instruction, not
about its semantics.

From: Paolo Bonzini <pbonzini@xxxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/x86_32/seg_fixup.c |   55 ++++++++++++++++++++++++++++++++++------
 1 files changed, 47 insertions(+), 8 deletions(-)

diff -r 8af26fef898c -r 95eec4e77c3c xen/arch/x86/x86_32/seg_fixup.c
--- a/xen/arch/x86/x86_32/seg_fixup.c   Fri Jul 24 12:08:54 2009 +0100
+++ b/xen/arch/x86/x86_32/seg_fixup.c   Tue Jul 28 16:15:18 2009 +0100
@@ -42,7 +42,7 @@
 #define O  OPCODE_BYTE
 #define M  HAS_MODRM
 
-static const unsigned char insn_decode[256] = {
+static const u8 insn_decode[256] = {
     /* 0x00 - 0x0F */
     O|M, O|M, O|M, O|M, X, X, X, X,
     O|M, O|M, O|M, O|M, X, X, X, X,
@@ -93,7 +93,18 @@ static const unsigned char insn_decode[2
     X, X, X, X, X, X, O|M, O|M
 };
 
-static const unsigned char twobyte_decode[256] = {
+static const u8 float_decode[64] = {
+    O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xD8 */
+    O|M, X, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xD9 */
+    O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xDA */
+    O|M, X, O|M, O|M, X, O|M, X, O|M, /* 0xDB */
+    O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xDC */
+    O|M, O|M, O|M, O|M, O|M, X, O|M, O|M, /* 0xDD */
+    O|M, O|M, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xDE */
+    O|M, X, O|M, O|M, O|M, O|M, O|M, O|M, /* 0xDF */
+};
+
+static const u8 twobyte_decode[256] = {
     /* 0x00 - 0x0F */
     X, X, X, X, X, X, X, X,
     X, X, X, X, X, X, X, X,
@@ -321,7 +332,8 @@ int gpf_emulate_4gb(struct cpu_user_regs
     s32            disp32 = 0;
     u8            *eip;         /* ptr to instruction start */
     u8            *pb, b;       /* ptr into instr. / current instr. byte */
-    int            gs_override = 0, scale = 0, twobyte = 0;
+    int            gs_override = 0, scale = 0, opcode = -1;
+    const u8      *table = insn_decode;
 
     /* WARNING: We only work for ring-3 segments. */
     if ( unlikely(vm86_mode(regs)) || unlikely(!ring_3(regs)) )
@@ -352,8 +364,11 @@ int gpf_emulate_4gb(struct cpu_user_regs
             goto fail;
         }
 
-        if ( twobyte )
+        if ( opcode != -1 )
+        {
+            opcode = (opcode << 8) | b;
             break;
+        }
 
         switch ( b )
         {
@@ -374,8 +389,29 @@ int gpf_emulate_4gb(struct cpu_user_regs
             gs_override = 1;
             break;
         case 0x0f: /* Not really a prefix byte */
-            twobyte = 1;
+            table = twobyte_decode;
+            opcode = b;
             break;
+        case 0xd8: /* Math coprocessor instructions.  */
+        case 0xd9:
+        case 0xda:
+        case 0xdb:
+        case 0xdc:
+        case 0xdd:
+        case 0xde:
+        case 0xdf:
+            /* Float opcodes have a secondary opcode in the modrm byte.  */
+            table = float_decode;
+            if ( get_user(modrm, pb + 1) )
+            {
+                dprintk(XENLOG_DEBUG, "Fault while extracting modrm byte\n");
+                goto page_fault;
+            }
+
+            opcode = (b << 8) | modrm;
+            b = ((b & 7) << 3) + ((modrm >> 3) & 7);
+            goto done_prefix;
+
         default: /* Not a prefix byte */
             goto done_prefix;
         }
@@ -388,13 +424,16 @@ int gpf_emulate_4gb(struct cpu_user_regs
         goto fail;
     }
 
-    decode = (!twobyte ? insn_decode : twobyte_decode)[b];
+    decode = table[b];
     pb++;
 
     if ( !(decode & OPCODE_BYTE) )
     {
-        dprintk(XENLOG_DEBUG, "Unsupported %sopcode %02x\n",
-                twobyte ? "two byte " : "", b);
+        if (opcode == -1)
+            dprintk(XENLOG_DEBUG, "Unsupported opcode %02x\n", b);
+        else
+            dprintk(XENLOG_DEBUG, "Unsupported opcode %02x %02x\n",
+                    opcode >> 8, opcode & 255);
         goto fail;
     }
 

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