diff options
author | Robin Murphy <robin.murphy@arm.com> | 2014-09-25 06:56:19 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-09-25 10:32:57 -0400 |
commit | 5ca918e5e3f9df4634077c06585c42bc6a8d699a (patch) | |
tree | 09ba26eae5c513a24604e4c707b9ee9aa5acab95 /arch/arm/mm | |
parent | 2c553ac19e73235b61b67fdc5c14be9913a2758d (diff) |
ARM: 8165/1: alignment: don't break misaligned NEON load/store
The alignment fixup incorrectly decodes faulting ARM VLDn/VSTn
instructions (where the optional alignment hint is given but incorrect)
as LDR/STR, leading to register corruption. Detect these and correctly
treat them as unhandled, so that userspace gets the fault it expects.
Reported-by: Simon Hosie <simon.hosie@arm.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/alignment.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 0c1ab49e5f7b..83792f4324ea 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c | |||
@@ -41,6 +41,7 @@ | |||
41 | * This code is not portable to processors with late data abort handling. | 41 | * This code is not portable to processors with late data abort handling. |
42 | */ | 42 | */ |
43 | #define CODING_BITS(i) (i & 0x0e000000) | 43 | #define CODING_BITS(i) (i & 0x0e000000) |
44 | #define COND_BITS(i) (i & 0xf0000000) | ||
44 | 45 | ||
45 | #define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */ | 46 | #define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */ |
46 | #define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */ | 47 | #define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */ |
@@ -821,6 +822,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
821 | break; | 822 | break; |
822 | 823 | ||
823 | case 0x04000000: /* ldr or str immediate */ | 824 | case 0x04000000: /* ldr or str immediate */ |
825 | if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */ | ||
826 | goto bad; | ||
824 | offset.un = OFFSET_BITS(instr); | 827 | offset.un = OFFSET_BITS(instr); |
825 | handler = do_alignment_ldrstr; | 828 | handler = do_alignment_ldrstr; |
826 | break; | 829 | break; |