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-10-19 20:46:34 +0100 |
commit | a79a0cb1d35ec422dcf493cef1bebf9fdfcfdb9a (patch) | |
tree | 4e3dfddc2f910e07c9847cf68a97eeb9fe646851 /arch/arm/kernel/traps.c | |
parent | 8592edf0dec8159fde379eb7e056eaddbbd697f2 (diff) | |
download | blackbird-op-linux-a79a0cb1d35ec422dcf493cef1bebf9fdfcfdb9a.tar.gz blackbird-op-linux-a79a0cb1d35ec422dcf493cef1bebf9fdfcfdb9a.zip |
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>
Tested-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Diffstat (limited to 'arch/arm/kernel/traps.c')
-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 8fcda140358d..caf96da27360 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; + inst2 = __mem_to_opcode_thumb16(((u16 *)pc)[1]); + instr = __opcode_thumb32_compose(instr, inst2); } } 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; } |