Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/vfs...
[pandora-kernel.git] / arch / arm / kernel / entry-armv.S
index a87cbf8..9ad50c4 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/unwind.h>
 #include <asm/unistd.h>
 #include <asm/tls.h>
+#include <asm/system.h>
 
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
@@ -262,8 +263,7 @@ __und_svc:
        ldr     r0, [r4, #-4]
 #else
        ldrh    r0, [r4, #-2]                   @ Thumb instruction at LR - 2
-       and     r9, r0, #0xf800
-       cmp     r9, #0xe800                     @ 32-bit instruction if xx >= 0
+       cmp     r0, #0xe800                     @ 32-bit instruction if xx >= 0
        ldrhhs  r9, [r4]                        @ bottom 16 bits
        orrhs   r0, r9, r0, lsl #16
 #endif
@@ -440,18 +440,46 @@ __und_usr:
 #endif
        beq     call_fpe
        @ Thumb instruction
-#if __LINUX_ARM_ARCH__ >= 7
+#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
+/*
+ * Thumb-2 instruction handling.  Note that because pre-v6 and >= v6 platforms
+ * can never be supported in a single kernel, this code is not applicable at
+ * all when __LINUX_ARM_ARCH__ < 6.  This allows simplifying assumptions to be
+ * made about .arch directives.
+ */
+#if __LINUX_ARM_ARCH__ < 7
+/* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */
+#define NEED_CPU_ARCHITECTURE
+       ldr     r5, .LCcpu_architecture
+       ldr     r5, [r5]
+       cmp     r5, #CPU_ARCH_ARMv7
+       blo     __und_usr_unknown
+/*
+ * The following code won't get run unless the running CPU really is v7, so
+ * coding round the lack of ldrht on older arches is pointless.  Temporarily
+ * override the assembler target arch with the minimum required instead:
+ */
+       .arch   armv6t2
+#endif
 2:
  ARM(  ldrht   r5, [r4], #2    )
  THUMB(        ldrht   r5, [r4]        )
  THUMB(        add     r4, r4, #2      )
-       and     r0, r5, #0xf800                 @ mask bits 111x x... .... ....
-       cmp     r0, #0xe800                     @ 32bit instruction if xx != 0
+       cmp     r5, #0xe800                     @ 32bit instruction if xx != 0
        blo     __und_usr_unknown
 3:     ldrht   r0, [r4]
        add     r2, r2, #2                      @ r2 is PC + 2, make it PC + 4
        orr     r0, r0, r5, lsl #16
+
+#if __LINUX_ARM_ARCH__ < 7
+/* If the target arch was overridden, change it back: */
+#ifdef CONFIG_CPU_32v6K
+       .arch   armv6k
 #else
+       .arch   armv6
+#endif
+#endif /* __LINUX_ARM_ARCH__ < 7 */
+#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */
        b       __und_usr_unknown
 #endif
  UNWIND(.fnend         )
@@ -578,6 +606,12 @@ call_fpe:
        movw_pc lr                              @ CP#14 (Debug)
        movw_pc lr                              @ CP#15 (Control)
 
+#ifdef NEED_CPU_ARCHITECTURE
+       .align  2
+.LCcpu_architecture:
+       .word   __cpu_architecture
+#endif
+
 #ifdef CONFIG_NEON
        .align  6