From 88f478108d10f4639e7e73bf4ac09ef44114663c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C3=85berg?= Date: Thu, 11 Feb 2021 16:04:17 +0100 Subject: [PATCH] sparc: write through switched_from in arch_switch() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Write through switched_from in arch_switch() as required by the switch protocol. Also restructure the implementation to better match the template in kernel_arch_interface.h, by removing a wrapper routine and instead use CONTAINER_OF(). Fixes #32197 Signed-off-by: Martin Ã…berg --- arch/sparc/core/switch.S | 23 ++++++++++++++++++----- arch/sparc/include/kernel_arch_func.h | 13 +++++++++++-- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/arch/sparc/core/switch.S b/arch/sparc/core/switch.S index 1fe71edb52d..be9565e8cfe 100644 --- a/arch/sparc/core/switch.S +++ b/arch/sparc/core/switch.S @@ -13,12 +13,16 @@ GTEXT(z_sparc_arch_switch) GTEXT(z_sparc_context_switch) GTEXT(z_thread_entry_wrapper) -/* In this implementation, switch_handle is the thread itself. */ -SECTION_FUNC(TEXT, z_sparc_arch_switch) - ba z_sparc_context_switch - sub %o1, ___thread_t_switch_handle_OFFSET, %o1 - /* + * The routine z_sparc_context_switch() is called from arch_switch(), or from + * the interrupt trap handler in case of preemption. The subtraction to get the + * "old" thread from "switched_from" has already been performed and the "old" + * thread is now in register %o1. We can address old->switch_handle in assembly + * as: [%o1 + ___thread_t_switch_handle_OFFSET]. + * + * The switch_handle is written in z_sparc_context_switch() after the old + * context has been saved. + * * This is a leaf function, so only out registers * can be used without saving their context first. * @@ -101,6 +105,15 @@ SECTION_FUNC(TEXT, z_sparc_context_switch) nop nop + /* + * We have finished saving the "old" context and are also back in the + * register window for which z_sparc_context_switch() was called. + * + * Now write the old thread into switch handle. + * "old->switch_handle = old". + */ + st %o1, [%o1 + ___thread_t_switch_handle_OFFSET] + ldd [%o0 + _thread_offset_to_y], %o4 mov %o4, %y diff --git a/arch/sparc/include/kernel_arch_func.h b/arch/sparc/include/kernel_arch_func.h index 889048e463a..41f48ccc44a 100644 --- a/arch/sparc/include/kernel_arch_func.h +++ b/arch/sparc/include/kernel_arch_func.h @@ -26,11 +26,20 @@ static ALWAYS_INLINE void arch_kernel_init(void) { } -void z_sparc_arch_switch(void *switch_to, void **switched_from); +void z_sparc_context_switch(struct k_thread *newt, struct k_thread *oldt); +/* + * In this implementation, the thread->switch_handle is the thread itself, so + * the parameter "switched_from" is assumed to be the address of + * thread->switch_handle. + */ static inline void arch_switch(void *switch_to, void **switched_from) { - z_sparc_arch_switch(switch_to, switched_from); + struct k_thread *newt = switch_to; + struct k_thread *oldt = CONTAINER_OF(switched_from, struct k_thread, + switch_handle); + + z_sparc_context_switch(newt, oldt); } FUNC_NORETURN void z_sparc_fatal_error(unsigned int reason,