/* [<][>][^][v][top][bottom][index][help] */
1 #ifndef TLSUTIL_H
2 #define TLSUTIL_H
3
4 /* These functions are not defined for x86_64. */
5 #ifdef __i386__
6 # define tls_get_thread_area(arg, myinfo_gs) \
7 mtcp_sys_get_thread_area(arg)
8 # define tls_set_thread_area(arg, myinfo_gs) \
9 mtcp_sys_set_thread_area(arg)
10 #endif
11
12 #ifdef __x86_64__
13 # include <asm/prctl.h>
14 # include <sys/prctl.h>
15 /* man arch_prctl has both signatures, and prctl.h above has no declaration.
16 * int arch_prctl(int code, unsigned long addr);
17 * int arch_prctl(int code, unsigned long addr);
18 */
19
20 int arch_prctl();
21 #if 1
22 // These calls need to be made from both DMTCP and mtcp_restart
23 /* ARE THE _GS OPERATIONS NECESSARY? */
24 # define tls_get_thread_area(uinfo, myinfo_gs) \
25 ( mtcp_inline_syscall(arch_prctl,2,ARCH_GET_FS, \
26 (unsigned long int)(&(((struct user_desc *)uinfo)->base_addr))), \
27 mtcp_inline_syscall(arch_prctl,2,ARCH_GET_GS, &myinfo_gs) \
28 )
29 # define tls_set_thread_area(uinfo, myinfo_gs) \
30 ( mtcp_inline_syscall(arch_prctl,2,ARCH_SET_FS, \
31 *(unsigned long int *)&(((struct user_desc *)uinfo)->base_addr)), \
32 mtcp_inline_syscall(arch_prctl,2,ARCH_SET_GS, myinfo_gs) \
33 )
34 # else
35 /* ARE THE _GS OPERATIONS NECESSARY? */
36 # define tls_get_thread_area(uinfo, myinfo_gs) \
37 ( arch_prctl(ARCH_GET_FS, \
38 (unsigned long int)(&(((struct user_desc *)uinfo)->base_addr))), \
39 arch_prctl(ARCH_GET_GS, &myinfo_gs) \
40 )
41 # define tls_set_thread_area(uinfo, myinfo_gs) \
42 ( arch_prctl(ARCH_SET_FS, \
43 *(unsigned long int *)&(((struct user_desc *)uinfo)->base_addr)), \
44 arch_prctl(ARCH_SET_GS, myinfo_gs) \
45 )
46 # endif
47 #endif /* end __x86_64__ */
48
49 #ifdef __arm__
50 /* This allocation hack will work only if calls to mtcp_sys_get_thread_area
51 * and mtcp_sys_get_thread_area are both inside the same file (mtcp.c).
52 * This is all because get_thread_area is not implemented for arm.
53 * For ARM, the thread pointer seems to point to the next slot
54 * after the 'struct pthread'. Why?? So, we subtract that address.
55 * After that, tid/pid will be located at offset 104/108 as expected
56 * for glibc-2.13.
57 * NOTE: 'struct pthread' defined in glibc/nptl/descr.h
58 * The value below (1216) is current for glibc-2.13.
59 * May have to update 'sizeof(struct pthread)' for new versions of glibc.
60 * We can automate this by searching for negative offset from end
61 * of 'struct pthread' in tls_tid_offset, tls_pid_offset in mtcp.c.
62 */
63
64 # define tls_get_thread_area(uinfo, myinfo_gs) \
65 ({ asm volatile ("mrc p15, 0, %0, c13, c0, 3 @ load_tp_hard\n\t" \
66 : "=r" (myinfo_gs) ); \
67 myinfo_gs = myinfo_gs - 1216; /* sizeof(struct pthread) = 1216 */ \
68 *(unsigned long int *)&(((struct user_desc *)uinfo)->base_addr) \
69 = myinfo_gs; \
70 myinfo_gs; })
71 # define tls_set_thread_area(uinfo, myinfo_gs) \
72 ( myinfo_gs = \
73 *(unsigned long int *)&(((struct user_desc *)uinfo)->base_addr), \
74 (mtcp_sys_kernel_set_tls(myinfo_gs+1216), 0) \
75 /* 0 return value at end means success */ )
76 #endif /* end __arm__ */
77
78 #ifdef __aarch64__
79 /* This allocation hack will work only if calls to mtcp_sys_get_thread_area
80 * and mtcp_sys_get_thread_area are both inside the same file (mtcp.c).
81 * This is all because get_thread_area is not implemented for aarch64.
82 * For ARM, the thread pointer seems to point to the next slot
83 * after the 'struct pthread'. Why?? So, we subtract that address.
84 * After that, tid/pid will be located at offset 208/212 as expected
85 * for glibc-2.17.
86 * NOTE: 'struct pthread' defined in glibc/nptl/descr.h
87 * The value below (1776) is current for glibc-2.17.
88 # See PORTING file for easy way to compute these numbers.
89 * May have to update 'sizeof(struct pthread)' for new versions of glibc.
90 * We can automate this by searching for negative offset from end
91 * of 'struct pthread' in tls_tid_offset, tls_pid_offset in mtcp.c.
92 */
93 /* NOTE: We want 'sizeof(myinfo_gs) == sizeof(unsigned long int)' always. */
94 # define tls_get_thread_area(uinfo, myinfo_gs) \
95 ({ asm volatile ("mrs %0, tpidr_el0" \
96 : "=r" (myinfo_gs) ); \
97 myinfo_gs = myinfo_gs - 1776; /* sizeof(struct pthread) = 1776 */ \
98 *(unsigned long int *)&(((struct user_desc *)uinfo)->base_addr) \
99 = myinfo_gs; \
100 myinfo_gs; })
101 # define tls_set_thread_area(uinfo, myinfo_gs) \
102 ({ myinfo_gs = \
103 *(unsigned long int *)&(((struct user_desc *)uinfo)->base_addr); \
104 myinfo_gs = myinfo_gs + 1776; \
105 asm volatile ("msr tpidr_el0, %[gs]" : : [gs] "r" (myinfo_gs) ); \
106 0; })
107 #endif /* end __aarch64__ */
108
109 #endif /* TLSUTIL_H */