diff --git a/CMakeLists.txt b/CMakeLists.txt index ea954bd713..9c13719792 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -291,6 +291,11 @@ zephyr_cc_option(-fno-pie) zephyr_cc_option(-fno-pic) zephyr_cc_option(-fno-strict-overflow) +if(CONFIG_THREAD_LOCAL_STORAGE) +# Only support local exec TLS model at this point. +zephyr_cc_option(-ftls-model=local-exec) +endif() + if(CONFIG_OVERRIDE_FRAME_POINTER_DEFAULT) if(CONFIG_OMIT_FRAME_POINTER) zephyr_cc_option(-fomit-frame-pointer) diff --git a/include/kernel.h b/include/kernel.h index 56fa75c729..9f07e6185a 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -365,6 +365,11 @@ struct k_thread { /** resource pool */ struct k_mem_pool *resource_pool; +#if defined(CONFIG_THREAD_LOCAL_STORAGE) + /* Pointer to arch-specific TLS area */ + uintptr_t tls; +#endif /* CONFIG_THREAD_LOCAL_STORAGE */ + /** arch-specifics: must always be at the end */ struct _thread_arch arch; }; diff --git a/kernel/include/kernel_arch_interface.h b/kernel/include/kernel_arch_interface.h index 58a8374610..42880ce82b 100644 --- a/kernel/include/kernel_arch_interface.h +++ b/kernel/include/kernel_arch_interface.h @@ -349,6 +349,26 @@ uint16_t arch_coredump_tgt_code_get(void); /** @} */ +/** + * @defgroup arch-tls Architecture-specific Thread Local Storage APIs + * @ingroup arch-interface + * @{ + */ + +/** + * @brief Setup Architecture-specific TLS area in stack + * + * This sets up the stack area for thread local storage. + * The structure inside in area is architecture specific. + * + * @param new_thread New thread object + * @param stack_ptr Stack pointer + * @return Number of bytes taken by the TLS area + */ +size_t arch_tls_stack_setup(struct k_thread *new_thread, char *stack_ptr); + +/** @} */ + /* Include arch-specific inline function implementation */ #include diff --git a/kernel/include/kernel_offsets.h b/kernel/include/kernel_offsets.h index 1978d04dad..aa07eb2650 100644 --- a/kernel/include/kernel_offsets.h +++ b/kernel/include/kernel_offsets.h @@ -77,6 +77,10 @@ GEN_OFFSET_SYM(_thread_t, next_thread); GEN_OFFSET_SYM(_thread_t, custom_data); #endif +#ifdef CONFIG_THREAD_LOCAL_STORAGE +GEN_OFFSET_SYM(_thread_t, tls); +#endif + GEN_ABSOLUTE_SYM(K_THREAD_SIZEOF, sizeof(struct k_thread)); /* size of the device structure. Used by linker scripts */ diff --git a/kernel/include/kernel_tls.h b/kernel/include/kernel_tls.h new file mode 100644 index 0000000000..58dfdb389e --- /dev/null +++ b/kernel/include/kernel_tls.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Kernel Thread Local Storage APIs. + * + * Kernel APIs related to thread local storage. + */ + +#ifndef ZEPHYR_KERNEL_INCLUDE_KERNEL_TLS_H_ +#define ZEPHYR_KERNEL_INCLUDE_KERNEL_TLS_H_ + +#include + +/** + * @brief Return the total size of TLS data/bss areas + * + * This returns the total size of thread local storage (TLS) + * data and bss areas as defined in the linker script. + * Note that this does not include any architecture specific + * bits required for proper functionality of TLS. + * + * @return Total size of TLS data/bss areas + */ +static inline size_t z_tls_data_size(void) +{ + return (size_t)__tls_size; +} + +/** + * @brief Copy the TLS data/bss areas into destination + * + * This copies the TLS data into destination and clear the area + * of TLS bss size after the data section. + * + * @param dest Pointer to destination + */ +static inline void z_tls_copy(char *dest) +{ + size_t tdata_size = (size_t)__tdata_size; + size_t tbss_size = (size_t)__tbss_size; + + /* Copy initialized data (tdata) */ + memcpy(dest, __tdata_start, tdata_size); + + /* Clear BSS data (tbss) */ + dest += tdata_size; + memset(dest, 0, tbss_size); +} + +#endif /* ZEPHYR_KERNEL_INCLUDE_KERNEL_TLS_H_ */ diff --git a/kernel/include/offsets_short.h b/kernel/include/offsets_short.h index 0e36f7ebba..4e4125760f 100644 --- a/kernel/include/offsets_short.h +++ b/kernel/include/offsets_short.h @@ -44,6 +44,11 @@ #define _thread_offset_to_callee_saved \ (___thread_t_callee_saved_OFFSET) +#ifdef CONFIG_THREAD_LOCAL_STORAGE +#define _thread_offset_to_tls \ + (___thread_t_tls_OFFSET) +#endif /* CONFIG_THREAD_LOCAL_STORAGE */ + /* base */ #define _thread_offset_to_thread_state \ diff --git a/kernel/thread.c b/kernel/thread.c index 260ecabc74..16de7a8f93 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -492,6 +492,9 @@ static char *setup_thread_stack(struct k_thread *new_thread, */ *((uint32_t *)stack_buf_start) = STACK_SENTINEL; #endif /* CONFIG_STACK_SENTINEL */ +#ifdef CONFIG_THREAD_LOCAL_STORAGE + delta += arch_tls_stack_setup(new_thread, (stack_ptr - delta)); +#endif /* CONFIG_THREAD_LOCAL_STORAGE */ #ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA size_t tls_size = sizeof(struct _thread_userspace_local_data);