From 8cd0b11eafeaaec3df5113cb39094e5456ca6b22 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sat, 22 Nov 2014 12:26:38 -0500 Subject: [PATCH] fix __aeabi_read_tp oversight in arm atomics/tls overhaul calls to __aeabi_read_tp may be generated by the compiler to access TLS on pre-v6 targets. previously, this function was hard-coded to call the kuser helper, which would crash on kernels with kuser helper removed. to fix the problem most efficiently, the definition of __aeabi_read_tp is moved so that it's an alias for the new __a_gettp. however, on v7+ targets, code to initialize the runtime choice of thread-pointer loading code is not even compiled, meaning that defining __aeabi_read_tp would have caused an immediate crash due to using the default implementation of __a_gettp with a HCF instruction. fortunately there is an elegant solution which reduces overall code size: putting the native thread-pointer loading instruction in the default code path for __a_gettp, so that separate default/native code paths are not needed. this function should never be called before __set_thread_area anyway, and if it is called early on pre-v6 hardware, the old behavior (crashing) is maintained. ideally __aeabi_read_tp would not be called at all on v7+ targets anyway -- in fact, prior to the overhaul, the same problem existed, but it was never caught by users building for v7+ with kuser disabled. however, it's possible for calls to __aeabi_read_tp to end up in a v7+ binary if some of the object files were built for pre-v7 targets, e.g. in the case of static libraries that were built separately, so this case needs to be handled. --- arch/arm/src/__set_thread_area.c | 3 +-- arch/arm/src/arm/atomics.s | 8 ++++---- src/thread/arm/tls.s | 4 ---- 3 files changed, 5 insertions(+), 10 deletions(-) delete mode 100644 src/thread/arm/tls.s diff --git a/arch/arm/src/__set_thread_area.c b/arch/arm/src/__set_thread_area.c index 680510ea..61d02827 100644 --- a/arch/arm/src/__set_thread_area.c +++ b/arch/arm/src/__set_thread_area.c @@ -9,7 +9,7 @@ extern const unsigned char __attribute__((__visibility__("hidden"))) __a_barrier_dummy[], __a_barrier_oldkuser[], __a_barrier_v6[], __a_barrier_v7[], __a_cas_dummy[], __a_cas_v6[], __a_cas_v7[], - __a_gettp_dummy[], __a_gettp_native[]; + __a_gettp_dummy[]; #define __a_barrier_kuser 0xffff0fa0 #define __a_cas_kuser 0xffff0fc0 @@ -26,7 +26,6 @@ int __set_thread_area(void *p) #if !__ARM_ARCH_7A__ && !__ARM_ARCH_7R__ && __ARM_ARCH < 7 if (__hwcap & HWCAP_TLS) { size_t *aux; - SET(gettp, native); SET(cas, v7); SET(barrier, v7); for (aux=libc.auxv; *aux; aux+=2) { diff --git a/arch/arm/src/arm/atomics.s b/arch/arm/src/arm/atomics.s index 9fcc7bd7..f241cc02 100644 --- a/arch/arm/src/arm/atomics.s +++ b/arch/arm/src/arm/atomics.s @@ -81,6 +81,10 @@ __a_cas_v7: .word 0xf57ff05b /* dmb ish */ bx lr +.global __aeabi_read_tp +.type __aeabi_read_tp,%function +__aeabi_read_tp: + .global __a_gettp .hidden __a_gettp .type __a_gettp,%function @@ -92,10 +96,6 @@ __a_gettp: .global __a_gettp_dummy .hidden __a_gettp_dummy __a_gettp_dummy: - .word 0xe7fddef1 -.global __a_gettp_native -.hidden __a_gettp_native -__a_gettp_native: mrc p15,0,r0,c13,c0,3 bx lr diff --git a/src/thread/arm/tls.s b/src/thread/arm/tls.s deleted file mode 100644 index 59736ac2..00000000 --- a/src/thread/arm/tls.s +++ /dev/null @@ -1,4 +0,0 @@ -.global __aeabi_read_tp -.type __aeabi_read_tp,%function -__aeabi_read_tp: - ldr pc,=0xffff0fe0 -- 2.25.1