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/app_memory/app_memdomain.h>
12 #include <zephyr/sys/util.h>
13 
14 #ifdef CONFIG_CPU_CORTEX_M
15 /*
16  * Since Cortex-M does not have the thread ID or process ID
17  * register needed to store TLS pointer at runtime for
18  * toolchain to access thread data. Use a global variable
19  * instead.
20  */
K_APP_DMEM(z_libc_partition)21 K_APP_DMEM(z_libc_partition) uintptr_t z_arm_tls_ptr;
22 #endif
23 
24 size_t arch_tls_stack_setup(struct k_thread *new_thread, char *stack_ptr)
25 {
26 	/*
27 	 * TLS area for ARM has some data fields following by
28 	 * thread data and bss. These fields are supposed to be
29 	 * used by toolchain and OS TLS code to aid in locating
30 	 * the TLS data/bss. Zephyr currently has no use for
31 	 * this so we can simply skip these. However, since GCC
32 	 * is generating code assuming these fields are there,
33 	 * we simply skip them when setting the TLS pointer.
34 	 */
35 
36 	/*
37 	 * Since we are populating things backwards,
38 	 * setup the TLS data/bss area first.
39 	 */
40 	stack_ptr -= z_tls_data_size();
41 	z_tls_copy(stack_ptr);
42 
43 	/* Skip two pointers due to toolchain */
44 	stack_ptr -= sizeof(uintptr_t) * 2;
45 
46 	/*
47 	 * Set thread TLS pointer which is used in
48 	 * context switch to point to TLS area.
49 	 */
50 	new_thread->tls = POINTER_TO_UINT(stack_ptr);
51 
52 	return (z_tls_data_size() + (sizeof(uintptr_t) * 2));
53 }
54