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] Add CMPXCHG8B support to the instruction emulator.

To: xen-changelog@xxxxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Add CMPXCHG8B support to the instruction emulator.
From: BitKeeper Bot <riel@xxxxxxxxxxx>
Date: Mon, 21 Mar 2005 18:04:36 +0000
Delivery-date: Mon, 21 Mar 2005 19:04:55 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-archive: <http://sourceforge.net/mailarchive/forum.php?forum=xen-changelog>
List-help: <mailto:xen-changelog-request@lists.sourceforge.net?subject=help>
List-id: <xen-changelog.lists.sourceforge.net>
List-post: <mailto:xen-changelog@lists.sourceforge.net>
List-subscribe: <https://lists.sourceforge.net/lists/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.sourceforge.net?subject=subscribe>
List-unsubscribe: <https://lists.sourceforge.net/lists/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.sourceforge.net?subject=unsubscribe>
Reply-to: Xen Development List <xen-devel@xxxxxxxxxxxxxxxxxxxxx>
Sender: xen-changelog-admin@xxxxxxxxxxxxxxxxxxxxx
ChangeSet 1.1337, 2005/03/21 18:04:36+00:00, kaf24@xxxxxxxxxxxxxxxxxxxx

        Add CMPXCHG8B support to the instruction emulator.
        Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>



 tools/tests/test_x86_emulator.c   |   52 +++++++++++++++++++++++++++++++-
 xen/arch/x86/x86_emulate.c        |   61 ++++++++++++++++++++++++++++++++++++--
 xen/include/asm-x86/x86_emulate.h |   21 +++++++++++++
 3 files changed, 129 insertions(+), 5 deletions(-)


diff -Nru a/tools/tests/test_x86_emulator.c b/tools/tests/test_x86_emulator.c
--- a/tools/tests/test_x86_emulator.c   2005-03-21 14:03:00 -05:00
+++ b/tools/tests/test_x86_emulator.c   2005-03-21 14:03:00 -05:00
@@ -60,15 +60,28 @@
     return X86EMUL_CONTINUE;
 }
 
+static int cmpxchg8b_any(
+    unsigned long addr,
+    unsigned long old_lo,
+    unsigned long old_hi,
+    unsigned long new_lo,
+    unsigned long new_hi)
+{
+    ((unsigned long *)addr)[0] = new_lo;
+    ((unsigned long *)addr)[1] = new_hi;
+    return X86EMUL_CONTINUE;
+}
+
 static struct x86_mem_emulator emulops = {
-    read_any, write_any, read_any, write_any, cmpxchg_any
+    read_any, write_any, read_any, write_any, cmpxchg_any, cmpxchg8b_any
 };
 
 int main(int argc, char **argv)
 {
     struct xen_regs regs;
-    char instr[] = { 0x01, 0x08 }; /* add %ecx,(%eax) */
+    char instr[20] = { 0x01, 0x08 }; /* add %ecx,(%eax) */
     unsigned int res = 0x7FFFFFFF;
+    u32 cmpxchg8b_res[2] = { 0x12345678, 0x87654321 };
     unsigned long cr2;
     int rc;
 
@@ -170,6 +183,41 @@
          (res != 0x2233445D) ||
          ((regs.eflags&0x201) != 0x201) ||
          (regs.eip != (unsigned long)&instr[4]) )
+        goto fail;
+    printf("okay\n");
+
+    printf("%-40s", "Testing cmpxchg (%edi) [succeeding]...");
+    instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f;
+    regs.eflags = 0x200;
+    regs.eax    = cmpxchg8b_res[0];
+    regs.edx    = cmpxchg8b_res[1];
+    regs.ebx    = 0x9999AAAA;
+    regs.ecx    = 0xCCCCFFFF;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.edi    = (unsigned long)cmpxchg8b_res;
+    cr2         = regs.edi;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
+    if ( (rc != 0) || 
+         (cmpxchg8b_res[0] != 0x9999AAAA) ||
+         (cmpxchg8b_res[1] != 0xCCCCFFFF) ||
+         ((regs.eflags&0x240) != 0x240) ||
+         (regs.eip != (unsigned long)&instr[3]) )
+        goto fail;
+    printf("okay\n");
+
+    printf("%-40s", "Testing cmpxchg (%edi) [failing]...");
+    instr[0] = 0x0f; instr[1] = 0xc7; instr[2] = 0x0f;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.edi    = (unsigned long)cmpxchg8b_res;
+    cr2         = regs.edi;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
+    if ( (rc != 0) || 
+         (cmpxchg8b_res[0] != 0x9999AAAA) ||
+         (cmpxchg8b_res[1] != 0xCCCCFFFF) ||
+         (regs.eax != 0x9999AAAA) ||
+         (regs.edx != 0xCCCCFFFF) ||
+         ((regs.eflags&0x240) != 0x200) ||
+         (regs.eip != (unsigned long)&instr[3]) )
         goto fail;
     printf("okay\n");
 
diff -Nru a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        2005-03-21 14:03:00 -05:00
+++ b/xen/arch/x86/x86_emulate.c        2005-03-21 14:03:00 -05:00
@@ -181,7 +181,7 @@
     /* 0xB8 - 0xBF */
     0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, 0, 0, 0, 0,
     /* 0xC0 - 0xCF */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0xD0 - 0xDF */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0xE0 - 0xEF */
@@ -963,8 +963,63 @@
     goto writeback;
 
  twobyte_special_insn:
-    /* Only prefetch instructions get here, so nothing to do. */
-    dst.orig_val = dst.val; /* disable writeback */
+    /* Disable writeback. */
+    dst.orig_val = dst.val;
+    switch ( b )
+    {
+    case 0x0d: /* GrpP (prefetch) */
+    case 0x18: /* Grp16 (prefetch/nop) */
+        break;
+    case 0xc7: /* Grp9 (cmpxchg8b) */
+#if defined(__i386__)
+    {
+        unsigned long old_lo, old_hi;
+        if ( ((rc = ops->read_emulated(cr2+0, &old_lo, 4)) != 0) ||
+             ((rc = ops->read_emulated(cr2+4, &old_hi, 4)) != 0) )
+            goto done;
+        if ( (old_lo != _regs.eax) || (old_hi != _regs.edx) )
+        {
+            _regs.eax = old_lo;
+            _regs.edx = old_hi;
+            _regs.eflags &= ~EFLG_ZF;
+        }
+        else if ( ops->cmpxchg8b_emulated == NULL )
+        {
+            rc = X86EMUL_UNHANDLEABLE;
+            goto done;
+        }
+        else
+        {
+            if ( (rc = ops->cmpxchg8b_emulated(cr2, old_lo, old_hi,
+                                               _regs.ebx, _regs.ecx)) != 0 )
+                goto done;
+            _regs.eflags |= EFLG_ZF;
+        }
+        break;
+    }
+#elif defined(__x86_64__)
+    {
+        unsigned long old, new;
+        if ( (rc = ops->read_emulated(cr2, &old, 8)) != 0 )
+            goto done;
+        if ( ((u32)(old>>0) != (u32)_regs.eax) ||
+             ((u32)(old>>32) != (u32)_regs.edx) )
+        {
+            _regs.eax = (u32)(old>>0);
+            _regs.edx = (u32)(old>>32);
+            _regs.eflags &= ~EFLG_ZF;
+        }
+        else
+        {
+            new = (_regs.ecx<<32)|(u32)_regs.ebx;
+            if ( (rc = ops->cmpxchg_emulated(cr2, old, new, 8)) != 0 )
+                goto done;
+            _regs.eflags |= EFLG_ZF;
+        }
+        break;
+    }
+#endif
+    }
     goto writeback;
 
  cannot_emulate:
diff -Nru a/xen/include/asm-x86/x86_emulate.h 
b/xen/include/asm-x86/x86_emulate.h
--- a/xen/include/asm-x86/x86_emulate.h 2005-03-21 14:03:00 -05:00
+++ b/xen/include/asm-x86/x86_emulate.h 2005-03-21 14:03:00 -05:00
@@ -34,6 +34,8 @@
  *     some out-of-band mechanism, unknown to the emulator. The memop signals
  *     failure by returning X86EMUL_PROPAGATE_FAULT to the emulator, which will
  *     then immediately bail.
+ *  3. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only
+ *     cmpxchg8b_emulated need support 8-byte accesses.
  */
 /* Access completed successfully: continue emulation as normal. */
 #define X86EMUL_CONTINUE        0
@@ -104,6 +106,25 @@
         unsigned long old,
         unsigned long new,
         unsigned int bytes);
+
+    /*
+     * cmpxchg_emulated: Emulate an atomic (LOCKed) CMPXCHG8B operation on an
+     *                   emulated/special memory area.
+     *  @addr:  [IN ] Linear address to access.
+     *  @old:   [IN ] Value expected to be current at @addr.
+     *  @new:   [IN ] Value to write to @addr.
+     * NOTES:
+     *  1. This function is only ever called when emulating a real CMPXCHG8B.
+     *  2. This function is *never* called on x86/64 systems.
+     *  2. Not defining this function (i.e., specifying NULL) is equivalent
+     *     to defining a function that always returns X86EMUL_UNHANDLEABLE.
+     */
+    int (*cmpxchg8b_emulated)(
+        unsigned long addr,
+        unsigned long old_lo,
+        unsigned long old_hi,
+        unsigned long new_lo,
+        unsigned long new_hi);
 };
 
 /* Standard reader/writer functions that callers may wish to use. */


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Add CMPXCHG8B support to the instruction emulator., BitKeeper Bot <=