diff options
author | Ben Dooks <ben.dooks@codethink.co.uk> | 2013-07-19 17:12:05 +0100 |
---|---|---|
committer | Ben Dooks <ben.dooks@codethink.co.uk> | 2013-08-27 21:58:00 +0100 |
commit | e35a8940bc93a56f0b86b6ca770a6fabb8222ba3 (patch) | |
tree | 547fe520ffc597be2022daf5ae4529c94eaa138b | |
parent | cb74cf4269beb568b276710028bb3f711cc15dda (diff) | |
download | linux-e35a8940bc93a56f0b86b6ca770a6fabb8222ba3.tar.gz |
ARM: traps: use <asm/opcodes.h> to get correct instruction order
The trap handler needs to take into account the endian configuration of
the system when loading instructions. Use <asm/opcodes.h> to provide the
necessary conversion functions.
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
-rw-r--r-- | arch/arm/kernel/traps.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index ab517fcce21b..99bcd0e3b8b8 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -34,6 +34,7 @@ #include <asm/unwind.h> #include <asm/tls.h> #include <asm/system_misc.h> +#include <asm/opcodes.h> static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; @@ -402,25 +403,28 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) if (processor_mode(regs) == SVC_MODE) { #ifdef CONFIG_THUMB2_KERNEL if (thumb_mode(regs)) { - instr = ((u16 *)pc)[0]; + instr = __mem_to_opcode_thumb16(((u16 *)pc)[0]); if (is_wide_instruction(instr)) { - instr <<= 16; - instr |= ((u16 *)pc)[1]; + u16 inst2; + instr2 = __mem_to_opcode_thumb16(((u16 *)pc)[1]); + instr = __opcode_thumb32_compose(instr, instr2); } } else #endif - instr = *(u32 *) pc; + instr = __mem_to_opcode_arm(*(u32 *) pc); } else if (thumb_mode(regs)) { if (get_user(instr, (u16 __user *)pc)) goto die_sig; + instr = __mem_to_opcode_thumb16(instr); if (is_wide_instruction(instr)) { unsigned int instr2; if (get_user(instr2, (u16 __user *)pc+1)) goto die_sig; - instr <<= 16; - instr |= instr2; + instr2 = __mem_to_opcode_thumb16(instr2); + instr = __opcode_thumb32_compose(instr, instr2); } } else if (get_user(instr, (u32 __user *)pc)) { + instr = __mem_to_opcode_arm(instr); goto die_sig; } |