[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86_emulate: Implement a more dynamic interface for handling FPU
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1208358641 -3600 # Node ID defbab4dba1a40ce08ed5b9331cfaf7a4422853e # Parent 837ea1f0aa8ab3446cfb8bf3ab9d68e258d08785 x86_emulate: Implement a more dynamic interface for handling FPU exceptions, which will allow emulation stubs to be built dynamically in a future patch. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- tools/tests/x86_emulate.c | 6 -- xen/arch/x86/Makefile | 2 xen/arch/x86/hvm/emulate.c | 23 +++++++-- xen/arch/x86/traps.c | 9 +++ xen/arch/x86/x86_emulate.c | 18 ------- xen/arch/x86/x86_emulate/x86_emulate.c | 82 ++++++++++++++++++++++----------- xen/arch/x86/x86_emulate/x86_emulate.h | 14 ++++- xen/include/asm-x86/hvm/vcpu.h | 3 + 8 files changed, 100 insertions(+), 57 deletions(-) diff -r 837ea1f0aa8a -r defbab4dba1a tools/tests/x86_emulate.c --- a/tools/tests/x86_emulate.c Wed Apr 16 13:43:23 2008 +0100 +++ b/tools/tests/x86_emulate.c Wed Apr 16 16:10:41 2008 +0100 @@ -4,10 +4,4 @@ #include <public/xen.h> #include "x86_emulate/x86_emulate.h" - -#define __emulate_fpu_insn(_op) \ -do{ rc = X86EMUL_UNHANDLEABLE; \ - goto done; \ -} while (0) - #include "x86_emulate/x86_emulate.c" diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Wed Apr 16 13:43:23 2008 +0100 +++ b/xen/arch/x86/Makefile Wed Apr 16 16:10:41 2008 +0100 @@ -52,6 +52,8 @@ obj-y += tboot.o obj-$(crash_debug) += gdbstub.o +x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h + $(TARGET): $(TARGET)-syms boot/mkelf32 ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \ `$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'` diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/hvm/emulate.c --- a/xen/arch/x86/hvm/emulate.c Wed Apr 16 13:43:23 2008 +0100 +++ b/xen/arch/x86/hvm/emulate.c Wed Apr 16 16:10:41 2008 +0100 @@ -674,11 +674,23 @@ static int hvmemul_inject_sw_interrupt( return X86EMUL_OKAY; } -static void hvmemul_load_fpu_ctxt( - struct x86_emulate_ctxt *ctxt) -{ - if ( !current->fpu_dirtied ) +static void hvmemul_get_fpu( + void (*exception_callback)(void *, struct cpu_user_regs *), + void *exception_callback_arg, + struct x86_emulate_ctxt *ctxt) +{ + struct vcpu *curr = current; + 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; +} + +static void hvmemul_put_fpu( + struct x86_emulate_ctxt *ctxt) +{ + struct vcpu *curr = current; + curr->arch.hvm_vcpu.fpu_exception_callback = NULL; } static int hvmemul_invlpg( @@ -720,7 +732,8 @@ static struct x86_emulate_ops hvm_emulat .cpuid = hvmemul_cpuid, .inject_hw_exception = hvmemul_inject_hw_exception, .inject_sw_interrupt = hvmemul_inject_sw_interrupt, - .load_fpu_ctxt = hvmemul_load_fpu_ctxt, + .get_fpu = hvmemul_get_fpu, + .put_fpu = hvmemul_put_fpu, .invlpg = hvmemul_invlpg }; diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Wed Apr 16 13:43:23 2008 +0100 +++ b/xen/arch/x86/traps.c Wed Apr 16 16:10:41 2008 +0100 @@ -479,6 +479,7 @@ static inline void do_trap( static inline void do_trap( int trapnr, struct cpu_user_regs *regs, int use_error_code) { + struct vcpu *curr = current; unsigned long fixup; DEBUGGER_trap_entry(trapnr, regs); @@ -494,6 +495,14 @@ static inline void do_trap( dprintk(XENLOG_ERR, "Trap %d: %p -> %p\n", trapnr, _p(regs->eip), _p(fixup)); regs->eip = fixup; + return; + } + + if ( ((trapnr == TRAP_copro_error) || (trapnr == TRAP_simd_error)) && + is_hvm_vcpu(curr) && curr->arch.hvm_vcpu.fpu_exception_callback ) + { + curr->arch.hvm_vcpu.fpu_exception_callback( + curr->arch.hvm_vcpu.fpu_exception_callback_arg, regs); return; } diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Wed Apr 16 13:43:23 2008 +0100 +++ b/xen/arch/x86/x86_emulate.c Wed Apr 16 16:10:41 2008 +0100 @@ -11,23 +11,7 @@ #include <asm/x86_emulate.h> +/* Avoid namespace pollution. */ #undef cmpxchg -#define __emulate_fpu_insn(_op) \ -do{ int _exn; \ - asm volatile ( \ - "1: " _op "\n" \ - "2: \n" \ - ".section .fixup,\"ax\"\n" \ - "3: mov $1,%0\n" \ - " jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n" \ - " "__FIXUP_ALIGN"\n" \ - " "__FIXUP_WORD" 1b,3b\n" \ - ".previous" \ - : "=r" (_exn) : "0" (0) ); \ - generate_exception_if(_exn, EXC_MF, -1); \ -} while (0) - #include "x86_emulate/x86_emulate.c" diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/x86_emulate/x86_emulate.c --- a/xen/arch/x86/x86_emulate/x86_emulate.c Wed Apr 16 13:43:23 2008 +0100 +++ b/xen/arch/x86/x86_emulate/x86_emulate.c Wed Apr 16 16:10:41 2008 +0100 @@ -544,6 +544,45 @@ do { if ( !mode_64bit() ) \ _regs.eip = ((op_bytes == 2) \ ? (uint16_t)_regs.eip : (uint32_t)_regs.eip); \ +} while (0) + +struct fpu_insn_ctxt { + uint8_t insn_bytes; + uint8_t exn_raised; +}; + +static void fpu_handle_exception(void *_fic, struct cpu_user_regs *regs) +{ + struct fpu_insn_ctxt *fic = _fic; + fic->exn_raised = 1; + regs->eip += fic->insn_bytes; +} + +#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); \ + 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); \ +} 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); \ + 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); \ } while (0) static unsigned long __get_rep_prefix( @@ -2399,8 +2438,6 @@ x86_emulate( } case 0x9b: /* wait/fwait */ - fail_if(ops->load_fpu_ctxt == NULL); - ops->load_fpu_ctxt(ctxt); __emulate_fpu_insn("fwait"); break; @@ -2721,53 +2758,46 @@ x86_emulate( } case 0xd9: /* FPU 0xd9 */ - fail_if(ops->load_fpu_ctxt == NULL); - ops->load_fpu_ctxt(ctxt); switch ( modrm ) { - case 0xc0: __emulate_fpu_insn(".byte 0xd9,0xc0"); break; - case 0xc1: __emulate_fpu_insn(".byte 0xd9,0xc1"); break; - case 0xc2: __emulate_fpu_insn(".byte 0xd9,0xc2"); break; - case 0xc3: __emulate_fpu_insn(".byte 0xd9,0xc3"); break; - case 0xc4: __emulate_fpu_insn(".byte 0xd9,0xc4"); break; - case 0xc5: __emulate_fpu_insn(".byte 0xd9,0xc5"); break; - case 0xc6: __emulate_fpu_insn(".byte 0xd9,0xc6"); break; - case 0xc7: __emulate_fpu_insn(".byte 0xd9,0xc7"); break; - case 0xe0: __emulate_fpu_insn(".byte 0xd9,0xe0"); break; - case 0xe8: __emulate_fpu_insn(".byte 0xd9,0xe8"); break; - case 0xee: __emulate_fpu_insn(".byte 0xd9,0xee"); break; + case 0xc0: __emulate_fpu_insn(".byte 0xd9,0xc0"); break; /* fld %st0 */ + case 0xc1: __emulate_fpu_insn(".byte 0xd9,0xc1"); break; /* fld %st1 */ + case 0xc2: __emulate_fpu_insn(".byte 0xd9,0xc2"); break; /* fld %st2 */ + case 0xc3: __emulate_fpu_insn(".byte 0xd9,0xc3"); break; /* fld %st3 */ + case 0xc4: __emulate_fpu_insn(".byte 0xd9,0xc4"); break; /* fld %st4 */ + case 0xc5: __emulate_fpu_insn(".byte 0xd9,0xc5"); break; /* fld %st5 */ + case 0xc6: __emulate_fpu_insn(".byte 0xd9,0xc6"); break; /* fld %st6 */ + case 0xc7: __emulate_fpu_insn(".byte 0xd9,0xc7"); break; /* fld %st7 */ + case 0xe0: __emulate_fpu_insn(".byte 0xd9,0xe0"); break; /* fchs */ + case 0xe1: __emulate_fpu_insn(".byte 0xd9,0xe1"); break; /* fabs */ + case 0xe8: __emulate_fpu_insn(".byte 0xd9,0xe8"); break; /* fld1 */ + case 0xee: __emulate_fpu_insn(".byte 0xd9,0xee"); break; /* fldz */ default: fail_if((modrm_reg & 7) != 7); fail_if(modrm >= 0xc0); /* fnstcw m2byte */ ea.bytes = 2; dst = ea; - asm volatile ( "fnstcw %0" : "=m" (dst.val) ); + __emulate_fpu_insn_memdst("fnstcw", dst.val); } break; case 0xdb: /* FPU 0xdb */ - fail_if(ops->load_fpu_ctxt == NULL); - ops->load_fpu_ctxt(ctxt); fail_if(modrm != 0xe3); /* fninit */ - asm volatile ( "fninit" ); + __emulate_fpu_insn("fninit"); break; case 0xdd: /* FPU 0xdd */ - fail_if(ops->load_fpu_ctxt == NULL); - ops->load_fpu_ctxt(ctxt); fail_if((modrm_reg & 7) != 7); fail_if(modrm >= 0xc0); /* fnstsw m2byte */ ea.bytes = 2; dst = ea; - asm volatile ( "fnstsw %0" : "=m" (dst.val) ); + __emulate_fpu_insn_memdst("fnstsw", dst.val); break; case 0xde: /* FPU 0xde */ - fail_if(ops->load_fpu_ctxt == NULL); - ops->load_fpu_ctxt(ctxt); switch ( modrm ) { case 0xd9: __emulate_fpu_insn(".byte 0xde,0xd9"); break; @@ -2784,14 +2814,12 @@ x86_emulate( break; case 0xdf: /* FPU 0xdf */ - fail_if(ops->load_fpu_ctxt == NULL); - ops->load_fpu_ctxt(ctxt); fail_if(modrm != 0xe0); /* fnstsw %ax */ dst.bytes = 2; dst.type = OP_REG; dst.reg = (unsigned long *)&_regs.eax; - asm volatile ( "fnstsw %0" : "=m" (dst.val) ); + __emulate_fpu_insn_memdst("fnstsw", dst.val); break; case 0xe0 ... 0xe2: /* loop{,z,nz} */ { diff -r 837ea1f0aa8a -r defbab4dba1a xen/arch/x86/x86_emulate/x86_emulate.h --- a/xen/arch/x86/x86_emulate/x86_emulate.h Wed Apr 16 13:43:23 2008 +0100 +++ b/xen/arch/x86/x86_emulate/x86_emulate.h Wed Apr 16 16:10:41 2008 +0100 @@ -342,8 +342,18 @@ struct x86_emulate_ops uint8_t insn_len, struct x86_emulate_ctxt *ctxt); - /* load_fpu_ctxt: Load emulated environment's FPU state onto processor. */ - void (*load_fpu_ctxt)( + /* + * get_fpu: Load emulated environment's FPU state onto processor. + * @exn_callback: On any FPU or SIMD exception, pass control to + * (*exception_callback)(exception_callback_arg, regs). + */ + void (*get_fpu)( + void (*exception_callback)(void *, struct cpu_user_regs *), + void *exception_callback_arg, + struct x86_emulate_ctxt *ctxt); + + /* put_fpu: Relinquish the FPU. Unhook from FPU/SIMD exception handlers. */ + void (*put_fpu)( struct x86_emulate_ctxt *ctxt); /* invlpg: Invalidate paging structures which map addressed byte. */ diff -r 837ea1f0aa8a -r defbab4dba1a xen/include/asm-x86/hvm/vcpu.h --- a/xen/include/asm-x86/hvm/vcpu.h Wed Apr 16 13:43:23 2008 +0100 +++ b/xen/include/asm-x86/hvm/vcpu.h Wed Apr 16 16:10:41 2008 +0100 @@ -83,6 +83,9 @@ struct hvm_vcpu { */ unsigned long mmio_gva; unsigned long mmio_gpfn; + + void (*fpu_exception_callback)(void *, struct cpu_user_regs *); + void *fpu_exception_callback_arg; }; #endif /* __ASM_X86_HVM_VCPU_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |