@@ -59,6 +59,7 @@ struct thread_info {
__u32 syscall; /* syscall number */
__u8 used_cp[16]; /* thread used copro */
unsigned long tp_value;
+ unsigned long tp2_value; /* userspace read/write thread id register (2) */
#ifdef CONFIG_CRUNCH
struct crunch_state crunchstate;
#endif
@@ -7,8 +7,6 @@
.macro set_tls_v6k, tp, tmp1, tmp2
mcr p15, 0, \tp, c13, c0, 3 @ set TLS register
- mov \tmp1, #0
- mcr p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register
.endm
.macro set_tls_v6, tp, tmp1, tmp2
@@ -17,8 +15,6 @@
mov \tmp2, #0xffff0fff
tst \tmp1, #HWCAP_TLS @ hardware TLS available?
mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register
- movne \tmp1, #0
- mcrne p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register
streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0
.endm
@@ -26,24 +22,63 @@
mov \tmp1, #0xffff0fff
str \tp, [\tmp1, #-15] @ set TLS value at 0xffff0ff0
.endm
+
+ .macro set_tls2_none, tp2, tmp1, tmp2
+ .endm
+
+ .macro set_tls2_v6k, tp2, tmp1, tmp2
+ mcr p15, 0, \tp2, c13, c0, 2 @ set TPIDRURW register
+ .endm
+
+ .macro set_tls2_v6, tp2, tmp1, tmp2
+ ldr \tmp1, =elf_hwcap
+ ldr \tmp1, [\tmp1, #0]
+ mov \tmp2, #0xffff0fff
+ tst \tmp1, #HWCAP_TLS @ hardware TLS available?
+ mcrne p15, 0, \tp2, c13, c0, 2 @ yes, set TPIDRURW register
+ .endm
+
+ .macro get_tls2_none, tp2, tmp1, tmp2
+ .endm
+
+ .macro get_tls2_v6k, tp2, tmp1, tmp2
+ mrc p15, 0, \tp2, c13, c0, 2 @ get TPIDRURW register
+ .endm
+
+ .macro get_tls2_v6, tp2, tmp1, tmp2
+ ldr \tmp1, =elf_hwcap
+ ldr \tmp1, [\tmp1, #0]
+ mov \tmp2, #0xffff0fff
+ tst \tmp1, #HWCAP_TLS @ hardware TLS available?
+ mrcne p15, 0, \tp2, c13, c0, 2 @ yes, get TPIDRURW register
+ .endm
+
#endif
#ifdef CONFIG_TLS_REG_EMUL
#define tls_emu 1
#define has_tls_reg 1
#define set_tls set_tls_none
+#define set_tls2 set_tls2_none
+#define get_tls2 get_tls2_none
#elif defined(CONFIG_CPU_V6)
#define tls_emu 0
#define has_tls_reg (elf_hwcap & HWCAP_TLS)
#define set_tls set_tls_v6
+#define set_tls2 set_tls2_v6
+#define get_tls2 get_tls2_v6
#elif defined(CONFIG_CPU_32v6K)
#define tls_emu 0
#define has_tls_reg 1
#define set_tls set_tls_v6k
+#define set_tls2 set_tls2_v6k
+#define get_tls2 get_tls2_v6k
#else
#define tls_emu 0
#define has_tls_reg 0
#define set_tls set_tls_software
+#define set_tls2 set_tls2_none
+#define get_tls2 get_tls2_none
#endif
#endif /* __ASMARM_TLS_H */
@@ -58,6 +58,7 @@ int main(void)
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp));
DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
+ DEFINE(TI_TP2_VALUE, offsetof(struct thread_info, tp2_value));
DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate));
#ifdef CONFIG_VFP
DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate));
@@ -737,6 +737,13 @@ ENTRY(__switch_to)
ldr r6, [r2, #TI_CPU_DOMAIN]
#endif
set_tls r3, r4, r5
+
+ @ preserve TPIDRURW register state
+ get_tls2 r3, r4, r5
+ str r3, [r1, #TI_TP2_VALUE]
+ ldr r3, [r2, #TI_TP2_VALUE]
+ set_tls2 r3, r4, r5
+
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
ldr r7, [r2, #TI_TASK]
ldr r8, =__stack_chk_guard