aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Dooks <ben.dooks@codethink.co.uk>2013-07-18 21:10:56 +0100
committerAndrey Konovalov <andrey.konovalov@linaro.org>2013-10-08 14:05:38 +0400
commit3d8c71bfaca8d9a9f119725c7ac0e660f795f5ea (patch)
treebf88b780c14e040ab3bf985db28f1f04b897ea4f
parent33c6ee131e3e2000df3c8b53a9b7795e228b0c60 (diff)
downloadjuice-3d8c71bfaca8d9a9f119725c7ac0e660f795f5ea.tar.gz
ARM: alignment: correctly decode instructions in BE8 mode.
If we are in BE8 mode, we must deal with the instruction stream being in LE order when data is being loaded in BE order. Ensure the data is swapped before processing to avoid thre following: Change to using <asm/opcodes.h> to provide the necessary conversion functions to change the byte ordering. This stops the following warning messages from the kernel on a fault: Unhandled fault: alignment exception (0x001) at 0xbfa09567 Alignment trap: not handling instruction 030091e8 at [<80333e8c>] Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> Reviewed-by: Dave Martin <Dave.Martin@arm.com> Tested-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
-rw-r--r--arch/arm/mm/alignment.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 6f4585b8907..924036473b1 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -25,6 +25,7 @@
#include <asm/cp15.h>
#include <asm/system_info.h>
#include <asm/unaligned.h>
+#include <asm/opcodes.h>
#include "fault.h"
@@ -762,21 +763,25 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
if (thumb_mode(regs)) {
u16 *ptr = (u16 *)(instrptr & ~1);
fault = probe_kernel_address(ptr, tinstr);
+ tinstr = __mem_to_opcode_thumb16(tinstr);
if (!fault) {
if (cpu_architecture() >= CPU_ARCH_ARMv7 &&
IS_T32(tinstr)) {
/* Thumb-2 32-bit */
u16 tinst2 = 0;
fault = probe_kernel_address(ptr + 1, tinst2);
- instr = (tinstr << 16) | tinst2;
+ tinst2 = __mem_to_opcode_thumb16(tinst2);
+ instr = __opcode_thumb32_compose(tinstr, tinst2);
thumb2_32b = 1;
} else {
isize = 2;
instr = thumb2arm(tinstr);
}
}
- } else
+ } else {
fault = probe_kernel_address(instrptr, instr);
+ instr = __mem_to_opcode_arm(instr);
+ }
if (fault) {
type = TYPE_FAULT;