arm: cortex_m: add support for thread local storage
Adds the necessary bits to initialize TLS in the stack area and sets up CPU registers during context switch. Note that since Cortex-M does not have the thread ID or process ID register needed to store TLS pointer at runtime for toolchain to access thread data, a global variable is used instead. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
778c996831
commit
388725870f
8 changed files with 52 additions and 1 deletions
|
@ -32,7 +32,7 @@ config ARM
|
||||||
# FIXME: current state of the code for all ARM requires this, but
|
# FIXME: current state of the code for all ARM requires this, but
|
||||||
# is really only necessary for Cortex-M with ARM MPU!
|
# is really only necessary for Cortex-M with ARM MPU!
|
||||||
select GEN_PRIV_STACKS
|
select GEN_PRIV_STACKS
|
||||||
select ARCH_HAS_THREAD_LOCAL_STORAGE if ARM64 || CPU_CORTEX_R
|
select ARCH_HAS_THREAD_LOCAL_STORAGE if ARM64 || CPU_CORTEX_R || CPU_CORTEX_M
|
||||||
help
|
help
|
||||||
ARM architecture
|
ARM architecture
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ zephyr_library_sources(
|
||||||
)
|
)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c)
|
zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE __aeabi_read_tp.S)
|
||||||
|
|
||||||
if(CONFIG_CORTEX_M_DWT)
|
if(CONFIG_CORTEX_M_DWT)
|
||||||
if (CONFIG_TIMING_FUNCTIONS)
|
if (CONFIG_TIMING_FUNCTIONS)
|
||||||
|
|
19
arch/arm/core/aarch32/cortex_m/__aeabi_read_tp.S
Normal file
19
arch/arm/core/aarch32/cortex_m/__aeabi_read_tp.S
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <toolchain.h>
|
||||||
|
|
||||||
|
_ASM_FILE_PROLOGUE
|
||||||
|
|
||||||
|
GTEXT(__aeabi_read_tp)
|
||||||
|
|
||||||
|
GDATA(z_arm_tls_ptr)
|
||||||
|
|
||||||
|
SECTION_FUNC(TEXT, __aeabi_read_tp)
|
||||||
|
/* Grab the TLS pointer and store in R0 */
|
||||||
|
ldr r0, =z_arm_tls_ptr
|
||||||
|
ldr r0, [r0]
|
||||||
|
bx lr
|
|
@ -30,6 +30,10 @@ GDATA(_k_neg_eagain)
|
||||||
|
|
||||||
GDATA(_kernel)
|
GDATA(_kernel)
|
||||||
|
|
||||||
|
#if defined(CONFIG_THREAD_LOCAL_STORAGE) && defined(CONFIG_CPU_CORTEX_M)
|
||||||
|
GDATA(z_arm_tls_ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief PendSV exception handler, handling context switches
|
* @brief PendSV exception handler, handling context switches
|
||||||
|
@ -180,6 +184,16 @@ out_fp_endif:
|
||||||
*/
|
*/
|
||||||
mcr 15, 0, r0, cr13, cr0, 3
|
mcr 15, 0, r0, cr13, cr0, 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_CPU_CORTEX_M)
|
||||||
|
/* For Cortex-M, store TLS pointer in a global variable,
|
||||||
|
* as it lacks the process ID or thread ID register
|
||||||
|
* to be used by toolchain to access thread data.
|
||||||
|
*/
|
||||||
|
ldr r4, =z_arm_tls_ptr
|
||||||
|
str r0, [r4]
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Restore previous interrupt disable state (irq_lock key)
|
/* Restore previous interrupt disable state (irq_lock key)
|
||||||
|
|
|
@ -8,8 +8,19 @@
|
||||||
#include <kernel_structs.h>
|
#include <kernel_structs.h>
|
||||||
#include <kernel_internal.h>
|
#include <kernel_internal.h>
|
||||||
#include <kernel_tls.h>
|
#include <kernel_tls.h>
|
||||||
|
#include <app_memory/app_memdomain.h>
|
||||||
#include <sys/util.h>
|
#include <sys/util.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_CORTEX_M
|
||||||
|
/*
|
||||||
|
* Since Cortex-M does not have the thread ID or process ID
|
||||||
|
* register needed to store TLS pointer at runtime for
|
||||||
|
* toolchain to access thread data. Use a global variable
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
K_APP_DMEM(z_libc_partition) uintptr_t z_arm_tls_ptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t arch_tls_stack_setup(struct k_thread *new_thread, char *stack_ptr)
|
size_t arch_tls_stack_setup(struct k_thread *new_thread, char *stack_ptr)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -160,6 +160,7 @@ SECTIONS
|
||||||
|
|
||||||
*(.text)
|
*(.text)
|
||||||
*(".text.*")
|
*(".text.*")
|
||||||
|
*(".TEXT.*")
|
||||||
*(.gnu.linkonce.t.*)
|
*(.gnu.linkonce.t.*)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -200,6 +201,7 @@ SECTIONS
|
||||||
_image_rodata_start = .;
|
_image_rodata_start = .;
|
||||||
|
|
||||||
#include <linker/common-rom.ld>
|
#include <linker/common-rom.ld>
|
||||||
|
#include <linker/thread-local-storage.ld>
|
||||||
|
|
||||||
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
|
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,6 +71,9 @@ extern struct k_mem_partition z_malloc_partition;
|
||||||
defined(CONFIG_NEED_LIBC_MEM_PARTITION)
|
defined(CONFIG_NEED_LIBC_MEM_PARTITION)
|
||||||
/* Minimal libc has no globals. We do put the stack canary global in the
|
/* Minimal libc has no globals. We do put the stack canary global in the
|
||||||
* libc partition since it is not worth placing in a partition of its own.
|
* libc partition since it is not worth placing in a partition of its own.
|
||||||
|
*
|
||||||
|
* Some architectures require a global pointer for thread local storage,
|
||||||
|
* which is placed inside the libc partition.
|
||||||
*/
|
*/
|
||||||
#define Z_LIBC_PARTITION_EXISTS 1
|
#define Z_LIBC_PARTITION_EXISTS 1
|
||||||
|
|
||||||
|
|
|
@ -856,6 +856,7 @@ config TICKLESS_KERNEL
|
||||||
config THREAD_LOCAL_STORAGE
|
config THREAD_LOCAL_STORAGE
|
||||||
bool "Thread Local Storage (TLS)"
|
bool "Thread Local Storage (TLS)"
|
||||||
depends on ARCH_HAS_THREAD_LOCAL_STORAGE
|
depends on ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||||
|
select NEED_LIBC_MEM_PARTITION if (CPU_CORTEX_M && USERSPACE)
|
||||||
help
|
help
|
||||||
This option enables thread local storage (TLS) support in kernel.
|
This option enables thread local storage (TLS) support in kernel.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue