[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Add CMPXCHG8B support to the instruction emulator.
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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |