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:
Daniel Leung 2020-09-29 12:16:01 -07:00 committed by Andrew Boie
commit 388725870f
8 changed files with 52 additions and 1 deletions

View file

@ -32,7 +32,7 @@ config ARM
# FIXME: current state of the code for all ARM requires this, but
# is really only necessary for Cortex-M with ARM MPU!
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
ARM architecture

View file

@ -14,6 +14,7 @@ zephyr_library_sources(
)
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_TIMING_FUNCTIONS)

View 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

View file

@ -30,6 +30,10 @@ GDATA(_k_neg_eagain)
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
@ -180,6 +184,16 @@ out_fp_endif:
*/
mcr 15, 0, r0, cr13, cr0, 3
#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
/* Restore previous interrupt disable state (irq_lock key)

View file

@ -8,8 +8,19 @@
#include <kernel_structs.h>
#include <kernel_internal.h>
#include <kernel_tls.h>
#include <app_memory/app_memdomain.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)
{
/*

View file

@ -160,6 +160,7 @@ SECTIONS
*(.text)
*(".text.*")
*(".TEXT.*")
*(.gnu.linkonce.t.*)
/*
@ -200,6 +201,7 @@ SECTIONS
_image_rodata_start = .;
#include <linker/common-rom.ld>
#include <linker/thread-local-storage.ld>
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
{

View file

@ -71,6 +71,9 @@ extern struct k_mem_partition z_malloc_partition;
defined(CONFIG_NEED_LIBC_MEM_PARTITION)
/* 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.
*
* Some architectures require a global pointer for thread local storage,
* which is placed inside the libc partition.
*/
#define Z_LIBC_PARTITION_EXISTS 1

View file

@ -856,6 +856,7 @@ config TICKLESS_KERNEL
config THREAD_LOCAL_STORAGE
bool "Thread Local Storage (TLS)"
depends on ARCH_HAS_THREAD_LOCAL_STORAGE
select NEED_LIBC_MEM_PARTITION if (CPU_CORTEX_M && USERSPACE)
help
This option enables thread local storage (TLS) support in kernel.