Hi, some comments ... On 16 June 2012 00:22, Lluis Batlle i Rossell <viric@xxxxxxxxxx> wrote: > Reusing most of the code from lw,ld,sw,sd emulation, > I add the emulation for lwc1,ldc1,swc1,sdc1. What about lwxc1, ldxc1, swxc1 and sdxc1? These also require alignment. > This avoids the direct SIGBUS sent to userspace processes that have > misaligned memory accesses. > > I've tested the change in Loongson2F, with an own test program, and > WebKit 1.4.0, as both were killed by sigbus without this patch. > > Signed-off: Lluis Batlle i Rossell <viric@xxxxxxxxxx> > --- > arch/mips/kernel/unaligned.c | 43 +++++++++++++++++++++++++++++------------- > 1 file changed, 30 insertions(+), 13 deletions(-) > > diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c > index 9c58bdf..4531e6c 100644 > --- a/arch/mips/kernel/unaligned.c > +++ b/arch/mips/kernel/unaligned.c > @@ -85,6 +85,7 @@ > #include <asm/cop2.h> > #include <asm/inst.h> > #include <asm/uaccess.h> > +#include <asm/fpu.h> > > #define STR(x) __STR(x) > #define __STR(x) #x > @@ -108,6 +109,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, > union mips_instruction insn; > unsigned long value; > unsigned int res; > + fpureg_t *fpuregs; > > perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, 0); > > @@ -183,6 +185,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, > break; > > case lw_op: > + case lwc1_op: > if (!access_ok(VERIFY_READ, addr, 4)) > goto sigbus; > > @@ -209,7 +212,12 @@ static void emulate_load_store_insn(struct pt_regs *regs, > if (res) > goto fault; > compute_return_epc(regs); > - regs->regs[insn.i_format.rt] = value; > + if (insn.i_format.opcode == lw_op) { > + regs->regs[insn.i_format.rt] = value; > + } else { > + fpuregs = get_fpu_regs(current); > + fpuregs[insn.i_format.rt] = value; > + } > break; > > case lhu_op: > @@ -291,6 +299,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, > goto sigill; > > case ld_op: > + case ldc1_op: > #ifdef CONFIG_64BIT >From what I can tell, ldc1 is a valid MIPS32 instruction, so this should probably be something like case ld_op: #ifndef CONFIG_64BIT return sigill; #endif case ldc1_op: ... > /* > * A 32-bit kernel might be running on a 64-bit processor. But > @@ -325,7 +334,12 @@ static void emulate_load_store_insn(struct pt_regs *regs, > if (res) > goto fault; > compute_return_epc(regs); > - regs->regs[insn.i_format.rt] = value; > + if (insn.i_format.opcode == ld_op) { > + regs->regs[insn.i_format.rt] = value; > + } else { > + fpuregs = get_fpu_regs(current); > + fpuregs[insn.i_format.rt] = value; > + } > break; > #endif /* CONFIG_64BIT */ > > @@ -370,10 +384,16 @@ static void emulate_load_store_insn(struct pt_regs *regs, > break; > > case sw_op: > + case swc1_op: > if (!access_ok(VERIFY_WRITE, addr, 4)) > goto sigbus; > > - value = regs->regs[insn.i_format.rt]; > + if (insn.i_format.opcode == sw_op) { > + value = regs->regs[insn.i_format.rt]; > + } else { > + fpuregs = get_fpu_regs(current); > + value = fpuregs[insn.i_format.rt]; > + } > __asm__ __volatile__ ( > #ifdef __BIG_ENDIAN > "1:\tswl\t%1,(%2)\n" > @@ -401,6 +421,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, > break; > > case sd_op: > + case sdc1_op: > #ifdef CONFIG_64BIT Same here. > /* > * A 32-bit kernel might be running on a 64-bit processor. But Regards, Jonas