powerpc: Unaligned stores and stmw are broken in emulation code
authorTom Musta <tmusta@us.ibm.com>
Thu, 22 Aug 2013 14:25:28 +0000 (09:25 -0500)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 27 Aug 2013 04:36:08 +0000 (14:36 +1000)
The stmw instruction was incorrectly decoded as an update form instruction
and thus the RA register was being clobbered.

Also, the utility routine to write memory to unaligned addresses breaks the
operation into smaller aligned accesses but was incorrectly incrementing
the address by only one; it needs to increment the address by the size of
the smaller aligned chunk.

Signed-off-by: Tom Musta <tmusta@us.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/lib/sstep.c

index 99c7fc16dc0d3ffe7ad59a746b085bd888961f00..a7ee978fb860c9ffd237d9fbafb716b724e3afec 100644 (file)
@@ -100,8 +100,10 @@ static unsigned long __kprobes dform_ea(unsigned int instr, struct pt_regs *regs
        ea = (signed short) instr;              /* sign-extend */
        if (ra) {
                ea += regs->gpr[ra];
-               if (instr & 0x04000000)         /* update forms */
-                       regs->gpr[ra] = ea;
+               if (instr & 0x04000000) {               /* update forms */
+                       if ((instr>>26) != 47)          /* stmw is not an update form */
+                               regs->gpr[ra] = ea;
+               }
        }
 
        return truncate_if_32bit(regs->msr, ea);
@@ -279,7 +281,7 @@ static int __kprobes write_mem_unaligned(unsigned long val, unsigned long ea,
                err = write_mem_aligned(val >> (nb - c) * 8, ea, c);
                if (err)
                        return err;
-               ++ea;
+               ea += c;
        }
        return 0;
 }