ARM: 7031/1: entry: Fix Thumb-2 undef handling for multi-CPU kernels
When v6 and >=v7 boards are supported in the same kernel, the __und_usr code currently makes a build-time assumption that Thumb-2 instructions occurring in userspace don't need to be supported. Strictly speaking this is incorrect. This patch fixes the above case by doing a run-time check on the CPU architecture in these cases. This only affects kernels which support v6 and >=v7 CPUs together: plain v6 and plain v7 kernels are unaffected. Signed-off-by: Dave Martin <dave.martin@linaro.org> Reviewed-by: Jon Medhurst <tixy@yxit.co.uk> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
committed by
Russell King
parent
85519189df
commit
ef4c53687e
@@ -24,6 +24,7 @@
|
|||||||
#include <asm/unwind.h>
|
#include <asm/unwind.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
#include <asm/tls.h>
|
#include <asm/tls.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
|
||||||
#include "entry-header.S"
|
#include "entry-header.S"
|
||||||
#include <asm/entry-macro-multi.S>
|
#include <asm/entry-macro-multi.S>
|
||||||
@@ -439,7 +440,27 @@ __und_usr:
|
|||||||
#endif
|
#endif
|
||||||
beq call_fpe
|
beq call_fpe
|
||||||
@ Thumb instruction
|
@ 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:
|
2:
|
||||||
ARM( ldrht r5, [r4], #2 )
|
ARM( ldrht r5, [r4], #2 )
|
||||||
THUMB( ldrht r5, [r4] )
|
THUMB( ldrht r5, [r4] )
|
||||||
@@ -449,7 +470,16 @@ __und_usr:
|
|||||||
3: ldrht r0, [r4]
|
3: ldrht r0, [r4]
|
||||||
add r2, r2, #2 @ r2 is PC + 2, make it PC + 4
|
add r2, r2, #2 @ r2 is PC + 2, make it PC + 4
|
||||||
orr r0, r0, r5, lsl #16
|
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
|
#else
|
||||||
|
.arch armv6
|
||||||
|
#endif
|
||||||
|
#endif /* __LINUX_ARM_ARCH__ < 7 */
|
||||||
|
#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */
|
||||||
b __und_usr_unknown
|
b __und_usr_unknown
|
||||||
#endif
|
#endif
|
||||||
UNWIND(.fnend )
|
UNWIND(.fnend )
|
||||||
@@ -576,6 +606,12 @@ call_fpe:
|
|||||||
movw_pc lr @ CP#14 (Debug)
|
movw_pc lr @ CP#14 (Debug)
|
||||||
movw_pc lr @ CP#15 (Control)
|
movw_pc lr @ CP#15 (Control)
|
||||||
|
|
||||||
|
#ifdef NEED_CPU_ARCHITECTURE
|
||||||
|
.align 2
|
||||||
|
.LCcpu_architecture:
|
||||||
|
.word __cpu_architecture
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NEON
|
#ifdef CONFIG_NEON
|
||||||
.align 6
|
.align 6
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user