arch/riscv: Use arch_switch() for context swap
Enable `arch_switch()` as preparation for SMP support. This patch doesn't try to keep support for old style context swap - only switch based swap is supported, to keep things simple. A fair amount of refactoring was done in this patch, specially regarding the code that decides what to do about the ISR. In RISC-V, ECALL instructions are used to signalize several events, such as user space system calls, forced syscall, IRQ offload, return from syscall and context switch. All those handled by the ISR - which also handles interrupts. After refactor, this "dispatching" step is done at the beginning of ISR (just after saving generic registers). As with other platforms, the thread object itself is used as the thread "switch handle" for the context swap. Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
This commit is contained in:
parent
8686ab5472
commit
be28de692c
6 changed files with 246 additions and 202 deletions
50
arch/riscv/core/switch.S
Normal file
50
arch/riscv/core/switch.S
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <offsets_short.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
/* exports */
|
||||
GTEXT(arch_switch)
|
||||
GTEXT(z_thread_entry_wrapper)
|
||||
|
||||
/* Use ABI name of registers for the sake of simplicity */
|
||||
|
||||
/*
|
||||
* void arch_switch(void *switch_to, void **switched_from);
|
||||
*
|
||||
* Always called with interrupts locked
|
||||
*
|
||||
* a0 = (struct k_thread *) switch_to
|
||||
* a1 = (struct k_thread **) address of output thread switch_handle field
|
||||
*/
|
||||
SECTION_FUNC(exception.other, arch_switch)
|
||||
|
||||
/* Make a system call to perform context switch */
|
||||
ecall
|
||||
|
||||
/* Return */
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* void z_thread_entry_wrapper(k_thread_entry_t, void *, void *, void *)
|
||||
*/
|
||||
SECTION_FUNC(TEXT, z_thread_entry_wrapper)
|
||||
/*
|
||||
* z_thread_entry_wrapper is called for every new thread upon the return
|
||||
* of arch_switch or ISR. Its address, as well as its input function
|
||||
* arguments thread_entry_t, void *, void *, void * are restored from
|
||||
* the thread stack (initialized via function _thread).
|
||||
* In this case, thread_entry_t, * void *, void * and void * are stored
|
||||
* in registers a0, a1, a2 and a3. These registers are used as arguments
|
||||
* to function z_thread_entry. Hence, just call z_thread_entry with
|
||||
* return address set to 0 to indicate a non-returning function call.
|
||||
*/
|
||||
|
||||
jal x0, z_thread_entry
|
Loading…
Add table
Add a link
Reference in a new issue