From 09b8387df4257e4943f9f06491d92fae8c5798cd Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Fri, 20 Nov 2020 10:58:37 +0100 Subject: [PATCH] cpu/native: align stack in thread_stack_init() Unaligned accesses on x86(_64) are allowed, but slow. However, some host systems might not be that forgiving. Aligning the stack to sizeof(uintptr_t) should be a pretty safe safety measure. And with this done, all casts of the stack pointer that increase alignment requirements are now intermediately casted to `uintptr_t` to silence warnings from -Wcast-align - after all the stacks are now manually aligned. --- cpu/native/irq_cpu.c | 8 ++++++-- cpu/native/native_cpu.c | 33 ++++++++++++++++++++++++++++----- cpu/native/syscalls.c | 4 +++- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq_cpu.c index afa5feb5f8..aa31e8e1c3 100644 --- a/cpu/native/irq_cpu.c +++ b/cpu/native/irq_cpu.c @@ -100,7 +100,9 @@ void print_sigmasks(void) ucontext_t *p; printf("%s:\n", sched_threads[i]->name); //print_thread_sigmask(sched_threads[i]->sp); - p = (ucontext_t *)(sched_threads[i]->stack_start); + /* Use intermediate cast to uintptr_t to silence -Wcast-align. + * stacks are manually word aligned in thread_static_init() */ + p = (ucontext_t *)(uintptr_t)(sched_threads[i]->stack_start); print_thread_sigmask(p); puts(""); } @@ -335,7 +337,9 @@ void native_isr_entry(int sig, siginfo_t *info, void *context) native_isr_context.uc_stack.ss_size = sizeof(__isr_stack); native_isr_context.uc_stack.ss_flags = 0; makecontext(&native_isr_context, native_irq_handler, 0); - _native_cur_ctx = (ucontext_t *)thread_get_active()->sp; + /* Use intermediate cast to uintptr_t to silence -Wcast-align. + * stacks are manually word aligned in thread_stack_init() */ + _native_cur_ctx = (ucontext_t *)(uintptr_t)thread_get_active()->sp; DEBUG("\n\n\t\tnative_isr_entry: return to _native_sig_leave_tramp\n\n"); /* disable interrupts in context */ diff --git a/cpu/native/native_cpu.c b/cpu/native/native_cpu.c index e4c02fd52a..cdbbcc629e 100644 --- a/cpu/native/native_cpu.c +++ b/cpu/native/native_cpu.c @@ -102,12 +102,27 @@ int thread_isr_stack_usage(void) return -1; } +static inline void *align_stack(void *stack_start, int *stacksize) +{ + const size_t alignment = sizeof(uintptr_t); + const uintptr_t align_mask = alignment - 1; + uintptr_t start = (uintptr_t)stack_start; + size_t unalignment = (start & align_mask) + ? (alignment - (start & align_mask)) : 0; + start += unalignment; + *stacksize -= unalignment; + *stacksize &= ~align_mask; + return (void *)start; +} + char *thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_start, int stacksize) { char *stk; ucontext_t *p; - VALGRIND_STACK_REGISTER(stack_start, (char *) stack_start + stacksize); + stack_start = align_stack(stack_start, &stacksize); + + VALGRIND_STACK_REGISTER(stack_start, (char *)stack_start + stacksize); VALGRIND_DEBUG("VALGRIND_STACK_REGISTER(%p, %p)\n", stack_start, (void*)((int)stack_start + stacksize)); @@ -115,7 +130,9 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_sta stk = stack_start; - p = (ucontext_t *)(stk + (stacksize - sizeof(ucontext_t))); + /* Use intermediate cast to uintptr_t to silence -Wcast-align. The stack + * is aligned to word size above. */ + p = (ucontext_t *)(uintptr_t)(stk + (stacksize - sizeof(ucontext_t))); stacksize -= sizeof(ucontext_t); if (getcontext(p) == -1) { @@ -146,7 +163,9 @@ void isr_cpu_switch_context_exit(void) } DEBUG("isr_cpu_switch_context_exit: calling setcontext(%" PRIkernel_pid ")\n\n", thread_getpid()); - ctx = (ucontext_t *)(thread_get_active()->sp); + /* Use intermediate cast to uintptr_t to silence -Wcast-align. + * stacks are manually word aligned in thread_static_init() */ + ctx = (ucontext_t *)(uintptr_t)(thread_get_active()->sp); native_interrupts_enabled = 1; _native_mod_ctx_leave_sigh(ctx); @@ -194,7 +213,9 @@ void isr_thread_yield(void) } sched_run(); - ucontext_t *ctx = (ucontext_t *)(thread_get_active()->sp); + /* Use intermediate cast to uintptr_t to silence -Wcast-align. + * stacks are manually word aligned in thread_static_init() */ + ucontext_t *ctx = (ucontext_t *)(uintptr_t)(thread_get_active()->sp); DEBUG("isr_thread_yield: switching to(%" PRIkernel_pid ")\n\n", thread_getpid()); @@ -211,7 +232,9 @@ void thread_yield_higher(void) sched_context_switch_request = 1; if (_native_in_isr == 0 && native_interrupts_enabled) { - ucontext_t *ctx = (ucontext_t *)(thread_get_active()->sp); + /* Use intermediate cast to uintptr_t to silence -Wcast-align. + * stacks are manually word aligned in thread_static_init() */ + ucontext_t *ctx = (ucontext_t *)(uintptr_t)(thread_get_active()->sp); _native_in_isr = 1; irq_disable(); native_isr_context.uc_stack.ss_sp = __isr_stack; diff --git a/cpu/native/syscalls.c b/cpu/native/syscalls.c index 620392bb8c..3cee6cb073 100644 --- a/cpu/native/syscalls.c +++ b/cpu/native/syscalls.c @@ -130,7 +130,9 @@ void _native_syscall_leave(void) ) { _native_in_isr = 1; - _native_cur_ctx = (ucontext_t *)thread_get_active()->sp; + /* Use intermediate cast to uintptr_t to silence -Wcast-align. + * stacks are manually word aligned in thread_static_init() */ + _native_cur_ctx = (ucontext_t *)(uintptr_t)thread_get_active()->sp; native_isr_context.uc_stack.ss_sp = __isr_stack; native_isr_context.uc_stack.ss_size = SIGSTKSZ; native_isr_context.uc_stack.ss_flags = 0;