[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: Extend emulator return codes.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1172087938 0 # Node ID b010e556fe2c1e7cf73d3f279113ba1f4eac6a11 # Parent ad3ee81cc8c4bf44edc01404782c7a197f8764fc x86: Extend emulator return codes. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- tools/tests/test_x86_emulator.c | 48 +++++++++++++++++++------------------- xen/arch/x86/mm.c | 17 +++++++------ xen/arch/x86/mm/shadow/common.c | 16 ++++++------ xen/arch/x86/mm/shadow/multi.c | 19 ++++++++------- xen/arch/x86/x86_emulate.c | 16 ++++++------ xen/include/asm-x86/x86_emulate.h | 24 +++++++++++-------- 6 files changed, 76 insertions(+), 64 deletions(-) diff -r ad3ee81cc8c4 -r b010e556fe2c tools/tests/test_x86_emulator.c --- a/tools/tests/test_x86_emulator.c Wed Feb 21 11:42:04 2007 -0800 +++ b/tools/tests/test_x86_emulator.c Wed Feb 21 19:58:58 2007 +0000 @@ -43,7 +43,7 @@ static int read( case 4: *val = *(u32 *)addr; break; case 8: *val = *(unsigned long *)addr; break; } - return X86EMUL_CONTINUE; + return X86EMUL_OKAY; } static int write( @@ -61,7 +61,7 @@ static int write( case 4: *(u32 *)addr = (u32)val; break; case 8: *(unsigned long *)addr = val; break; } - return X86EMUL_CONTINUE; + return X86EMUL_OKAY; } static int cmpxchg( @@ -80,7 +80,7 @@ static int cmpxchg( case 4: *(u32 *)addr = (u32)new; break; case 8: *(unsigned long *)addr = new; break; } - return X86EMUL_CONTINUE; + return X86EMUL_OKAY; } static int cmpxchg8b( @@ -95,7 +95,7 @@ static int cmpxchg8b( unsigned long addr = offset; ((unsigned long *)addr)[0] = new_lo; ((unsigned long *)addr)[1] = new_hi; - return X86EMUL_CONTINUE; + return X86EMUL_OKAY; } static struct x86_emulate_ops emulops = { @@ -138,7 +138,7 @@ int main(int argc, char **argv) regs.eax = (unsigned long)res; *res = 0x7FFFFFFF; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x92345677) || (regs.eflags != 0xa94) || (regs.eip != (unsigned long)&instr[2]) ) @@ -152,7 +152,7 @@ int main(int argc, char **argv) regs.ecx = 0x12345678; regs.eax = 0x7FFFFFFF; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (regs.ecx != 0x12345678) || (regs.eax != 0x92345677) || (regs.eflags != 0xa94) || @@ -171,7 +171,7 @@ int main(int argc, char **argv) #endif regs.eax = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x92345677) || (regs.ecx != 0x8000000FUL) || (regs.eip != (unsigned long)&instr[2]) ) @@ -185,7 +185,7 @@ int main(int argc, char **argv) regs.ecx = ~0UL; regs.eax = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x92345677) || (regs.ecx != 0x92345677UL) || (regs.eip != (unsigned long)&instr[2]) ) @@ -200,7 +200,7 @@ int main(int argc, char **argv) regs.ecx = 0xAA; regs.ebx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x923456AA) || (regs.eflags != 0x244) || (regs.eax != 0x92345677UL) || @@ -216,7 +216,7 @@ int main(int argc, char **argv) regs.ecx = 0xFF; regs.ebx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x923456AA) || ((regs.eflags&0x240) != 0x200) || (regs.eax != 0xAABBCCAA) || @@ -232,7 +232,7 @@ int main(int argc, char **argv) regs.ecx = 0x12345678; regs.eax = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x12345678) || (regs.eflags != 0x200) || (regs.ecx != 0x923456AA) || @@ -249,7 +249,7 @@ int main(int argc, char **argv) regs.ecx = 0xDDEEFF00L; regs.ebx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0xDDEEFF00) || (regs.eflags != 0x244) || (regs.eax != 0x923456AAUL) || @@ -266,7 +266,7 @@ int main(int argc, char **argv) regs.esi = (unsigned long)res + 0; regs.edi = (unsigned long)res + 2; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x44554455) || (regs.eflags != 0x200) || (regs.ecx != 22) || @@ -283,7 +283,7 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x2233445D) || ((regs.eflags&0x201) != 0x201) || (regs.eip != (unsigned long)&instr[4]) ) @@ -298,7 +298,7 @@ int main(int argc, char **argv) regs.eax = -32; regs.edi = (unsigned long)(res+1); rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x2233445E) || ((regs.eflags&0x201) != 0x201) || (regs.eip != (unsigned long)&instr[3]) ) @@ -318,7 +318,7 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (res[0] != 0x9999AAAA) || (res[1] != 0xCCCCFFFF) || ((regs.eflags&0x240) != 0x240) || @@ -332,7 +332,7 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (res[0] != 0x9999AAAA) || (res[1] != 0xCCCCFFFF) || (regs.eax != 0x9999AAAA) || @@ -350,7 +350,7 @@ int main(int argc, char **argv) regs.eax = (unsigned long)res; *res = 0x82; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x82) || (regs.ecx != 0xFFFFFF82) || ((regs.eflags&0x240) != 0x200) || @@ -366,7 +366,7 @@ int main(int argc, char **argv) regs.eax = (unsigned long)res; *res = 0x1234aa82; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x1234aa82) || (regs.ecx != 0xaa82) || ((regs.eflags&0x240) != 0x200) || @@ -382,7 +382,7 @@ int main(int argc, char **argv) regs.eax = 0x12345678; *res = 0x11111111; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (*res != 0x11116789) || (regs.eax != 0x12341111) || ((regs.eflags&0x240) != 0x200) || @@ -396,7 +396,7 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.eax = 0x00000000; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (regs.eax != 0x0000ffff) || ((regs.eflags&0x240) != 0x200) || (regs.eip != (unsigned long)&instr[2]) ) @@ -410,7 +410,7 @@ int main(int argc, char **argv) regs.eax = 0x12345678; regs.ebp = 0xaaaaaaaa; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != 0) || + if ( (rc != X86EMUL_OKAY) || (regs.eax != 0xaaaaaab2) || ((regs.eflags&0x240) != 0x200) || (regs.eip != (unsigned long)&instr[3]) ) @@ -454,7 +454,7 @@ int main(int argc, char **argv) bcdres_emul |= (regs.eflags & EFLG_SF) ? 0x400 : 0; bcdres_emul |= (regs.eflags & EFLG_CF) ? 0x200 : 0; bcdres_emul |= (regs.eflags & EFLG_AF) ? 0x100 : 0; - if ( (rc != 0) || (regs.eax > 255) || + if ( (rc != X86EMUL_OKAY) || (regs.eax > 255) || (regs.eip != (unsigned long)&instr[1]) ) goto fail; @@ -501,7 +501,7 @@ int main(int argc, char **argv) if ( (i++ & 8191) == 0 ) printf("."); rc = x86_emulate(&ctxt, &emulops); - if ( rc != 0 ) + if ( rc != X86EMUL_OKAY ) { printf("failed at %%eip == %08x\n", (unsigned int)regs.eip); return 1; diff -r ad3ee81cc8c4 -r b010e556fe2c xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Wed Feb 21 11:42:04 2007 -0800 +++ b/xen/arch/x86/mm.c Wed Feb 21 19:58:58 2007 +0000 @@ -3151,10 +3151,10 @@ static int ptwr_emulated_read( if ( (rc = copy_from_user((void *)val, (void *)addr, bytes)) != 0 ) { propagate_page_fault(addr + bytes - rc, 0); /* read fault */ - return X86EMUL_PROPAGATE_FAULT; - } - - return X86EMUL_CONTINUE; + return X86EMUL_EXCEPTION; + } + + return X86EMUL_OKAY; } static int ptwr_emulated_update( @@ -3190,7 +3190,7 @@ static int ptwr_emulated_update( if ( (rc = copy_from_user(&full, (void *)addr, sizeof(paddr_t))) != 0 ) { propagate_page_fault(addr+sizeof(paddr_t)-rc, 0); /* read fault */ - return X86EMUL_PROPAGATE_FAULT; + return X86EMUL_EXCEPTION; } /* Mask out bits provided by caller. */ full &= ~((((paddr_t)1 << (bytes*8)) - 1) << (offset*8)); @@ -3273,7 +3273,7 @@ static int ptwr_emulated_update( /* Finally, drop the old PTE. */ put_page_from_l1e(gl1e_to_ml1e(d, ol1e), d); - return X86EMUL_CONTINUE; + return X86EMUL_OKAY; } static int ptwr_emulated_write( @@ -3333,6 +3333,7 @@ int ptwr_do_page_fault(struct vcpu *v, u struct page_info *page; l1_pgentry_t pte; struct ptwr_emulate_ctxt ptwr_ctxt; + int rc; LOCK_BIGLOCK(d); @@ -3357,7 +3358,9 @@ int ptwr_do_page_fault(struct vcpu *v, u IS_COMPAT(d) ? 32 : BITS_PER_LONG; ptwr_ctxt.cr2 = addr; ptwr_ctxt.pte = pte; - if ( x86_emulate(&ptwr_ctxt.ctxt, &ptwr_emulate_ops) ) + + rc = x86_emulate(&ptwr_ctxt.ctxt, &ptwr_emulate_ops); + if ( rc == X86EMUL_UNHANDLEABLE ) goto bail; UNLOCK_BIGLOCK(d); diff -r ad3ee81cc8c4 -r b010e556fe2c xen/arch/x86/mm/shadow/common.c --- a/xen/arch/x86/mm/shadow/common.c Wed Feb 21 11:42:04 2007 -0800 +++ b/xen/arch/x86/mm/shadow/common.c Wed Feb 21 19:58:58 2007 +0000 @@ -191,7 +191,7 @@ static int hvm_translate_linear_addr( gpf: /* Inject #GP(0). */ hvm_inject_exception(TRAP_gp_fault, 0, 0); - return X86EMUL_PROPAGATE_FAULT; + return X86EMUL_EXCEPTION; } static int @@ -216,7 +216,7 @@ hvm_read(enum x86_segment seg, // In this case, that is only a user vs supervisor access check. // if ( (rc = hvm_copy_from_guest_virt(val, addr, bytes)) == 0 ) - return X86EMUL_CONTINUE; + return X86EMUL_OKAY; /* If we got here, there was nothing mapped here, or a bad GFN * was mapped here. This should never happen: we're here because @@ -226,7 +226,7 @@ hvm_read(enum x86_segment seg, if ( access_type == hvm_access_insn_fetch ) errcode |= PFEC_insn_fetch; hvm_inject_exception(TRAP_page_fault, errcode, addr + bytes - rc); - return X86EMUL_PROPAGATE_FAULT; + return X86EMUL_EXCEPTION; } static int @@ -259,7 +259,7 @@ hvm_emulate_insn_fetch(enum x86_segment /* Hit the cache. Simple memcpy. */ *val = 0; memcpy(val, &sh_ctxt->insn_buf[insn_off], bytes); - return X86EMUL_CONTINUE; + return X86EMUL_OKAY; } static int @@ -352,10 +352,10 @@ pv_emulate_read(enum x86_segment seg, if ( (rc = copy_from_user((void *)val, (void *)offset, bytes)) != 0 ) { propagate_page_fault(offset + bytes - rc, 0); /* read fault */ - return X86EMUL_PROPAGATE_FAULT; - } - - return X86EMUL_CONTINUE; + return X86EMUL_EXCEPTION; + } + + return X86EMUL_OKAY; } static int diff -r ad3ee81cc8c4 -r b010e556fe2c xen/arch/x86/mm/shadow/multi.c --- a/xen/arch/x86/mm/shadow/multi.c Wed Feb 21 11:42:04 2007 -0800 +++ b/xen/arch/x86/mm/shadow/multi.c Wed Feb 21 19:58:58 2007 +0000 @@ -2911,8 +2911,11 @@ static int sh_page_fault(struct vcpu *v, * page is no longer a page table. This behaviour differs from native, but * it seems very unlikely that any OS grants user access to page tables. */ - if ( (regs->error_code & PFEC_user_mode) || - x86_emulate(&emul_ctxt.ctxt, emul_ops) ) + r = X86EMUL_UNHANDLEABLE; + if ( !(regs->error_code & PFEC_user_mode) ) + r = x86_emulate(&emul_ctxt.ctxt, emul_ops); + + if ( (r == X86EMUL_UNHANDLEABLE) || (r == X86EMUL_EXCEPTION) ) { SHADOW_PRINTK("emulator failure, unshadowing mfn %#lx\n", mfn_x(gmfn)); @@ -3956,7 +3959,7 @@ sh_x86_emulate_write(struct vcpu *v, uns ASSERT(((vaddr & ~PAGE_MASK) + bytes) <= PAGE_SIZE); if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL ) - return X86EMUL_PROPAGATE_FAULT; + return X86EMUL_EXCEPTION; skip = safe_not_to_verify_write(mfn, addr, src, bytes); memcpy(addr, src, bytes); @@ -3968,7 +3971,7 @@ sh_x86_emulate_write(struct vcpu *v, uns sh_unmap_domain_page(addr); shadow_audit_tables(v); - return X86EMUL_CONTINUE; + return X86EMUL_OKAY; } int @@ -3979,7 +3982,7 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u mfn_t mfn; void *addr; unsigned long prev; - int rv = X86EMUL_CONTINUE, skip; + int rv = X86EMUL_OKAY, skip; ASSERT(shadow_locked_by_me(v->domain)); ASSERT(bytes <= sizeof(unsigned long)); @@ -3988,7 +3991,7 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u return X86EMUL_UNHANDLEABLE; if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL ) - return X86EMUL_PROPAGATE_FAULT; + return X86EMUL_EXCEPTION; skip = safe_not_to_verify_write(mfn, &new, &old, bytes); @@ -4032,7 +4035,7 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v, mfn_t mfn; void *addr; u64 old, new, prev; - int rv = X86EMUL_CONTINUE, skip; + int rv = X86EMUL_OKAY, skip; ASSERT(shadow_locked_by_me(v->domain)); @@ -4040,7 +4043,7 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v, return X86EMUL_UNHANDLEABLE; if ( (addr = emulate_map_dest(v, vaddr, sh_ctxt, &mfn)) == NULL ) - return X86EMUL_PROPAGATE_FAULT; + return X86EMUL_EXCEPTION; old = (((u64) old_hi) << 32) | (u64) old_lo; new = (((u64) new_hi) << 32) | (u64) new_lo; diff -r ad3ee81cc8c4 -r b010e556fe2c xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Wed Feb 21 11:42:04 2007 -0800 +++ b/xen/arch/x86/x86_emulate.c Wed Feb 21 19:58:58 2007 +0000 @@ -464,10 +464,10 @@ do{ __asm__ __volatile__ ( #define mode_64bit() (def_ad_bytes == 8) -#define fail_if(p) \ -do { \ - rc = (p) ? X86EMUL_UNHANDLEABLE : 0; \ - if ( rc ) goto done; \ +#define fail_if(p) \ +do { \ + rc = (p) ? X86EMUL_UNHANDLEABLE : X86EMUL_OKAY; \ + if ( rc ) goto done; \ } while (0) /* In future we will be able to generate arbitrary exceptions. */ @@ -726,7 +726,7 @@ x86_emulate( uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes; unsigned int lock_prefix = 0, rep_prefix = 0; - int rc = 0; + int rc = X86EMUL_OKAY; struct operand src, dst; /* Data operand effective address (usually computed from ModRM). */ @@ -742,7 +742,7 @@ x86_emulate( { op_bytes = def_op_bytes = 4; #ifndef __x86_64__ - return -1; + return X86EMUL_UNHANDLEABLE; #endif } @@ -1593,7 +1593,7 @@ x86_emulate( *ctxt->regs = _regs; done: - return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; + return rc; special_insn: dst.type = OP_NONE; @@ -2383,5 +2383,5 @@ x86_emulate( } printk("\n"); #endif - return -1; + return X86EMUL_UNHANDLEABLE; } diff -r ad3ee81cc8c4 -r b010e556fe2c xen/include/asm-x86/x86_emulate.h --- a/xen/include/asm-x86/x86_emulate.h Wed Feb 21 11:42:04 2007 -0800 +++ b/xen/include/asm-x86/x86_emulate.h Wed Feb 21 19:58:58 2007 +0000 @@ -46,26 +46,32 @@ enum x86_segment { }; /* + * Return codes from state-accessor functions and from x86_emulate(). + */ + /* Completed successfully. State modified appropriately. */ +#define X86EMUL_OKAY 0 + /* Unhandleable access or emulation. No state modified. */ +#define X86EMUL_UNHANDLEABLE 1 + /* Exception raised and requires delivery. */ +#define X86EMUL_EXCEPTION 2 + /* Retry the emulation for some reason. No state modified. */ +#define X86EMUL_RETRY 3 + /* (cmpxchg accessor): CMPXCHG failed. Maps to X86EMUL_RETRY in caller. */ +#define X86EMUL_CMPXCHG_FAILED 3 + +/* * These operations represent the instruction emulator's interface to memory. * * NOTES: * 1. If the access fails (cannot emulate, or a standard access faults) then * it is up to the memop to propagate the fault to the guest VM via * some out-of-band mechanism, unknown to the emulator. The memop signals - * failure by returning X86EMUL_PROPAGATE_FAULT to the emulator, which will + * failure by returning X86EMUL_EXCEPTION to the emulator, which will * then immediately bail. * 2. Valid access sizes are 1, 2, 4 and 8 bytes. On x86/32 systems only * cmpxchg8b_emulated need support 8-byte accesses. * 3. The emulator cannot handle 64-bit mode emulation on an x86/32 system. */ -/* Access completed successfully: continue emulation as normal. */ -#define X86EMUL_CONTINUE 0 -/* Access is unhandleable: bail from emulation and return error to caller. */ -#define X86EMUL_UNHANDLEABLE 1 -/* Terminate emulation but return success to the caller. */ -#define X86EMUL_PROPAGATE_FAULT 2 /* propagate a generated fault to guest */ -#define X86EMUL_RETRY_INSTR 2 /* retry the instruction for some reason */ -#define X86EMUL_CMPXCHG_FAILED 2 /* cmpxchg did not see expected value */ struct x86_emulate_ops { /* _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |