aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64/kernel/entry.S
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-09-15 19:21:14 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2022-09-15 19:46:07 +0300
commita717296a2036cede5fccfff544513043a984d614 (patch)
tree68f75a23adc298628fb9cab41fd47402a99dd19d /arch/riscv64/kernel/entry.S
parent619725a5f2f5272f9cbb547ed95c87312c2765a9 (diff)
downloadkmi-a717296a2036cede5fccfff544513043a984d614.tar.gz
kmi-a717296a2036cede5fccfff544513043a984d614.zip
change syscalls to take 5 params and return 6
+ In total, a syscall is built up of 6 values, with the first being the syscall number. Symmetrically, the first value is now a status and the following five values return "values". This allows us to cram in more info into the ipc_* functions. The performance difference is absolutely minimal, at least from my testing in qemu.
Diffstat (limited to 'arch/riscv64/kernel/entry.S')
-rw-r--r--arch/riscv64/kernel/entry.S35
1 files changed, 24 insertions, 11 deletions
diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S
index 1bd6046..8ff642a 100644
--- a/arch/riscv64/kernel/entry.S
+++ b/arch/riscv64/kernel/entry.S
@@ -86,25 +86,42 @@ handle_syscall:
/* add 4 (size of ecall) to EPC to avoid running the same instruction
* twice */
csrr s0, CSR_SEPC
- addi s0, s0, 4
+ addi s0, s0, 4
csrw CSR_SEPC, s0
+ /* allocate space for sys_ret structure on stack and shift argument
+ * registers down one to make room for the pointer to this structure */
+ addi sp, sp, -sizeof_sys_ret
+ mv a6, a5
+ mv a5, a4
+ mv a4, a3
+ mv a3, a2
+ mv a2, a1
+ mv a1, a0
+ mv a0, sp
jal syscall_dispatch
+ /* move structure from stack into registers. */
+ lr a0, offsetof_s(sp)
+ lr a1, offsetof_ar0(sp)
+ lr a2, offsetof_ar1(sp)
+ lr a3, offsetof_ar2(sp)
+ lr a4, offsetof_ar3(sp)
+ lr a5, offsetof_ar4(sp)
+ addi sp, sp, sizeof_sys_ret
/* if we had a thread switch, load kernel stack of current thread and
* restore its context */
- /* TODO: is a whole function call necessary? */
- mv s0, a0
- mv s1, a1
/* get associated kernel stack */
mv sp, tp
addi sp, sp, -sizeof_registers
/* restore system call result */
- mv a0, s0
- mv a1, s1
j restore_noreturn
restore_all:
lr a0, offsetof_a0(sp)
lr a1, offsetof_a1(sp)
+ lr a2, offsetof_a2(sp)
+ lr a3, offsetof_a3(sp)
+ lr a4, offsetof_a4(sp)
+ lr a5, offsetof_a5(sp)
restore_noreturn:
/* restore registers besides possible return value, assume instruction
@@ -117,11 +134,7 @@ restore_noreturn:
lr t0, offsetof_t0(sp)
lr t1, offsetof_t1(sp)
lr t2, offsetof_t2(sp)
- /* a0 and a1 should not be restored when coming from a syscall */
- lr a2, offsetof_a2(sp)
- lr a3, offsetof_a3(sp)
- lr a4, offsetof_a4(sp)
- lr a5, offsetof_a5(sp)
+ /* a0 - a5 should not be restored when coming from a syscall */
lr a6, offsetof_a6(sp)
lr s0, offsetof_s0(sp)
lr s1, offsetof_s1(sp)