5 #include <asm/asm-offsets.h>
6 .macro switch_tls_none
, prev
, next
, tp
, tpuser
, tmp1
, tmp2
9 .macro switch_tls_v6k
, prev
, next
, tp
, tpuser
, tmp1
, tmp2
10 ldrd
\tp
, \tpuser
, [\next
, #TI_TP_VALUE] @ get the next TLS and user r/w register
11 mrc p15
, 0, \tmp
2, c13
, c0
, 2 @ get the user r
/w
register
12 mcr p15
, 0, \tp
, c13
, c0
, 3 @ set TLS
register
13 mcr p15
, 0, \tpuser
, c13
, c0
, 2 @
and the user r
/w
register
14 str
\tmp
2, [\prev
, #TI_TP_VALUE + 4] @ save it
17 .macro switch_tls_v6
, prev
, next
, tp
, tpuser
, tmp1
, tmp2
19 ldr
\tmp
1, [\tmp
1, #0]
20 mov
\tmp
2, #0xffff0fff
21 ldr
\tp
, [\next
, #TI_TP_VALUE] @ get the next TLS register
22 tst
\tmp
1, #HWCAP_TLS @ hardware TLS available?
23 streq
\tp
, [\tmp
2, #-15] @ set TLS value at 0xffff0ff0
24 mrcne p15
, 0, \tmp
2, c13
, c0
, 2 @ get the previous user r
/w
register
25 ldrne
\tpuser
, [\next
, #TI_TP_VALUE + 4] @ get the next user r/w register
26 mcrne p15
, 0, \tp
, c13
, c0
, 3 @ yes
, set TLS
register
27 mcrne p15
, 0, \tpuser
, c13
, c0
, 2 @ set user r
/w
register
28 strne
\tmp
2, [\prev
, #TI_TP_VALUE + 4] @ save it
31 .macro switch_tls_software
, prev
, next
, tp
, tpuser
, tmp1
, tmp2
32 mov
\tmp
1, #0xffff0fff
33 str
\tp
, [\tmp
1, #-15] @ set TLS value at 0xffff0ff0
37 #ifdef CONFIG_TLS_REG_EMUL
40 #define switch_tls switch_tls_none
41 #elif defined(CONFIG_CPU_V6)
43 #define has_tls_reg (elf_hwcap & HWCAP_TLS)
44 #define switch_tls switch_tls_v6
45 #elif defined(CONFIG_CPU_32v6K)
48 #define switch_tls switch_tls_v6k
52 #define switch_tls switch_tls_software
56 static inline unsigned long get_tpuser(void)
58 unsigned long reg
= 0;
60 if (has_tls_reg
&& !tls_emu
)
61 __asm__("mrc p15, 0, %0, c13, c0, 2" : "=r" (reg
));
66 #endif /* __ASMARM_TLS_H */