From 371752bce3c3eb72ae0f7c370f38e80ae646e2b4 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 4 Feb 2021 20:05:45 -0800 Subject: [PATCH] kernel: tls: align tdata/tbss sections in stack This lets the linker tell us what kind of alignment is required for both tdata and tbss data when copying them into stack. If they are not aligned as expected by the toolchain, generated code would be accessing incorrect location for thread variables. Fixes #32015 Signed-off-by: Daniel Leung --- include/linker/linker-defs.h | 2 ++ include/linker/thread-local-storage.ld | 2 ++ kernel/include/kernel_tls.h | 7 +++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linker/linker-defs.h b/include/linker/linker-defs.h index be75c318d2..03b8da543e 100644 --- a/include/linker/linker-defs.h +++ b/include/linker/linker-defs.h @@ -309,9 +309,11 @@ extern char z_kobject_data_begin[]; extern char __tdata_start[]; extern char __tdata_end[]; extern char __tdata_size[]; +extern char __tdata_align[]; extern char __tbss_start[]; extern char __tbss_end[]; extern char __tbss_size[]; +extern char __tbss_align[]; extern char __tls_start[]; extern char __tls_end[]; extern char __tls_size[]; diff --git a/include/linker/thread-local-storage.ld b/include/linker/thread-local-storage.ld index 74d1f43c27..a8a072572b 100644 --- a/include/linker/thread-local-storage.ld +++ b/include/linker/thread-local-storage.ld @@ -21,10 +21,12 @@ PROVIDE(__tdata_start = LOADADDR(tdata)); PROVIDE(__tdata_size = SIZEOF(tdata)); PROVIDE(__tdata_end = __tdata_start + __tdata_size); + PROVIDE(__tdata_align = ALIGNOF(tdata)); PROVIDE(__tbss_start = LOADADDR(tbss)); PROVIDE(__tbss_size = SIZEOF(tbss)); PROVIDE(__tbss_end = __tbss_start + __tbss_size); + PROVIDE(__tbss_align = ALIGNOF(tbss)); PROVIDE(__tls_start = __tdata_start); PROVIDE(__tls_end = __tbss_end); diff --git a/kernel/include/kernel_tls.h b/kernel/include/kernel_tls.h index 58dfdb389e..b7d99950d0 100644 --- a/kernel/include/kernel_tls.h +++ b/kernel/include/kernel_tls.h @@ -28,7 +28,10 @@ */ static inline size_t z_tls_data_size(void) { - return (size_t)__tls_size; + size_t tdata_size = ROUND_UP(__tdata_size, __tdata_align); + size_t tbss_size = ROUND_UP(__tbss_size, __tbss_align); + + return tdata_size + tbss_size; } /** @@ -48,7 +51,7 @@ static inline void z_tls_copy(char *dest) memcpy(dest, __tdata_start, tdata_size); /* Clear BSS data (tbss) */ - dest += tdata_size; + dest += ROUND_UP(tdata_size, __tdata_align); memset(dest, 0, tbss_size); }