aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorTom Musta <tmusta@us.ibm.com>2013-08-22 10:25:28 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-08-27 00:36:08 -0400
commit17e8de7e1878bbd45f3e268932e997496ddbbfe7 (patch)
treef7dc643d8809b2701be9d7547ddb680c19f2fd02 /arch/powerpc
parentf748edafac858404be6c8dd67160c2032d97ddf5 (diff)
powerpc: Unaligned stores and stmw are broken in emulation code
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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/lib/sstep.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 99c7fc16dc0d..a7ee978fb860 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -100,8 +100,10 @@ static unsigned long __kprobes dform_ea(unsigned int instr, struct pt_regs *regs
100 ea = (signed short) instr; /* sign-extend */ 100 ea = (signed short) instr; /* sign-extend */
101 if (ra) { 101 if (ra) {
102 ea += regs->gpr[ra]; 102 ea += regs->gpr[ra];
103 if (instr & 0x04000000) /* update forms */ 103 if (instr & 0x04000000) { /* update forms */
104 regs->gpr[ra] = ea; 104 if ((instr>>26) != 47) /* stmw is not an update form */
105 regs->gpr[ra] = ea;
106 }
105 } 107 }
106 108
107 return truncate_if_32bit(regs->msr, ea); 109 return truncate_if_32bit(regs->msr, ea);
@@ -279,7 +281,7 @@ static int __kprobes write_mem_unaligned(unsigned long val, unsigned long ea,
279 err = write_mem_aligned(val >> (nb - c) * 8, ea, c); 281 err = write_mem_aligned(val >> (nb - c) * 8, ea, c);
280 if (err) 282 if (err)
281 return err; 283 return err;
282 ++ea; 284 ea += c;
283 } 285 }
284 return 0; 286 return 0;
285} 287}