1 /*
2  * Copyright (c) 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/kernel_structs.h>
9 #include <kernel_internal.h>
10 #include <kernel_tls.h>
11 #include <zephyr/sys/util.h>
12 
arch_tls_stack_setup(struct k_thread * new_thread,char * stack_ptr)13 size_t arch_tls_stack_setup(struct k_thread *new_thread, char *stack_ptr)
14 {
15 	/*
16 	 * TLS area for x86 and x86_64 has the data/bss first,
17 	 * then a pointer pointing to itself. The address to
18 	 * this pointer needs to be stored in register GS (x86)
19 	 * or FS (x86_64). GCC generates code which reads this
20 	 * pointer and offsets from this pointer are used to
21 	 * access data.
22 	 */
23 
24 	uintptr_t *self_ptr;
25 
26 	/*
27 	 * Since we are populating things backwards, store
28 	 * the pointer to the TLS area at top of stack.
29 	 */
30 	stack_ptr -= sizeof(uintptr_t);
31 	self_ptr = (void *)stack_ptr;
32 	*self_ptr = POINTER_TO_UINT(stack_ptr);
33 
34 	/*
35 	 * Set thread TLS pointer as this is used to populate
36 	 * FS/GS at context switch.
37 	 */
38 	new_thread->tls = POINTER_TO_UINT(self_ptr);
39 
40 	/* Setup the TLS data */
41 	stack_ptr -= z_tls_data_size();
42 	z_tls_copy(stack_ptr);
43 
44 	return (z_tls_data_size() + sizeof(uintptr_t));
45 }
46