diff options
author | Rich Felker <dalias@aerifal.cx> | 2016-12-18 19:38:53 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2016-12-19 21:21:08 -0500 |
commit | 29237f7f5c09c436825a7a12b68ab4143b0ebd1f (patch) | |
tree | 486acbdd1ea1f652fa79ca2ccba145dc745e7316 /src/thread/arm/__set_thread_area.c | |
parent | 9067a3006ea2f84395ab23a1dd30191387312e0c (diff) | |
download | musl-29237f7f5c09c436825a7a12b68ab4143b0ebd1f.tar.gz musl-29237f7f5c09c436825a7a12b68ab4143b0ebd1f.tar.bz2 musl-29237f7f5c09c436825a7a12b68ab4143b0ebd1f.tar.xz musl-29237f7f5c09c436825a7a12b68ab4143b0ebd1f.zip |
rework arm atomic/tp backends to be thumb-compatible and fdpic-ready
three problems are addressed:
- use of pc arithmetic, which was difficult if not impossible to make
correct in thumb mode on all models, so that relative rather than
absolute pointers to the backends could be used. this was designed
back when there was no coherent model for the early stages of the
dynamic linker before relocations, and is no longer necessary.
- assumption that data (the relative pointers to the backends) can be
accessed at a constant displacement from the code. this will not be
possible on future fdpic subarchs (for cortex-m), so move
responsibility for loading the backend code address to the caller.
- hard-coded arm opcodes using the .word directive. instead, use the
.arch directive to work around the assembler's refusal to assemble
instructions not available (or in some cases, available but just
considered deprecated) in the target isa level. the obscure v6t2
arch is used for v6 code so as to (1) allow generation of thumb2
output if -mthumb is active, and (2) avoid warnings/errors for mcr
barriers that clang would produce if we just set arch to v7-a.
in addition, the __aeabi_read_tp function is moved out of the inner
workings and implemented as an asm wrapper around a C function, so
that asm code does not need to read global data. the asm wrapper
serves to satisfy the ABI calling convention requirements for this
function.
Diffstat (limited to 'src/thread/arm/__set_thread_area.c')
-rw-r--r-- | src/thread/arm/__set_thread_area.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/src/thread/arm/__set_thread_area.c b/src/thread/arm/__set_thread_area.c index 61d02827..daf496c2 100644 --- a/src/thread/arm/__set_thread_area.c +++ b/src/thread/arm/__set_thread_area.c @@ -6,43 +6,47 @@ #define HWCAP_TLS (1 << 15) 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_barrier_oldkuser[], __a_barrier_v6[], __a_barrier_v7[], + __a_cas_v6[], __a_cas_v7[], + __a_gettp_cp15[]; #define __a_barrier_kuser 0xffff0fa0 +#define __a_barrier_oldkuser (uintptr_t)__a_barrier_oldkuser +#define __a_barrier_v6 (uintptr_t)__a_barrier_v6 +#define __a_barrier_v7 (uintptr_t)__a_barrier_v7 + #define __a_cas_kuser 0xffff0fc0 +#define __a_cas_v6 (uintptr_t)__a_cas_v6 +#define __a_cas_v7 (uintptr_t)__a_cas_v7 + #define __a_gettp_kuser 0xffff0fe0 +#define __a_gettp_cp15 (uintptr_t)__a_gettp_cp15 extern uintptr_t __attribute__((__visibility__("hidden"))) __a_barrier_ptr, __a_cas_ptr, __a_gettp_ptr; -#define SET(op,ver) (__a_##op##_ptr = \ - (uintptr_t)__a_##op##_##ver - (uintptr_t)__a_##op##_dummy) - int __set_thread_area(void *p) { #if !__ARM_ARCH_7A__ && !__ARM_ARCH_7R__ && __ARM_ARCH < 7 if (__hwcap & HWCAP_TLS) { size_t *aux; - SET(cas, v7); - SET(barrier, v7); + __a_cas_ptr = __a_cas_v7; + __a_barrier_ptr = __a_barrier_v7; for (aux=libc.auxv; *aux; aux+=2) { if (*aux != AT_PLATFORM) continue; const char *s = (void *)aux[1]; if (s[0]!='v' || s[1]!='6' || s[2]-'0'<10u) break; - SET(cas, v6); - SET(barrier, v6); + __a_cas_ptr = __a_cas_v6; + __a_barrier_ptr = __a_barrier_v6; break; } } else { int ver = *(int *)0xffff0ffc; - SET(gettp, kuser); - SET(cas, kuser); - SET(barrier, kuser); + __a_gettp_ptr = __a_gettp_kuser; + __a_cas_ptr = __a_cas_kuser; + __a_barrier_ptr = __a_barrier_kuser; if (ver < 2) a_crash(); - if (ver < 3) SET(barrier, oldkuser); + if (ver < 3) __a_barrier_ptr = __a_barrier_oldkuser; } #endif return __syscall(0xf0005, p); |