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(®s, 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(®s, 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
|