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
|