Adds the necessary bits to initialize TLS in the stack area and sets up CPU registers during context switch. Note that this does not enable TLS for all Xtensa SoC. This is because Xtensa SoCs are highly configurable so that each SoC can be considered a whole architecture. So TLS needs to be enabled on the SoC level, instead of at the arch level. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
48 lines
1.2 KiB
C
48 lines
1.2 KiB
C
/*
|
|
* Copyright (c) 2020 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <kernel.h>
|
|
#include <kernel_structs.h>
|
|
#include <kernel_internal.h>
|
|
#include <kernel_tls.h>
|
|
#include <app_memory/app_memdomain.h>
|
|
#include <sys/util.h>
|
|
|
|
#if XCHAL_HAVE_THREADPTR == 0
|
|
#error SoC does not support THREADPTR for thread local storage.
|
|
#endif
|
|
|
|
size_t arch_tls_stack_setup(struct k_thread *new_thread, char *stack_ptr)
|
|
{
|
|
/*
|
|
* TLS area has some data fields following by
|
|
* thread data and bss. These fields are supposed to be
|
|
* used by toolchain and OS TLS code to aid in locating
|
|
* the TLS data/bss. Zephyr currently has no use for
|
|
* this so we can simply skip these. However, since GCC
|
|
* is generating code assuming these fields are there,
|
|
* we simply skip them when setting the TLS pointer.
|
|
*/
|
|
|
|
/*
|
|
* Since we are populating things backwards,
|
|
* setup the TLS data/bss area first.
|
|
*/
|
|
stack_ptr -= z_tls_data_size();
|
|
z_tls_copy(stack_ptr);
|
|
|
|
/* Skip two pointers due to toolchain */
|
|
stack_ptr -= sizeof(uintptr_t) * 2;
|
|
|
|
/*
|
|
* Set thread TLS pointer which is used in
|
|
* context switch to point to TLS area.
|
|
*/
|
|
new_thread->tls = POINTER_TO_UINT(stack_ptr);
|
|
|
|
return (z_tls_data_size() + (sizeof(uintptr_t) * 2));
|
|
}
|