diff options
author | Mark Charlebois <charlebm@gmail.com> | 2014-03-11 10:43:45 -0700 |
---|---|---|
committer | Behan Webster <behanw@converseincode.com> | 2014-03-31 00:07:21 -0700 |
commit | cfb5300b065aec89d943e4bf80314024fce935c8 (patch) | |
tree | f2f4a25d361fdba0e1857484da049b481417a60d /arch/arm/include/asm/compiler.h | |
parent | f5841fc320d50027b692ddb57a2e21affe145ead (diff) |
LLVMLinux: Remove use of named register for ARM percpu
The use of sp as a named register variable is not supported in clang and
the behavior they are working around in GCC may not even be present
in clang.
See commit 509eb76ebf97
Unfortunately, GCC doesn't treat a "memory" clobber on a non-volatile
asm block as a side-effect, and will happily re-order it before other
memory clobbers (including those in prempt_disable()) and cache the
value. This has been observed to break the cmpxchg logic in the slub
allocator, leading to livelock in kmem_cache_alloc in mainline kernels.
Because the GCC workaround causes numerous warnings, revert the change
until it can be verified that it is in fact an issue for clang.
Signed-off-by: Mark Charlebois <charlebm@gmail.com>
Signed-off-by: Behan Webster <behanw@converseincode.com>
Diffstat (limited to 'arch/arm/include/asm/compiler.h')
-rw-r--r-- | arch/arm/include/asm/compiler.h | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/arm/include/asm/compiler.h b/arch/arm/include/asm/compiler.h index 8155db2f7fa..009eafa2ea0 100644 --- a/arch/arm/include/asm/compiler.h +++ b/arch/arm/include/asm/compiler.h @@ -11,5 +11,37 @@ */ #define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" +#if defined(CONFIG_SMP) && !defined(CONFIG_CPU_V6) +/* + * Read TPIDRPRW. + * GCC requires a workaround as it does not treat a "memory" clobber on a + * non-volatile asm block as a side-effect. + * We want to allow caching the value, so for GCC avoid using volatile and + * instead use a fake stack read to hazard against barrier(). + */ +#if defined(__clang__) +static inline unsigned long read_TPIDRPRW(void) +{ + unsigned long off; + + /* + * Read TPIDRPRW. + */ + asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : : "memory"); + + return off; +} +#else +static inline unsigned long read_TPIDRPRW(void) +{ + unsigned long off; + register unsigned long *sp asm ("sp"); + + asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : "Q" (*sp)); + + return off; +} +#endif +#endif #endif /* __ASM_ARM_COMPILER_H */ |