I was advised by Jon Burgess to forward the fix to this mailing list as well Ralf Baechle said he would look at the fix. --- "D.J. Barrow" <barrow_dj@yahoo.com> wrote: > Date: Fri, 27 Sep 2002 09:26:01 -0700 (PDT) > From: "D.J. Barrow" <barrow_dj@yahoo.com> > Subject: mips unaligned.c bugfix > To: Kernel Mailing List <linux-kernel@vger.kernel.org>, > Ralf Baechle <ralf@uni-koblenz.de> > > Hi Ralf & others, > > I found & fixed kernel bug in unaligned.c which was affecting the iptables code > in little mips32 endian. > > The patch is against 2.4.17 on oss.sgi.com & should hopefully apply to the latest > kernel. > > The fixes code for I did mips 64 is untested, I had no way to test them unfortunately. > > An example of the bug is the bug following sequence of mips instructions > beqz v0,<destaddr> > lw v0,(t3) > > say reg t3 points to an unaligned address > > In the emulation the v0 register was being loaded & modified before > the computation of the destination address ( which depended on v0 ) > this was incorrect so I had to save the updating of the v0 register > until the computation of the destination address was done. > > ===== > D.J. Barrow Linux kernel developer > eMail: dj_barrow@ariasoft.ie > Home: +353-22-47196. > Work: +353-91-758353 > > __________________________________________________ > Do you Yahoo!? > New DSL Internet Access from SBC & Yahoo! > http://sbc.yahoo.com > ATTACHMENT part 2 application/x-unknown name=unaligned.diff ===== D.J. Barrow Linux kernel developer eMail: dj_barrow@ariasoft.ie Home: +353-22-47196. Apt till end Oct 2002: +353-91-533628 __________________________________________________ Do you Yahoo!? New DSL Internet Access from SBC & Yahoo! http://sbc.yahoo.com
--- kernel.orig/arch/mips/kernel/unaligned.c Tue Jan 15 04:08:09 2002 +++ kernel/arch/mips/kernel/unaligned.c Fri Sep 27 16:58:22 2002 @@ -8,6 +8,11 @@ * Copyright (C) 1996, 1998 by Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. * + * Fixes: + * 2002 Denis Joseph Barrow <dj_barrow@ariasoft.ie> + * Fix to do_ade to compute destination addresses correctly + * after fixing delay slot instructions. + * * This file contains exception handler for address error exception with the * special capability to execute faulting instructions in software. The * handler does not try to handle the case when the program counter points @@ -97,13 +102,15 @@ goto sigbus; static inline int emulate_load_store_insn(struct pt_regs *regs, - unsigned long addr, unsigned long pc) + unsigned long addr, unsigned long pc, + unsigned long **regptr,unsigned long *newvalue) { union mips_instruction insn; unsigned long value, fixup; unsigned int res; regs->regs[0] = 0; + *regptr=NULL; /* * This load never faults. */ @@ -169,7 +176,8 @@ : "r" (addr), "i" (-EFAULT)); if (res) goto fault; - regs->regs[insn.i_format.rt] = value; + *newvalue=value; + *regptr=®s->regs[insn.i_format.rt]; return 0; case lw_op: @@ -196,7 +204,8 @@ : "r" (addr), "i" (-EFAULT)); if (res) goto fault; - regs->regs[insn.i_format.rt] = value; + *newvalue=value; + *regptr=®s->regs[insn.i_format.rt]; return 0; case lhu_op: @@ -227,7 +236,8 @@ : "r" (addr), "i" (-EFAULT)); if (res) goto fault; - regs->regs[insn.i_format.rt] = value; + *newvalue=value; + *regptr=®s->regs[insn.i_format.rt]; return 0; case lwu_op: @@ -365,7 +375,7 @@ asmlinkage void do_ade(struct pt_regs *regs) { - unsigned long pc; + unsigned long pc,*regptr,newval; extern int do_dsemulret(struct pt_regs *); /* @@ -395,9 +405,18 @@ * Do branch emulation only if we didn't forward the exception. * This is all so but ugly ... */ - if (!emulate_load_store_insn(regs, regs->cp0_badvaddr, pc)) + if (!emulate_load_store_insn(regs, regs->cp0_badvaddr, pc,®ptr,&newval)) + { compute_return_epc(regs); - + /* We need use the regptr complication for delay slot instructions + * which can miscompute destination addresses + * e.g. consider the sequence + * beqz v0,<destaddr> + * lw v0,(t3) + */ + if(regptr) + *regptr=newval; + } #ifdef CONFIG_PROC_FS unaligned_instructions++; #endif --- kernel.orig/arch/mips64/kernel/unaligned.c Sat Jan 26 07:28:35 2002 +++ kernel/arch/mips64/kernel/unaligned.c Fri Sep 27 17:09:28 2002 @@ -8,6 +8,11 @@ * Copyright (C) 1996, 1998, 1999 by Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. * + * Fixes: + * 2002 Denis Joseph Barrow <dj_barrow@ariasoft.ie> + * Fix to do_ade to compute destination addresses correctly + * after fixing delay slot instructions. + * * This file contains exception handler for address error exception with the * special capability to execute faulting instructions in software. The * handler does not try to handle the case when the program counter points @@ -97,12 +102,14 @@ goto sigbus; static inline int emulate_load_store_insn(struct pt_regs *regs, - unsigned long addr, unsigned long pc) + unsigned long addr, unsigned long pc, + unsigned long **regptr,unsigned long *newvalue) { union mips_instruction insn; unsigned long value, fixup; regs->regs[0] = 0; + *regptr=NULL; /* * This load never faults. */ @@ -162,7 +169,8 @@ ".previous" :"=&r" (value) :"r" (addr), "i" (&&fault)); - regs->regs[insn.i_format.rt] = value; + *newvalue=value; + *regptr=®s->regs[insn.i_format.rt]; return 0; case lw_op: @@ -182,8 +190,9 @@ ".previous" :"=&r" (value) :"r" (addr), "i" (&&fault)); - regs->regs[insn.i_format.rt] = value; - return 0; + *newvalue=value; + *regptr=®s->regs[insn.i_format.rt]; + return 0; case lhu_op: check_axs(pc, addr, 2); @@ -206,7 +215,8 @@ ".previous" :"=&r" (value) :"r" (addr), "i" (&&fault)); - regs->regs[insn.i_format.rt] = value; + *newvalue=value; + *regptr=®s->regs[insn.i_format.rt]; return 0; case lwu_op: @@ -227,7 +237,8 @@ :"=&r" (value) :"r" (addr), "i" (&&fault)); value &= 0xffffffff; - regs->regs[insn.i_format.rt] = value; + *newvalue=value; + *regptr=®s->regs[insn.i_format.rt]; return 0; case ld_op: @@ -249,7 +260,8 @@ ".previous" :"=&r" (value) :"r" (addr), "i" (&&fault)); - regs->regs[insn.i_format.rt] = value; + *newvalue=value; + *regptr=®s->regs[insn.i_format.rt]; return 0; case sh_op: @@ -398,9 +410,18 @@ * Do branch emulation only if we didn't forward the exception. * This is all so but ugly ... */ - if (!emulate_load_store_insn(regs, regs->cp0_badvaddr, pc)) + if (!emulate_load_store_insn(regs, regs->cp0_badvaddr, pc,®ptr,&newval)) + { compute_return_epc(regs); - + /* We need use the regptr complication for delay slot instructions + * which can miscompute destination addresses + * e.g. consider the sequence + * beqz v0,<destaddr> + * lw v0,(t3) + */ + if(regptr) + *regptr=newval; + } #ifdef CONFIG_PROC_FS unaligned_instructions++; #endif