Commit 3855ab61 authored by Ard Biesheuvel's avatar Ard Biesheuvel

ARM: smp: Free up the TLS register while running in the kernel

To prepare for a subsequent patch that stores the current task pointer
in the user space TLS register while running in the kernel, modify the
set_tls and switch_tls routines not to touch the register directly, and
update the return to user space code to load the correct value.
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Tested-by: default avatarAmit Daniel Kachhap <amit.kachhap@arm.com>
parent 19f29aeb
...@@ -12,8 +12,8 @@ ...@@ -12,8 +12,8 @@
.macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2 .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2
mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register
mcr p15, 0, \tp, c13, c0, 3 @ set TLS register @ TLS register update is deferred until return to user space
mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register mcr p15, 0, \tpuser, c13, c0, 2 @ set the user r/w register
str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it
.endm .endm
...@@ -38,18 +38,22 @@ ...@@ -38,18 +38,22 @@
#ifdef CONFIG_TLS_REG_EMUL #ifdef CONFIG_TLS_REG_EMUL
#define tls_emu 1 #define tls_emu 1
#define has_tls_reg 1 #define has_tls_reg 1
#define defer_tls_reg_update 0
#define switch_tls switch_tls_none #define switch_tls switch_tls_none
#elif defined(CONFIG_CPU_V6) #elif defined(CONFIG_CPU_V6)
#define tls_emu 0 #define tls_emu 0
#define has_tls_reg (elf_hwcap & HWCAP_TLS) #define has_tls_reg (elf_hwcap & HWCAP_TLS)
#define defer_tls_reg_update 0
#define switch_tls switch_tls_v6 #define switch_tls switch_tls_v6
#elif defined(CONFIG_CPU_32v6K) #elif defined(CONFIG_CPU_32v6K)
#define tls_emu 0 #define tls_emu 0
#define has_tls_reg 1 #define has_tls_reg 1
#define defer_tls_reg_update 1
#define switch_tls switch_tls_v6k #define switch_tls switch_tls_v6k
#else #else
#define tls_emu 0 #define tls_emu 0
#define has_tls_reg 0 #define has_tls_reg 0
#define defer_tls_reg_update 0
#define switch_tls switch_tls_software #define switch_tls switch_tls_software
#endif #endif
...@@ -77,7 +81,7 @@ static inline void set_tls(unsigned long val) ...@@ -77,7 +81,7 @@ static inline void set_tls(unsigned long val)
*/ */
barrier(); barrier();
if (!tls_emu) { if (!tls_emu && !defer_tls_reg_update) {
if (has_tls_reg) { if (has_tls_reg) {
asm("mcr p15, 0, %0, c13, c0, 3" asm("mcr p15, 0, %0, c13, c0, 3"
: : "r" (val)); : : "r" (val));
......
...@@ -292,6 +292,14 @@ ...@@ -292,6 +292,14 @@
.macro restore_user_regs, fast = 0, offset = 0 .macro restore_user_regs, fast = 0, offset = 0
#if defined(CONFIG_CPU_32v6K) && !defined(CONFIG_CPU_V6)
@ The TLS register update is deferred until return to user space so we
@ can use it for other things while running in the kernel
get_thread_info r1
ldr r1, [r1, #TI_TP_VALUE]
mcr p15, 0, r1, c13, c0, 3 @ set TLS register
#endif
uaccess_enable r1, isb=0 uaccess_enable r1, isb=0
#ifndef CONFIG_THUMB2_KERNEL #ifndef CONFIG_THUMB2_KERNEL
@ ARM mode restore @ ARM mode restore
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment