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

[Xen-changelog] [xen-unstable] [XEN] Fix/implement JMP/CALL/RET emulation.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1168537633 0
# Node ID f455a26a4170b84e3bcbda1c8701c89cb66380ac
# Parent  66eba8d1b83a9d22b5b88d0f11fe8aa79895f1cb
[XEN] Fix/implement JMP/CALL/RET emulation.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/x86_emulate.c |   96 ++++++++++++++++++++++++++++++++++++---------
 1 files changed, 77 insertions(+), 19 deletions(-)

diff -r 66eba8d1b83a -r f455a26a4170 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Thu Jan 11 17:03:11 2007 +0000
+++ b/xen/arch/x86/x86_emulate.c        Thu Jan 11 17:47:13 2007 +0000
@@ -85,9 +85,11 @@ static uint8_t opcode_table[256] = {
     ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov,
     ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov,
     ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov,
-    /* 0x60 - 0x6F */
+    /* 0x60 - 0x67 */
     0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0,
+    /* 0x68 - 0x6F */
+    ImplicitOps|Mov, 0, ImplicitOps|Mov, 0, 0, 0, 0, 0,
     /* 0x70 - 0x77 */
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -125,7 +127,8 @@ static uint8_t opcode_table[256] = {
     DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov,
     DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov,
     /* 0xC0 - 0xC7 */
-    ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0,
+    ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM,
+    ImplicitOps, ImplicitOps,
     0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov,
     /* 0xC8 - 0xCF */
     0, 0, 0, 0, 0, 0, 0, 0,
@@ -138,7 +141,7 @@ static uint8_t opcode_table[256] = {
     /* 0xE0 - 0xE7 */
     0, 0, 0, ImplicitOps, 0, 0, 0, 0,
     /* 0xE8 - 0xEF */
-    0, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0,
+    ImplicitOps, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0,
     /* 0xF0 - 0xF7 */
     0, 0, 0, 0,
     0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
@@ -1110,6 +1113,20 @@ x86_emulate(
         case 1: /* dec */
             emulate_1op("dec", dst, _regs.eflags);
             break;
+        case 2: /* call (near) */
+        case 3: /* jmp (near) */
+            if ( ((op_bytes = dst.bytes) != 8) && mode_64bit() )
+            {
+                dst.bytes = op_bytes = 8;
+                if ( (rc = ops->read(dst.mem.seg, dst.mem.off,
+                                     &dst.val, 8, ctxt)) != 0 )
+                    goto done;
+            }
+            src.val = _regs.eip;
+            _regs.eip = dst.val;
+            if ( (modrm_reg & 7) == 2 )
+                goto push; /* call */
+            break;
         case 6: /* push */
             /* 64-bit mode: PUSH defaults to a 64-bit operand. */
             if ( mode_64bit() && (dst.bytes == 4) )
@@ -1264,16 +1281,9 @@ x86_emulate(
         break;
 
     case 0x50 ... 0x57: /* push reg */
-        dst.type  = OP_MEM;
-        dst.bytes = op_bytes;
-        if ( mode_64bit() && (dst.bytes == 4) )
-            dst.bytes = 8;
-        dst.val = *(unsigned long *)decode_register(
+        src.val = *(unsigned long *)decode_register(
             (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);
-        register_address_increment(_regs.esp, -dst.bytes);
-        dst.mem.seg = x86_seg_ss;
-        dst.mem.off = truncate_ea(_regs.esp);
-        break;
+        goto push;
 
     case 0x58 ... 0x5f: /* pop reg */
         dst.type  = OP_REG;
@@ -1286,6 +1296,26 @@ x86_emulate(
                              &dst.val, dst.bytes, ctxt)) != 0 )
             goto done;
         register_address_increment(_regs.esp, dst.bytes);
+        break;
+
+    case 0x68: /* push imm{16,32,64} */
+        src.val = ((op_bytes == 2)
+                   ? (int32_t)insn_fetch_type(int16_t)
+                   : insn_fetch_type(int32_t));
+        goto push;
+
+    case 0x6a: /* push imm8 */
+        src.val = insn_fetch_type(int8_t);
+    push:
+        d |= Mov; /* force writeback */
+        dst.type  = OP_MEM;
+        dst.bytes = op_bytes;
+        if ( mode_64bit() && (dst.bytes == 4) )
+            dst.bytes = 8;
+        dst.val = src.val;
+        register_address_increment(_regs.esp, -dst.bytes);
+        dst.mem.seg = x86_seg_ss;
+        dst.mem.off = truncate_ea(_regs.esp);
         break;
 
     case 0x70 ... 0x7f: /* jcc (short) */ {
@@ -1371,6 +1401,18 @@ x86_emulate(
             _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
         break;
 
+    case 0xc2: /* ret imm16 (near) */
+    case 0xc3: /* ret (near) */ {
+        int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0;
+        op_bytes = mode_64bit() ? 8 : op_bytes;
+        if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp),
+                             &dst.val, op_bytes, ctxt)) != 0 )
+            goto done;
+        _regs.eip = dst.val;
+        register_address_increment(_regs.esp, op_bytes + offset);
+        break;
+    }
+
     case 0xd4: /* aam */ {
         unsigned int base = insn_fetch_type(uint8_t);
         uint8_t al = _regs.eax;
@@ -1418,12 +1460,26 @@ x86_emulate(
         break;
     }
 
-    case 0xe9: /* jmp (short) */
+    case 0xe8: /* call (near) */ {
+        int rel = (((op_bytes == 2) && !mode_64bit())
+                   ? (int32_t)insn_fetch_type(int16_t)
+                   : insn_fetch_type(int32_t));
+        op_bytes = mode_64bit() ? 8 : op_bytes;
+        src.val = _regs.eip;
+        jmp_rel(rel);
+        goto push;
+    }
+
+    case 0xe9: /* jmp (near) */ {
+        int rel = (((op_bytes == 2) && !mode_64bit())
+                   ? (int32_t)insn_fetch_type(int16_t)
+                   : insn_fetch_type(int32_t));
+        jmp_rel(rel);
+        break;
+    }
+
+    case 0xeb: /* jmp (short) */
         jmp_rel(insn_fetch_type(int8_t));
-        break;
-
-    case 0xeb: /* jmp (near) */
-        jmp_rel(insn_fetch_bytes(mode_64bit() ? 4 : op_bytes));
         break;
 
     case 0xf5: /* cmc */
@@ -1550,7 +1606,9 @@ x86_emulate(
         break;
 
     case 0x80 ... 0x8f: /* jcc (near) */ {
-        int rel = insn_fetch_bytes(mode_64bit() ? 4 : op_bytes);
+        int rel = (((op_bytes == 2) && !mode_64bit())
+                   ? (int32_t)insn_fetch_type(int16_t)
+                   : insn_fetch_type(int32_t));
         if ( test_cc(b, _regs.eflags) )
             jmp_rel(rel);
         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®.