ARM: 8165/1: alignment: don't break misaligned NEON load/store
authorRobin Murphy <robin.murphy@arm.com>
Thu, 25 Sep 2014 10:56:19 +0000 (11:56 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 5 Oct 2014 21:52:16 +0000 (14:52 -0700)
commit 5ca918e5e3f9df4634077c06585c42bc6a8d699a upstream.

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>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/mm/alignment.c

index 9240364..d301662 100644 (file)
@@ -40,6 +40,7 @@
  * This code is not portable to processors with late data abort handling.
  */
 #define CODING_BITS(i) (i & 0x0e000000)
+#define COND_BITS(i)   (i & 0xf0000000)
 
 #define LDST_I_BIT(i)  (i & (1 << 26))         /* Immediate constant   */
 #define LDST_P_BIT(i)  (i & (1 << 24))         /* Preindex             */
@@ -817,6 +818,8 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                break;
 
        case 0x04000000:        /* ldr or str immediate */
+               if (COND_BITS(instr) == 0xf0000000) /* NEON VLDn, VSTn */
+                       goto bad;
                offset.un = OFFSET_BITS(instr);
                handler = do_alignment_ldrstr;
                break;