1b2b3ffcdSSimon Schubert /*
2*4c898ae5SMatthew Dillon * Copyright (c) 2005,2008,2020 The DragonFly Project. All rights reserved.
3b2b3ffcdSSimon Schubert *
4b2b3ffcdSSimon Schubert * Redistribution and use in source and binary forms, with or without
5b2b3ffcdSSimon Schubert * modification, are permitted provided that the following conditions
6b2b3ffcdSSimon Schubert * are met:
7b2b3ffcdSSimon Schubert *
8b2b3ffcdSSimon Schubert * 1. Redistributions of source code must retain the above copyright
9b2b3ffcdSSimon Schubert * notice, this list of conditions and the following disclaimer.
10b2b3ffcdSSimon Schubert * 2. Redistributions in binary form must reproduce the above copyright
11b2b3ffcdSSimon Schubert * notice, this list of conditions and the following disclaimer in
12b2b3ffcdSSimon Schubert * the documentation and/or other materials provided with the
13b2b3ffcdSSimon Schubert * distribution.
14b2b3ffcdSSimon Schubert * 3. Neither the name of The DragonFly Project nor the names of its
15b2b3ffcdSSimon Schubert * contributors may be used to endorse or promote products derived
16b2b3ffcdSSimon Schubert * from this software without specific, prior written permission.
17b2b3ffcdSSimon Schubert *
18b2b3ffcdSSimon Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19b2b3ffcdSSimon Schubert * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20b2b3ffcdSSimon Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21b2b3ffcdSSimon Schubert * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22b2b3ffcdSSimon Schubert * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23b2b3ffcdSSimon Schubert * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24b2b3ffcdSSimon Schubert * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25b2b3ffcdSSimon Schubert * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26b2b3ffcdSSimon Schubert * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27b2b3ffcdSSimon Schubert * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28b2b3ffcdSSimon Schubert * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29b2b3ffcdSSimon Schubert * SUCH DAMAGE.
30b2b3ffcdSSimon Schubert */
31b2b3ffcdSSimon Schubert
32b2b3ffcdSSimon Schubert #ifndef _CPU_TLS_H_
33b2b3ffcdSSimon Schubert #define _CPU_TLS_H_
34b2b3ffcdSSimon Schubert
35b2b3ffcdSSimon Schubert #ifndef _SYS_TYPES_H_
36b2b3ffcdSSimon Schubert #include <sys/types.h>
37b2b3ffcdSSimon Schubert #endif
38b2b3ffcdSSimon Schubert #ifndef _SYS_TLS_H_
39b2b3ffcdSSimon Schubert #include <sys/tls.h>
40b2b3ffcdSSimon Schubert #endif
41b2b3ffcdSSimon Schubert
42b2b3ffcdSSimon Schubert /*
43b2b3ffcdSSimon Schubert * NOTE: the tcb_{self,dtv,pthread,errno) fields must be declared
44b2b3ffcdSSimon Schubert * in the structure in the specified order as assembly will access the
45b2b3ffcdSSimon Schubert * fields with a hardwired offset.
46b2b3ffcdSSimon Schubert *
47b2b3ffcdSSimon Schubert * Outside of this file, the system call layer generation will hardwire
48b2b3ffcdSSimon Schubert * the offset for tcb_errno.
49b2b3ffcdSSimon Schubert */
50b2b3ffcdSSimon Schubert struct tls_tcb {
51b2b3ffcdSSimon Schubert struct tls_tcb *tcb_self; /* pointer to self*/
52b2b3ffcdSSimon Schubert void *tcb_dtv; /* Dynamic Thread Vector */
53b2b3ffcdSSimon Schubert void *tcb_pthread; /* thread library's data*/
54b2b3ffcdSSimon Schubert int *tcb_errno_p; /* pointer to per-thread errno */
55166bae11SMichael Neumann void *tcb_segstack; /* used for segmented stacks */
56166bae11SMichael Neumann /* e.g. by LLVM to store stack bound */
57e900a7a2SMichael Neumann /* NOTE: do not reorder this field */
58e900a7a2SMichael Neumann /* as LLVM uses a fixed offset (32) */
59166bae11SMichael Neumann void *tcb_unused[3];
60b2b3ffcdSSimon Schubert };
61b2b3ffcdSSimon Schubert
62b2b3ffcdSSimon Schubert struct tls_dtv {
63b2b3ffcdSSimon Schubert uintptr_t dtv_generation;
64b2b3ffcdSSimon Schubert uintptr_t dtv_max_index;
65b2b3ffcdSSimon Schubert void *dtv_offset[__ARRAY_ZERO];
66b2b3ffcdSSimon Schubert };
67b2b3ffcdSSimon Schubert
68e4f37b93SMatthew Dillon /*
69e4f37b93SMatthew Dillon * NOTE: RTLD_STATIC_TLS_EXTRA_DEFAULT is set as the kernel's kern.tls_extra
70e4f37b93SMatthew Dillon * default, generally made large enough to accomodate modern libraries
71e4f37b93SMatthew Dillon * that desire to use static TLS sections. Make it roughly 2048 bytes
72e4f37b93SMatthew Dillon * smaller than a multiple of an aligned page for allocation efficiency.
73e4f37b93SMatthew Dillon */
74b2b3ffcdSSimon Schubert #define RTLD_TCB_HAS_SELF_POINTER
75b2b3ffcdSSimon Schubert #define RTLD_STATIC_TLS_ALIGN 16
76b2b3ffcdSSimon Schubert #define RTLD_STATIC_TLS_ALIGN_MASK (RTLD_STATIC_TLS_ALIGN - 1)
77e4f37b93SMatthew Dillon #define RTLD_STATIC_TLS_EXTRA_MIN 2048
78e4f37b93SMatthew Dillon #define RTLD_STATIC_TLS_EXTRA_MAX (1*1024*1024*1024)
79e4f37b93SMatthew Dillon #define RTLD_STATIC_TLS_EXTRA_DEFAULT 6144 /* sysctl kern.tls_extra */
80b2b3ffcdSSimon Schubert #define RTLD_STATIC_TLS_VARIANT_II
81b2b3ffcdSSimon Schubert
82b2b3ffcdSSimon Schubert /* Get the current TCB. */
83b2b3ffcdSSimon Schubert static __inline struct tls_tcb *
tls_get_tcb(void)84b2b3ffcdSSimon Schubert tls_get_tcb(void)
85b2b3ffcdSSimon Schubert {
86b2b3ffcdSSimon Schubert void *self;
87b2b3ffcdSSimon Schubert
88b2b3ffcdSSimon Schubert __asm __volatile ("movq %%fs:%1, %0"
89b2b3ffcdSSimon Schubert : "=r" (self)
90b2b3ffcdSSimon Schubert : "m" (((struct tls_tcb *)0)->tcb_self));
91b2b3ffcdSSimon Schubert
92b2b3ffcdSSimon Schubert return(self);
93b2b3ffcdSSimon Schubert }
94b2b3ffcdSSimon Schubert
95b2b3ffcdSSimon Schubert /* Get the current thread. */
96b2b3ffcdSSimon Schubert static __inline void *
tls_get_curthread(void)97b2b3ffcdSSimon Schubert tls_get_curthread(void)
98b2b3ffcdSSimon Schubert {
99b2b3ffcdSSimon Schubert void *self;
100b2b3ffcdSSimon Schubert
101b2b3ffcdSSimon Schubert __asm __volatile ("movq %%fs:%1, %0"
102b2b3ffcdSSimon Schubert : "=r" (self)
103b2b3ffcdSSimon Schubert : "m" (((struct tls_tcb *)0)->tcb_pthread));
104b2b3ffcdSSimon Schubert
105b2b3ffcdSSimon Schubert return(self);
106b2b3ffcdSSimon Schubert }
107b2b3ffcdSSimon Schubert
108b2b3ffcdSSimon Schubert static __inline void
tls_set_tcb(struct tls_tcb * tcb)109b2b3ffcdSSimon Schubert tls_set_tcb(struct tls_tcb *tcb)
110b2b3ffcdSSimon Schubert {
111b2b3ffcdSSimon Schubert struct tls_info info;
112b2b3ffcdSSimon Schubert int seg;
113b2b3ffcdSSimon Schubert
114b2b3ffcdSSimon Schubert info.base = tcb;
115b2b3ffcdSSimon Schubert info.size = -1;
116b2b3ffcdSSimon Schubert seg = set_tls_area(0, &info, sizeof(info));
117b2b3ffcdSSimon Schubert /*__asm __volatile("movl %0, %%fs" : : "r" (seg));*/
118b2b3ffcdSSimon Schubert }
119b2b3ffcdSSimon Schubert
120a293ac08SJordan Gordeev static __inline void
tls_set_gs(void * base,size_t bytes)121a293ac08SJordan Gordeev tls_set_gs(void *base, size_t bytes)
122a293ac08SJordan Gordeev {
123a293ac08SJordan Gordeev struct tls_info info;
124a293ac08SJordan Gordeev int seg;
125a293ac08SJordan Gordeev
126a293ac08SJordan Gordeev info.base = base;
127a293ac08SJordan Gordeev info.size = bytes;
128a293ac08SJordan Gordeev seg = set_tls_area(1, &info, sizeof(info));
129a293ac08SJordan Gordeev /*__asm __volatile("mov %0, %%fs" : : "g" (seg));*/
130a293ac08SJordan Gordeev }
131a293ac08SJordan Gordeev
132a293ac08SJordan Gordeev #ifndef _KERNEL
133a293ac08SJordan Gordeev
134b2b3ffcdSSimon Schubert struct tls_tcb *_rtld_allocate_tls(void);
135b2b3ffcdSSimon Schubert struct tls_tcb *_libc_allocate_tls(void);
136b2b3ffcdSSimon Schubert void _rtld_free_tls(struct tls_tcb *);
137b2b3ffcdSSimon Schubert void _libc_free_tls(struct tls_tcb *);
138b2b3ffcdSSimon Schubert void _rtld_call_init(void);
139b2b3ffcdSSimon Schubert struct tls_tcb *_libc_init_tls(void);
140b2b3ffcdSSimon Schubert struct tls_tcb *_init_tls(void);
141b2b3ffcdSSimon Schubert
142b2b3ffcdSSimon Schubert #endif
143b2b3ffcdSSimon Schubert
144b2b3ffcdSSimon Schubert #endif /* !_CPU_TLS_H_ */
145