From 388725870fbaa82328d24779042551b19651b329 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Tue, 29 Sep 2020 12:16:01 -0700 Subject: [PATCH] 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 --- arch/Kconfig | 2 +- arch/arm/core/aarch32/cortex_m/CMakeLists.txt | 1 + .../core/aarch32/cortex_m/__aeabi_read_tp.S | 19 +++++++++++++++++++ arch/arm/core/aarch32/swap_helper.S | 14 ++++++++++++++ arch/arm/core/common/tls.c | 11 +++++++++++ .../arm/aarch32/cortex_m/scripts/linker.ld | 2 ++ include/sys/libc-hooks.h | 3 +++ kernel/Kconfig | 1 + 8 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 arch/arm/core/aarch32/cortex_m/__aeabi_read_tp.S diff --git a/arch/Kconfig b/arch/Kconfig index c4c31a59232..133e14656fd 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -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 diff --git a/arch/arm/core/aarch32/cortex_m/CMakeLists.txt b/arch/arm/core/aarch32/cortex_m/CMakeLists.txt index bdbce1efb59..42c80368c79 100644 --- a/arch/arm/core/aarch32/cortex_m/CMakeLists.txt +++ b/arch/arm/core/aarch32/cortex_m/CMakeLists.txt @@ -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) diff --git a/arch/arm/core/aarch32/cortex_m/__aeabi_read_tp.S b/arch/arm/core/aarch32/cortex_m/__aeabi_read_tp.S new file mode 100644 index 00000000000..bb13290d38c --- /dev/null +++ b/arch/arm/core/aarch32/cortex_m/__aeabi_read_tp.S @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +_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 diff --git a/arch/arm/core/aarch32/swap_helper.S b/arch/arm/core/aarch32/swap_helper.S index d9bd3fdf606..e72af94f31b 100644 --- a/arch/arm/core/aarch32/swap_helper.S +++ b/arch/arm/core/aarch32/swap_helper.S @@ -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) diff --git a/arch/arm/core/common/tls.c b/arch/arm/core/common/tls.c index 1eb7213d44c..37baeeedef1 100644 --- a/arch/arm/core/common/tls.c +++ b/arch/arm/core/common/tls.c @@ -8,8 +8,19 @@ #include #include #include +#include #include +#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) { /* diff --git a/include/arch/arm/aarch32/cortex_m/scripts/linker.ld b/include/arch/arm/aarch32/cortex_m/scripts/linker.ld index 533aca09409..853013b8f1b 100644 --- a/include/arch/arm/aarch32/cortex_m/scripts/linker.ld +++ b/include/arch/arm/aarch32/cortex_m/scripts/linker.ld @@ -160,6 +160,7 @@ SECTIONS *(.text) *(".text.*") + *(".TEXT.*") *(.gnu.linkonce.t.*) /* @@ -200,6 +201,7 @@ SECTIONS _image_rodata_start = .; #include +#include SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) { diff --git a/include/sys/libc-hooks.h b/include/sys/libc-hooks.h index 0152711b401..3122fe06db3 100644 --- a/include/sys/libc-hooks.h +++ b/include/sys/libc-hooks.h @@ -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 diff --git a/kernel/Kconfig b/kernel/Kconfig index b394f8ab951..18441ada35f 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -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.