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

[Xen-changelog] [xen-unstable] hvm: Fix some bugs in mmio decoder



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1176463804 -3600
# Node ID 5f6b31335cdaee6a5ac8e93743e5fbad0109cfd2
# Parent  ba8d4bc2435a742f74909c3fc9efab1655aae41f
hvm: Fix some bugs in mmio decoder

Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require
the src immediate operand be sign-extented befere the op is executed,
but this is omitted in the current Xcode. The patch fixes this.
The patch also fixes an issue in handling address-size override
prefix, and fixes an issue in get_immediate().

Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
 xen/arch/x86/hvm/platform.c |   40 ++++++++++++++++++++++++++++++++++------
 1 files changed, 34 insertions(+), 6 deletions(-)

diff -r ba8d4bc2435a -r 5f6b31335cda xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Fri Apr 13 12:29:06 2007 +0100
+++ b/xen/arch/x86/hvm/platform.c       Fri Apr 13 12:30:04 2007 +0100
@@ -221,7 +221,6 @@ static inline unsigned long get_immediat
 
     inst++; //skip ModR/M byte
     if ( ad_size != WORD && mod != 3 && rm == 4 ) {
-        rm = *inst & 7;
         inst++; //skip SIB byte
     }
 
@@ -255,6 +254,33 @@ static inline unsigned long get_immediat
     }
 
     return val;
+}
+
+/* Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require
+ * the src immediate operand be sign-extented befere the op is executed. Here
+ * we always sign-extend the operand to a "unsigned long" variable.
+ *
+ * Note: to simplify the logic here, the sign-extension here may be performed
+ * redundantly against some instructions, like "MOV $imm16, r/m16" -- however
+ * this is harmless, since we always remember the operand's size.
+ */
+static inline unsigned long get_immediate_sign_ext(int ad_size,
+                                                   const unsigned char *inst,
+                                                   int op_size)
+{
+    unsigned long result = get_immediate(ad_size, inst, op_size);
+
+    if ( op_size == QUAD )
+        op_size = LONG;
+
+    ASSERT( op_size == BYTE || op_size == WORD || op_size == LONG );
+
+    if ( result & (1UL << ((8*op_size) - 1)) )
+    {
+        unsigned long mask = ~0UL >> (8 * (sizeof(mask) - op_size));
+        result = ~mask | (result & mask);
+    }
+    return result;
 }
 
 static inline int get_index(const unsigned char *inst, unsigned char rex)
@@ -394,7 +420,9 @@ static int mmio_decode(int address_bytes
     case 8:
         if ( *op_size == 0 )
             *op_size = rex & 0x8 ? QUAD : LONG;
-        if ( *ad_size == 0 )
+        if ( *ad_size == WORD )
+            *ad_size = LONG;
+        else if ( *ad_size == 0 )
             *ad_size = QUAD;
         break;
 #endif
@@ -520,10 +548,10 @@ static int mmio_decode(int address_bytes
         /* opcode 0x83 always has a single byte operand */
         if ( opcode[0] == 0x83 )
             mmio_op->immediate =
-                (signed char)get_immediate(*ad_size, opcode + 1, BYTE);
+                get_immediate_sign_ext(*ad_size, opcode + 1, BYTE);
         else
             mmio_op->immediate =
-                get_immediate(*ad_size, opcode + 1, *op_size);
+                get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
 
         mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
         mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
@@ -677,7 +705,7 @@ static int mmio_decode(int address_bytes
 
             mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE);
             mmio_op->immediate =
-                    get_immediate(*ad_size, opcode + 1, *op_size);
+                    get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
             mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
 
             return DECODE_success;
@@ -699,7 +727,7 @@ static int mmio_decode(int address_bytes
 
             mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
             mmio_op->immediate =
-                    get_immediate(*ad_size, opcode + 1, *op_size);
+                    get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
             mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
 
             return DECODE_success;

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