[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86_emulate: Emulate MMX movq instructions.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1208425614 -3600 # Node ID d178c5ee6822a269e365d206da74e9704f059fa1 # Parent a38a41de0800cefca755ffb600d6d5e96f084697 x86_emulate: Emulate MMX movq instructions. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/hvm/emulate.c | 19 +++++++- xen/arch/x86/x86_emulate/x86_emulate.c | 77 ++++++++++++++++++++++++++------- xen/arch/x86/x86_emulate/x86_emulate.h | 9 +++ 3 files changed, 87 insertions(+), 18 deletions(-) diff -r a38a41de0800 -r d178c5ee6822 xen/arch/x86/hvm/emulate.c --- a/xen/arch/x86/hvm/emulate.c Wed Apr 16 16:42:47 2008 +0100 +++ b/xen/arch/x86/hvm/emulate.c Thu Apr 17 10:46:54 2008 +0100 @@ -674,16 +674,33 @@ static int hvmemul_inject_sw_interrupt( return X86EMUL_OKAY; } -static void hvmemul_get_fpu( +static int hvmemul_get_fpu( void (*exception_callback)(void *, struct cpu_user_regs *), void *exception_callback_arg, + enum x86_emulate_fpu_type type, struct x86_emulate_ctxt *ctxt) { struct vcpu *curr = current; + + switch ( type ) + { + case X86EMUL_FPU_fpu: + break; + case X86EMUL_FPU_mmx: + if ( !cpu_has_mmx ) + return X86EMUL_UNHANDLEABLE; + break; + default: + return X86EMUL_UNHANDLEABLE; + } + if ( !curr->fpu_dirtied ) hvm_funcs.fpu_dirty_intercept(); + curr->arch.hvm_vcpu.fpu_exception_callback = exception_callback; curr->arch.hvm_vcpu.fpu_exception_callback_arg = exception_callback_arg; + + return X86EMUL_OKAY; } static void hvmemul_put_fpu( diff -r a38a41de0800 -r d178c5ee6822 xen/arch/x86/x86_emulate/x86_emulate.c --- a/xen/arch/x86/x86_emulate/x86_emulate.c Wed Apr 16 16:42:47 2008 +0100 +++ b/xen/arch/x86/x86_emulate/x86_emulate.c Thu Apr 17 10:46:54 2008 +0100 @@ -195,9 +195,9 @@ static uint8_t twobyte_table[256] = { /* 0x50 - 0x5F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ - 0, 0, 0, 0, 0, 0, 0, 0, 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, /* 0x70 - 0x7F */ - 0, 0, 0, 0, 0, 0, 0, 0, 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, /* 0x80 - 0x87 */ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, @@ -558,41 +558,48 @@ static void fpu_handle_exception(void *_ regs->eip += fic->insn_bytes; } +#define get_fpu(_type, _fic) \ +do{ (_fic)->exn_raised = 0; \ + fail_if(ops->get_fpu == NULL); \ + rc = ops->get_fpu(fpu_handle_exception, _fic, _type, ctxt); \ + if ( rc ) goto done; \ +} while (0) +#define put_fpu(_fic) \ +do{ \ + if ( ops->put_fpu != NULL ) \ + ops->put_fpu(ctxt); \ + generate_exception_if((_fic)->exn_raised, EXC_MF, -1); \ +} while (0) + #define emulate_fpu_insn(_op) \ -do{ struct fpu_insn_ctxt fic = { 0 }; \ - fail_if(ops->get_fpu == NULL); \ - ops->get_fpu(fpu_handle_exception, &fic, ctxt); \ +do{ struct fpu_insn_ctxt fic; \ + get_fpu(X86EMUL_FPU_fpu, &fic); \ asm volatile ( \ "movb $2f-1f,%0 \n" \ "1: " _op " \n" \ "2: \n" \ : "=m" (fic.insn_bytes) : : "memory" ); \ - ops->put_fpu(ctxt); \ - generate_exception_if(fic.exn_raised, EXC_MF, -1); \ + put_fpu(&fic); \ } while (0) #define emulate_fpu_insn_memdst(_op, _arg) \ -do{ struct fpu_insn_ctxt fic = { 0 }; \ - fail_if(ops->get_fpu == NULL); \ - ops->get_fpu(fpu_handle_exception, &fic, ctxt); \ +do{ struct fpu_insn_ctxt fic; \ + get_fpu(X86EMUL_FPU_fpu, &fic); \ asm volatile ( \ "movb $2f-1f,%0 \n" \ "1: " _op " %1 \n" \ "2: \n" \ : "=m" (fic.insn_bytes), "=m" (_arg) \ : : "memory" ); \ - ops->put_fpu(ctxt); \ - generate_exception_if(fic.exn_raised, EXC_MF, -1); \ + put_fpu(&fic); \ } while (0) #define emulate_fpu_insn_stub(_bytes...) \ do{ uint8_t stub[] = { _bytes, 0xc3 }; \ struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 }; \ - fail_if(ops->get_fpu == NULL); \ - ops->get_fpu(fpu_handle_exception, &fic, ctxt); \ + get_fpu(X86EMUL_FPU_fpu, &fic); \ (*(void(*)(void))stub)(); \ - ops->put_fpu(ctxt); \ - generate_exception_if(fic.exn_raised, EXC_MF, -1); \ + put_fpu(&fic); \ } while (0) static unsigned long __get_rep_prefix( @@ -3369,6 +3376,44 @@ x86_emulate( break; } + case 0x6f: /* movq mm/m64,mm */ { + uint8_t stub[] = { 0x0f, 0x6f, modrm, 0xc3 }; + struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 }; + uint64_t val; + if ( ea.type == OP_MEM ) + { + unsigned long lval, hval; + if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &lval, 4, ctxt)) || + (rc = ops->read(ea.mem.seg, ea.mem.off+4, &hval, 4, ctxt)) ) + goto done; + val = ((uint64_t)hval << 32) | (uint32_t)lval; + stub[2] = modrm & 0x38; /* movq (%eax),%mmN */ + } + get_fpu(X86EMUL_FPU_mmx, &fic); + asm volatile ( "call *%0" : : "r" (stub), "a" (&val) : "memory" ); + put_fpu(&fic); + break; + } + + case 0x7f: /* movq mm,mm/m64 */ { + uint8_t stub[] = { 0x0f, 0x7f, modrm, 0xc3 }; + struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 }; + uint64_t val; + if ( ea.type == OP_MEM ) + stub[2] = modrm & 0x38; /* movq %mmN,(%eax) */ + get_fpu(X86EMUL_FPU_mmx, &fic); + asm volatile ( "call *%0" : : "r" (stub), "a" (&val) : "memory" ); + put_fpu(&fic); + if ( ea.type == OP_MEM ) + { + unsigned long lval = (uint32_t)val, hval = (uint32_t)(val >> 32); + if ( (rc = ops->write(ea.mem.seg, ea.mem.off+0, lval, 4, ctxt)) || + (rc = ops->write(ea.mem.seg, ea.mem.off+4, hval, 4, ctxt)) ) + goto done; + } + break; + } + case 0x80 ... 0x8f: /* jcc (near) */ { int rel = (((op_bytes == 2) && !mode_64bit()) ? (int32_t)insn_fetch_type(int16_t) diff -r a38a41de0800 -r d178c5ee6822 xen/arch/x86/x86_emulate/x86_emulate.h --- a/xen/arch/x86/x86_emulate/x86_emulate.h Wed Apr 16 16:42:47 2008 +0100 +++ b/xen/arch/x86/x86_emulate/x86_emulate.h Thu Apr 17 10:46:54 2008 +0100 @@ -95,6 +95,12 @@ struct segment_register { /* (cmpxchg accessor): CMPXCHG failed. Maps to X86EMUL_RETRY in caller. */ #define X86EMUL_CMPXCHG_FAILED 3 +/* FPU sub-types which may be requested via ->get_fpu(). */ +enum x86_emulate_fpu_type { + X86EMUL_FPU_fpu, /* Standard FPU coprocessor instruction set */ + X86EMUL_FPU_mmx /* MMX instruction set (%mm0-%mm7) */ +}; + /* * These operations represent the instruction emulator's interface to memory. * @@ -347,9 +353,10 @@ struct x86_emulate_ops * @exn_callback: On any FPU or SIMD exception, pass control to * (*exception_callback)(exception_callback_arg, regs). */ - void (*get_fpu)( + int (*get_fpu)( void (*exception_callback)(void *, struct cpu_user_regs *), void *exception_callback_arg, + enum x86_emulate_fpu_type type, struct x86_emulate_ctxt *ctxt); /* put_fpu: Relinquish the FPU. Unhook from FPU/SIMD exception handlers. */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |