diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-04-29 17:38:41 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2022-04-29 17:38:41 +0300 |
| commit | 9273c16434316a8ab60dc78ee65a03e68031203a (patch) | |
| tree | 41754de4b7c459fc07e20189948c94a0e2cab966 /arch/riscv64/kernel/head.S | |
| parent | 105f3d0dab75f669d1fc404c06b73289b343591c (diff) | |
| download | kmi-9273c16434316a8ab60dc78ee65a03e68031203a.tar.gz kmi-9273c16434316a8ab60dc78ee65a03e68031203a.zip | |
continue building base for irq handling
Diffstat (limited to 'arch/riscv64/kernel/head.S')
| -rw-r--r-- | arch/riscv64/kernel/head.S | 136 |
1 files changed, 99 insertions, 37 deletions
diff --git a/arch/riscv64/kernel/head.S b/arch/riscv64/kernel/head.S index d2a1927..cef74ba 100644 --- a/arch/riscv64/kernel/head.S +++ b/arch/riscv64/kernel/head.S @@ -1,3 +1,4 @@ +#include <gen/asm-offsets.h> #include <csr.h> #if __riscv_xlen == 64 @@ -8,28 +9,57 @@ #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: - addi sp,sp,-144 - sr ra,136(sp) - sr t0,128(sp) - sr t1,120(sp) - sr t2,112(sp) - sr s0,104(sp) - sr a0,96(sp) - sr a1,88(sp) - sr a2,80(sp) - sr a3,72(sp) - sr a4,64(sp) - sr a5,56(sp) - sr a6,48(sp) - sr a7,40(sp) - sr t3,32(sp) - sr t4,24(sp) - sr t5,16(sp) - sr t6,8(sp) - addi s0,sp,144 + 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 */ @@ -44,29 +74,61 @@ handle_exception: 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 + /* get current tcb */ + call cur_tcb + mv tp, a0 + /* get associated kernel stack */ + mv sp, tp + addi sp, sp, -sizeof_registers j restore_noreturn restore_all: - lr a0,96(sp) + lr s0, offsetof_s0(sp) restore_noreturn: - lr ra,136(sp) - lr t0,128(sp) - lr t1,120(sp) - lr t2,112(sp) - lr s0,104(sp) - lr a1,88(sp) - lr a2,80(sp) - lr a3,72(sp) - lr a4,64(sp) - lr a5,56(sp) - lr a6,48(sp) - lr a7,40(sp) - lr t3,32(sp) - lr t4,24(sp) - lr t5,16(sp) - lr t6,8(sp) - addi sp,sp,144 + /* 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) + 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) + lr a6, offsetof_a6(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 |
