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,