Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 1 | #ifndef __ASMARM_TLS_H |
| 2 | #define __ASMARM_TLS_H |
| 3 | |
| 4 | #ifdef __ASSEMBLY__ |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 5 | #include <asm/asm-offsets.h> |
| 6 | .macro switch_tls_none, base, tp, tpuser, tmp1, tmp2 |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 7 | .endm |
| 8 | |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 9 | .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2 |
| 10 | mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 11 | mcr p15, 0, \tp, c13, c0, 3 @ set TLS register |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 12 | mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register |
| 13 | str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 14 | .endm |
| 15 | |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 16 | .macro switch_tls_v6, base, tp, tpuser, tmp1, tmp2 |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 17 | ldr \tmp1, =elf_hwcap |
| 18 | ldr \tmp1, [\tmp1, #0] |
| 19 | mov \tmp2, #0xffff0fff |
| 20 | tst \tmp1, #HWCAP_TLS @ hardware TLS available? |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 21 | streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0 |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 22 | mrcne p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register |
| 23 | mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register |
| 24 | mcrne p15, 0, \tpuser, c13, c0, 2 @ set user r/w register |
| 25 | strne \tmp2, [\base, #TI_TP_VALUE + 4] @ save it |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 26 | .endm |
| 27 | |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 28 | .macro switch_tls_software, base, tp, tpuser, tmp1, tmp2 |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 29 | mov \tmp1, #0xffff0fff |
| 30 | str \tp, [\tmp1, #-15] @ set TLS value at 0xffff0ff0 |
| 31 | .endm |
| 32 | #endif |
| 33 | |
| 34 | #ifdef CONFIG_TLS_REG_EMUL |
| 35 | #define tls_emu 1 |
| 36 | #define has_tls_reg 1 |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 37 | #define switch_tls switch_tls_none |
Russell King | 37bc618 | 2011-01-17 16:38:56 +0000 | [diff] [blame] | 38 | #elif defined(CONFIG_CPU_V6) |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 39 | #define tls_emu 0 |
| 40 | #define has_tls_reg (elf_hwcap & HWCAP_TLS) |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 41 | #define switch_tls switch_tls_v6 |
Russell King | 37bc618 | 2011-01-17 16:38:56 +0000 | [diff] [blame] | 42 | #elif defined(CONFIG_CPU_32v6K) |
| 43 | #define tls_emu 0 |
| 44 | #define has_tls_reg 1 |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 45 | #define switch_tls switch_tls_v6k |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 46 | #else |
| 47 | #define tls_emu 0 |
| 48 | #define has_tls_reg 0 |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 49 | #define switch_tls switch_tls_software |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 50 | #endif |
| 51 | |
André Hentschel | a0730e8 | 2013-06-18 23:23:26 +0100 | [diff] [blame] | 52 | #ifndef __ASSEMBLY__ |
| 53 | static inline unsigned long get_tpuser(void) |
| 54 | { |
| 55 | unsigned long reg = 0; |
| 56 | |
| 57 | if (has_tls_reg && !tls_emu) |
| 58 | __asm__("mrc p15, 0, %0, c13, c0, 2" : "=r" (reg)); |
| 59 | |
| 60 | return reg; |
| 61 | } |
| 62 | #endif |
Tony Lindgren | f159f4e | 2010-07-05 14:53:10 +0100 | [diff] [blame] | 63 | #endif /* __ASMARM_TLS_H */ |