diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index 1e0f0e4..a9f8463 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -382,6 +382,21 @@ config CPU_EMU_FUCOMI If you are not sure, say N. +config CPU_EMU_SSE2 + bool "SSE2 instruction emulation" + depends on X86_32 && CPU_EMU486 + ---help--- + This attemps to emulate certain SSE2 codes by software. + This will allow programs compiled by -mfpmath=sse, which is now common for + .i686 distributions, to run on CPUs without SSE2. + + WARNING: This only works with CPUs withOUT MMX. Since some SSE + instructions are interpreted as MMX instructions on non-SSE + processors, it is impossible to emulate them via #UD exception. + Practically only works on plain Pentuim P54C without MMX. + + If you are not sure, say N. + config CPU_PROC_EMULATED_OPS bool "/proc/emulated_ops support" depends on X86_32 && CPU_EMU486 diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b43e343..1f078c4 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -432,10 +432,28 @@ union thread_xstate { struct xsave_struct xsave; }; +#if defined(CONFIG_CPU_EMU_SSE2) +/* Software emulated XMM registers */ +union xmm_t { + struct { u64 q[2]; } qw; + struct { s32 d[4]; } dw; +}; +#endif + struct fpu { unsigned int last_cpu; unsigned int has_fpu; union thread_xstate *state; +#if defined(CONFIG_CPU_EMU_SSE2) + /* Software emulated XMM registers */ + /* This does not belong here, but state->fsave is not always available */ + + /* this padding must be adjusted where this + * struct fpu belongs in struct thread_struct, + * so that xmm will be aligned at 16-byte boundary */ + u32 padding[1]; + union xmm_t xmm[8]; /* 8 XMM registers, 128bit */ +#endif }; #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 056206b..5ab1d61 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -1300,10 +1300,12 @@ dotraplinkage void do_invalid_op(struct pt_regs *regs, long error_code) break; } /*while(1)*/ + eip = (u8 *)regs->ip; /* reset */ + /* it's a case we can't handle. Unknown opcode or too many prefixes. */ invalid_opcode: #ifdef CONFIG_CPU_EMU486_DEBUG - printk(KERN_DEBUG "do_invalid_op() : invalid opcode detected @%p : %02x %02x %02x %02x %02x...\n", eip, eip[0], eip[1], eip[2], eip[3], eip[4]); + printk(KERN_DEBUG "do_invalid_op() : invalid opcode detected pid %d(%s) @%p : %02x %02x >%02x %02x %02x %02x %02x...\n", current->pid, current->comm, eip, eip[-2], eip[-1], eip[0], eip[1], eip[2], eip[3], eip[4]); #endif current->thread.error_code = error_code; current->thread.trap_nr = X86_TRAP_UD;