aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64/kernel/entry.S
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-05-09 00:12:05 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2022-05-09 00:12:05 +0300
commit42a1e087ce99f07b48aaea5552f8e1ce5219d228 (patch)
tree086ac77af67a46ff4ba420c4562cbf6a57d09ab0 /arch/riscv64/kernel/entry.S
parent658f21dd60bb930c5226b611bbe8cb95713b3f76 (diff)
downloadkmi-42a1e087ce99f07b48aaea5552f8e1ce5219d228.tar.gz
kmi-42a1e087ce99f07b48aaea5552f8e1ce5219d228.zip
improve uapi
Diffstat (limited to 'arch/riscv64/kernel/entry.S')
-rw-r--r--arch/riscv64/kernel/entry.S139
1 files changed, 139 insertions, 0 deletions
diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S
new file mode 100644
index 0000000..0ff1a69
--- /dev/null
+++ b/arch/riscv64/kernel/entry.S
@@ -0,0 +1,139 @@
+#include <gen/asm-offsets.h>
+#include <csr.h>
+
+#if __riscv_xlen == 64
+#define sr sd
+#define lr ld
+#else
+#define sr sw
+#define lr lw
+#endif
+
+/* very much based on linux, but why change it if works, eh? */
+.section .text
+.align 4
+.global handle_irq
+handle_irq:
+ csrrw tp, CSR_SSCRATCH, tp
+ bnez tp, _save_context
+ /* the exception came from the kernel, should probably handle but for
+ * now just spin in place */
+ 1: j 1b
+_save_context:
+ /* store user stack pointer and replace it with kernel stack */
+ addi tp, tp,-sizeof_registers
+ sr sp, offsetof_sp(tp)
+ mv sp, tp
+
+ /* set scratch to 0 and move thread pointer back */
+ csrrw tp, CSR_SSCRATCH, x0
+
+ /* save registers */
+ sr ra, offsetof_ra(sp)
+ sr gp, offsetof_gp(sp)
+ sr tp, offsetof_tp(sp)
+ sr t0, offsetof_t0(sp)
+ sr t1, offsetof_t1(sp)
+ sr t2, offsetof_t2(sp)
+ sr s0, offsetof_s0(sp)
+ sr a0, offsetof_a0(sp)
+ sr a1, offsetof_a1(sp)
+ sr a2, offsetof_a2(sp)
+ sr a3, offsetof_a3(sp)
+ sr a4, offsetof_a4(sp)
+ sr a5, offsetof_a5(sp)
+ sr a6, offsetof_a6(sp)
+ sr a7, offsetof_a7(sp)
+ sr s1, offsetof_s1(sp)
+ sr s2, offsetof_s2(sp)
+ sr s3, offsetof_s3(sp)
+ sr s4, offsetof_s4(sp)
+ sr s5, offsetof_s5(sp)
+ sr s6, offsetof_s6(sp)
+ sr s7, offsetof_s7(sp)
+ sr s8, offsetof_s8(sp)
+ sr s9, offsetof_s9(sp)
+ sr s10,offsetof_s10(sp)
+ sr s11,offsetof_s11(sp)
+ sr t3, offsetof_t3(sp)
+ sr t4, offsetof_t4(sp)
+ sr t5, offsetof_t5(sp)
+ sr t6, offsetof_t6(sp)
+
+ /* load supervisor cause */
+ csrr s4, CSR_SCAUSE
+ /* interrupts fall through, exceptions jump */
+ bge s4, zero, handle_exception
+ /* TODO: handle interrupts */
+ j restore_all
+
+handle_exception:
+ li t0, EXC_SYSCALL
+ /* system exceptions fall through, syscalls jump */
+ beq s4, t0, handle_syscall
+ j restore_all
+
+handle_syscall:
+ /* TODO: CSR_EPC should be moved forward one instruction when dealing
+ * with syscalls */
+ jal syscall_dispatch
+ /* 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 current tcb */
+ call cur_tcb
+ mv tp, a0
+ /* 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)
+
+restore_noreturn:
+ /* restore registers besides possible return value, assume instruction
+ * to return to has already been set (CSR_EPC) */
+ csrw CSR_SSCRATCH, tp
+
+ lr ra, offsetof_ra(sp)
+ lr gp, offsetof_gp(sp)
+ lr tp, offsetof_tp(sp)
+ 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)
+ lr a6, offsetof_a6(sp)
+ lr s0, offsetof_s0(sp)
+ lr s1, offsetof_s1(sp)
+ lr s2, offsetof_s2(sp)
+ lr s3, offsetof_s3(sp)
+ lr s4, offsetof_s4(sp)
+ lr s5, offsetof_s4(sp)
+ lr s6, offsetof_s6(sp)
+ lr s7, offsetof_s7(sp)
+ lr s8, offsetof_s8(sp)
+ lr s9, offsetof_s9(sp)
+ lr s10,offsetof_s10(sp)
+ lr s11,offsetof_s11(sp)
+ lr a7, offsetof_a7(sp)
+ lr t3, offsetof_t3(sp)
+ lr t4, offsetof_t4(sp)
+ lr t5, offsetof_t5(sp)
+ lr t6, offsetof_t6(sp)
+
+ /* restore stack pointer */
+ lr sp, offsetof_sp(sp)
+
+ /* assume supervisor for now */
+ sret