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] [XEN] Fix x86_emulate and hvm-mmio-insn-l

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEN] Fix x86_emulate and hvm-mmio-insn-len decoders
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 27 Sep 2006 09:50:23 +0000
Delivery-date: Wed, 27 Sep 2006 02:51:08 -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 kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID 8905ffc1a3c842fdb297c2e6f5153cfee9cb369d
# Parent  bd811e94d293ebcb8fb15db0becacd36c65a4ac7
[XEN] Fix x86_emulate and hvm-mmio-insn-len decoders
to properly add cs<<4 to eip only when guest is in real
mode (or vm86 mode).
Remove bogus test-and-fail from hvm-mmio-insn-len decoder.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/instrlen.c |   72 ++++++++++++++------------------------------
 xen/arch/x86/x86_emulate.c  |   37 +++++++++++-----------
 2 files changed, 43 insertions(+), 66 deletions(-)

diff -r bd811e94d293 -r 8905ffc1a3c8 xen/arch/x86/hvm/instrlen.c
--- a/xen/arch/x86/hvm/instrlen.c       Tue Sep 26 19:50:07 2006 +0100
+++ b/xen/arch/x86/hvm/instrlen.c       Wed Sep 27 09:29:46 2006 +0100
@@ -196,26 +196,17 @@ static uint8_t twobyte_table[256] = {
 
 /* 
  * insn_fetch - fetch the next 1 to 4 bytes from instruction stream 
- * 
  * @_type:   u8, u16, u32, s8, s16, or s32
  * @_size:   1, 2, or 4 bytes
- * @_eip:    address to fetch from guest memory
- * @_length: increments the current instruction length counter by _size
- *
- * This is used internally by hvm_instruction_length to fetch the next byte,
- * word, or dword from guest memory at location _eip.  we currently use a local
- * unsigned long as the storage buffer since the most bytes we're gonna get
- * is limited to 4.
- */
-#define insn_fetch(_type, _size, _eip, _length)                         \
-({  unsigned long _x;                                                   \
-        if ((rc = inst_copy_from_guest((unsigned char *)(&(_x)),        \
-                (unsigned long)(_eip), _size))                          \
-                    != _size)                                           \
-        goto done;                                                      \
-    (_eip) += (_size);                                                  \
-    (_length) += (_size);                                               \
-    (_type)_x;                                                          \
+ */
+#define insn_fetch(_type, _size)                                        \
+({ unsigned long _x, _ptr = _regs.eip;                                  \
+   if ( mode == X86EMUL_MODE_REAL ) _ptr += _regs.cs << 4;              \
+   rc = inst_copy_from_guest((unsigned char *)(&(_x)), _ptr, _size);    \
+   if ( rc != _size ) goto done;                                        \
+   _regs.eip += (_size);                                                \
+   length += (_size);                                                   \
+   (_type)_x;                                                           \
 })
 
 /**
@@ -231,17 +222,13 @@ int hvm_instruction_length(struct cpu_us
 {
     uint8_t b, d, twobyte = 0, rex_prefix = 0;
     uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
-    unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
+    unsigned int op_bytes, ad_bytes, i;
     int rc = 0;
     int length = 0;
     unsigned int tmp;
 
     /* Shadow copy of register state. Committed on successful emulation. */
     struct cpu_user_regs _regs = *regs;
-
-    /* include CS for 16-bit modes */
-    if (mode == X86EMUL_MODE_REAL || mode == X86EMUL_MODE_PROT16)
-        _regs.eip += (_regs.cs << 4);
 
     switch ( mode )
     {
@@ -265,7 +252,7 @@ int hvm_instruction_length(struct cpu_us
     /* Legacy prefixes. */
     for ( i = 0; i < 8; i++ )
     {
-        switch ( b = insn_fetch(uint8_t, 1, _regs.eip, length) )
+        switch ( b = insn_fetch(uint8_t, 1) )
         {
         case 0x66: /* operand-size override */
             op_bytes ^= 6;      /* switch between 2/4 bytes */
@@ -282,13 +269,8 @@ int hvm_instruction_length(struct cpu_us
         case 0x64: /* FS override */
         case 0x65: /* GS override */
         case 0x36: /* SS override */
-            break;
         case 0xf0: /* LOCK */
-            lock_prefix = 1;
-            break;
         case 0xf3: /* REP/REPE/REPZ */
-            rep_prefix = 1;
-            break;
         case 0xf2: /* REPNE/REPNZ */
             break;
         default:
@@ -296,12 +278,6 @@ int hvm_instruction_length(struct cpu_us
         }
     }
 done_prefixes:
-
-    /* Note quite the same as 80386 real mode, but hopefully good enough. */
-    if ( (mode == X86EMUL_MODE_REAL) && (ad_bytes != 2) ) {
-        printf("sonofabitch!! we don't support 32-bit addresses in 
realmode\n");
-        goto cannot_emulate;
-    }
 
     /* REX prefix. */
     if ( (mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40) )
@@ -311,7 +287,7 @@ done_prefixes:
             op_bytes = 8;          /* REX.W */
         modrm_reg = (b & 4) << 1;  /* REX.R */
         /* REX.B and REX.X do not need to be decoded. */
-        b = insn_fetch(uint8_t, 1, _regs.eip, length);
+        b = insn_fetch(uint8_t, 1);
     }
 
     /* Opcode byte(s). */
@@ -322,7 +298,7 @@ done_prefixes:
         if ( b == 0x0f )
         {
             twobyte = 1;
-            b = insn_fetch(uint8_t, 1, _regs.eip, length);
+            b = insn_fetch(uint8_t, 1);
             d = twobyte_table[b];
         }
 
@@ -334,7 +310,7 @@ done_prefixes:
     /* ModRM and SIB bytes. */
     if ( d & ModRM )
     {
-        modrm = insn_fetch(uint8_t, 1, _regs.eip, length);
+        modrm = insn_fetch(uint8_t, 1);
         modrm_mod |= (modrm & 0xc0) >> 6;
         modrm_reg |= (modrm & 0x38) >> 3;
         modrm_rm  |= (modrm & 0x07);
@@ -374,7 +350,7 @@ done_prefixes:
             {
             case 0:
                 if ( (modrm_rm == 4) && 
-                     (((insn_fetch(uint8_t, 1, _regs.eip, length)) & 7) 
+                     (((insn_fetch(uint8_t, 1)) & 7) 
                         == 5) )
                 {
                     length += 4;
@@ -389,7 +365,7 @@ done_prefixes:
             case 1:
                 if ( modrm_rm == 4 )
                 {
-                    insn_fetch(uint8_t, 1, _regs.eip, length);
+                    insn_fetch(uint8_t, 1);
                 }
                 length += 1;
                 _regs.eip += 1; /* skip disp8 */
@@ -397,7 +373,7 @@ done_prefixes:
             case 2:
                 if ( modrm_rm == 4 )
                 {
-                    insn_fetch(uint8_t, 1, _regs.eip, length);
+                    insn_fetch(uint8_t, 1);
                 }
                 length += 4;
                 _regs.eip += 4; /* skip disp32 */
@@ -423,13 +399,13 @@ done_prefixes:
         /* NB. Immediates are sign-extended as necessary. */
         switch ( tmp )
         {
-        case 1: insn_fetch(int8_t,  1, _regs.eip, length); break;
-        case 2: insn_fetch(int16_t, 2, _regs.eip, length); break;
-        case 4: insn_fetch(int32_t, 4, _regs.eip, length); break;
+        case 1: insn_fetch(int8_t,  1); break;
+        case 2: insn_fetch(int16_t, 2); break;
+        case 4: insn_fetch(int32_t, 4); break;
         }
         break;
     case SrcImmByte:
-        insn_fetch(int8_t,  1, _regs.eip, length);
+        insn_fetch(int8_t,  1);
         break;
     }
 
@@ -455,9 +431,9 @@ done_prefixes:
             if ( tmp == 8 ) tmp = 4;
             switch ( tmp )
             {
-            case 1: insn_fetch(int8_t,  1, _regs.eip, length); break;
-            case 2: insn_fetch(int16_t, 2, _regs.eip, length); break;
-            case 4: insn_fetch(int32_t, 4, _regs.eip, length); break;
+            case 1: insn_fetch(int8_t,  1); break;
+            case 2: insn_fetch(int16_t, 2); break;
+            case 4: insn_fetch(int32_t, 4); break;
             }
             goto done;
         }
diff -r bd811e94d293 -r 8905ffc1a3c8 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Tue Sep 26 19:50:07 2006 +0100
+++ b/xen/arch/x86/x86_emulate.c        Wed Sep 27 09:29:46 2006 +0100
@@ -368,12 +368,13 @@ do{ __asm__ __volatile__ (              
 #endif /* __i386__ */
 
 /* Fetch next part of the instruction being emulated. */
-#define insn_fetch(_type, _size, _eip)                                  \
-({ unsigned long _x;                                                    \
-   rc = ops->read_std((unsigned long)(_eip), &_x, (_size), ctxt);       \
+#define insn_fetch(_type, _size)                                        \
+({ unsigned long _x, _ptr = _regs.eip;                                  \
+   if ( mode == X86EMUL_MODE_REAL ) _ptr += _regs.cs << 4;              \
+   rc = ops->read_std(_ptr, &_x, (_size), ctxt);                        \
    if ( rc != 0 )                                                       \
        goto done;                                                       \
-   (_eip) += (_size);                                                   \
+   _regs.eip += (_size);                                                \
    (_type)_x;                                                           \
 })
 
@@ -478,7 +479,7 @@ x86_emulate_memop(
     /* Legacy prefixes. */
     for ( i = 0; i < 8; i++ )
     {
-        switch ( b = insn_fetch(uint8_t, 1, _regs.eip) )
+        switch ( b = insn_fetch(uint8_t, 1) )
         {
         case 0x66: /* operand-size override */
             op_bytes ^= 6;      /* switch between 2/4 bytes */
@@ -529,7 +530,7 @@ x86_emulate_memop(
             op_bytes = 8;          /* REX.W */
         modrm_reg = (b & 4) << 1;  /* REX.R */
         /* REX.B and REX.X do not need to be decoded. */
-        b = insn_fetch(uint8_t, 1, _regs.eip);
+        b = insn_fetch(uint8_t, 1);
     }
 
     /* Opcode byte(s). */
@@ -540,7 +541,7 @@ x86_emulate_memop(
         if ( b == 0x0f )
         {
             twobyte = 1;
-            b = insn_fetch(uint8_t, 1, _regs.eip);
+            b = insn_fetch(uint8_t, 1);
             d = twobyte_table[b];
         }
 
@@ -552,7 +553,7 @@ x86_emulate_memop(
     /* ModRM and SIB bytes. */
     if ( d & ModRM )
     {
-        modrm = insn_fetch(uint8_t, 1, _regs.eip);
+        modrm = insn_fetch(uint8_t, 1);
         modrm_mod |= (modrm & 0xc0) >> 6;
         modrm_reg |= (modrm & 0x38) >> 3;
         modrm_rm  |= (modrm & 0x07);
@@ -587,19 +588,19 @@ x86_emulate_memop(
             {
             case 0:
                 if ( (modrm_rm == 4) && 
-                     (((sib = insn_fetch(uint8_t, 1, _regs.eip)) & 7) == 5) )
+                     (((sib = insn_fetch(uint8_t, 1)) & 7) == 5) )
                     _regs.eip += 4; /* skip disp32 specified by SIB.base */
                 else if ( modrm_rm == 5 )
                     _regs.eip += 4; /* skip disp32 */
                 break;
             case 1:
                 if ( modrm_rm == 4 )
-                    sib = insn_fetch(uint8_t, 1, _regs.eip);
+                    sib = insn_fetch(uint8_t, 1);
                 _regs.eip += 1; /* skip disp8 */
                 break;
             case 2:
                 if ( modrm_rm == 4 )
-                    sib = insn_fetch(uint8_t, 1, _regs.eip);
+                    sib = insn_fetch(uint8_t, 1);
                 _regs.eip += 4; /* skip disp32 */
                 break;
             }
@@ -691,16 +692,16 @@ x86_emulate_memop(
         /* NB. Immediates are sign-extended as necessary. */
         switch ( src.bytes )
         {
-        case 1: src.val = insn_fetch(int8_t,  1, _regs.eip); break;
-        case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break;
-        case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break;
+        case 1: src.val = insn_fetch(int8_t,  1); break;
+        case 2: src.val = insn_fetch(int16_t, 2); break;
+        case 4: src.val = insn_fetch(int32_t, 4); break;
         }
         break;
     case SrcImmByte:
         src.type  = OP_IMM;
         src.ptr   = (unsigned long *)_regs.eip;
         src.bytes = 1;
-        src.val   = insn_fetch(int8_t,  1, _regs.eip);
+        src.val   = insn_fetch(int8_t,  1);
         break;
     }
 
@@ -840,9 +841,9 @@ x86_emulate_memop(
             if ( src.bytes == 8 ) src.bytes = 4;
             switch ( src.bytes )
             {
-            case 1: src.val = insn_fetch(int8_t,  1, _regs.eip); break;
-            case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break;
-            case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break;
+            case 1: src.val = insn_fetch(int8_t,  1); break;
+            case 2: src.val = insn_fetch(int16_t, 2); break;
+            case 4: src.val = insn_fetch(int32_t, 4); break;
             }
             goto test;
         case 2: /* not */

_______________________________________________
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] [XEN] Fix x86_emulate and hvm-mmio-insn-len decoders, Xen patchbot-unstable <=