From 9273c16434316a8ab60dc78ee65a03e68031203a Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 29 Apr 2022 17:38:41 +0300 Subject: continue building base for irq handling --- arch/riscv64/conf/init | Bin 1096 -> 1096 bytes arch/riscv64/conf/initrd | Bin 1536 -> 1536 bytes arch/riscv64/conf/s.S | 10 +-- arch/riscv64/gen/asm-offsets.c | 44 +++++++++++++ arch/riscv64/gen/source.mk | 8 +++ arch/riscv64/include/regs.h | 9 +++ arch/riscv64/include/vmem.h | 22 ++++--- arch/riscv64/kernel/head.S | 136 ++++++++++++++++++++++++++++++----------- arch/riscv64/kernel/irq.c | 2 + arch/riscv64/kernel/proc.c | 17 ++++++ arch/riscv64/source.mk | 14 +++-- 11 files changed, 207 insertions(+), 55 deletions(-) create mode 100644 arch/riscv64/gen/asm-offsets.c create mode 100644 arch/riscv64/gen/source.mk create mode 100644 arch/riscv64/include/regs.h (limited to 'arch') diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init index c415457..0a67c41 100755 Binary files a/arch/riscv64/conf/init and b/arch/riscv64/conf/init differ diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd index 6d2ac10..6021c8f 100644 Binary files a/arch/riscv64/conf/initrd and b/arch/riscv64/conf/initrd differ diff --git a/arch/riscv64/conf/s.S b/arch/riscv64/conf/s.S index 1344f69..97c66ff 100644 --- a/arch/riscv64/conf/s.S +++ b/arch/riscv64/conf/s.S @@ -1,9 +1,9 @@ .text .global _start _start: -li a0, 1 -li a1, 2 -li a2, 3 -li a3, 4 -li a4, 5 +li a0, 0 /* 0 should be NOOP */ +li a1, 1 +li a2, 2 +li a3, 3 +li a4, 4 ecall diff --git a/arch/riscv64/gen/asm-offsets.c b/arch/riscv64/gen/asm-offsets.c new file mode 100644 index 0000000..d78e0ec --- /dev/null +++ b/arch/riscv64/gen/asm-offsets.c @@ -0,0 +1,44 @@ +#include +#include + +/* largely based on linux */ +#define DEFINE(sym, val) \ + __asm__ volatile("\n-> " #sym " %0 " #val "\n" ::"i"(val)) +#define OFFSETOF(m, s) DEFINE(offsetof_##m, offsetof(s, m)) +#define SIZEOF(n, s) DEFINE(sizeof_##n, sizeof(s)) + +void asm_offsets() +{ + OFFSETOF(ra, struct riscv_regs); + OFFSETOF(sp, struct riscv_regs); + OFFSETOF(tp, struct riscv_regs); + OFFSETOF(gp, struct riscv_regs); + OFFSETOF(t0, struct riscv_regs); + OFFSETOF(t1, struct riscv_regs); + OFFSETOF(t2, struct riscv_regs); + OFFSETOF(s0, struct riscv_regs); + OFFSETOF(s1, struct riscv_regs); + OFFSETOF(a0, struct riscv_regs); + OFFSETOF(a1, struct riscv_regs); + OFFSETOF(a2, struct riscv_regs); + OFFSETOF(a3, struct riscv_regs); + OFFSETOF(a4, struct riscv_regs); + OFFSETOF(a5, struct riscv_regs); + OFFSETOF(a6, struct riscv_regs); + OFFSETOF(a7, struct riscv_regs); + OFFSETOF(s2, struct riscv_regs); + OFFSETOF(s3, struct riscv_regs); + OFFSETOF(s4, struct riscv_regs); + OFFSETOF(s5, struct riscv_regs); + OFFSETOF(s6, struct riscv_regs); + OFFSETOF(s7, struct riscv_regs); + OFFSETOF(s8, struct riscv_regs); + OFFSETOF(s9, struct riscv_regs); + OFFSETOF(s10, struct riscv_regs); + OFFSETOF(s11, struct riscv_regs); + OFFSETOF(t3, struct riscv_regs); + OFFSETOF(t4, struct riscv_regs); + OFFSETOF(t5, struct riscv_regs); + OFFSETOF(t6, struct riscv_regs); + SIZEOF(registers, struct riscv_regs); +} diff --git a/arch/riscv64/gen/source.mk b/arch/riscv64/gen/source.mk new file mode 100644 index 0000000..d291983 --- /dev/null +++ b/arch/riscv64/gen/source.mk @@ -0,0 +1,8 @@ +$(ARCH_SOURCE)/include/gen/asm-offsets.h: $(ARCH_SOURCE)/gen/asm-offsets.c + echo "#ifndef APOS_ASM_OFFSETS_H" > $@ + echo "#define APOS_ASM_OFFSETS_H" >> $@ + $(COMPILER) $(INCLUDE_FLAGS) -S $< -o - |\ + awk '($$1 == "->") { print "#define " $$2 " " $$3 }' >> $@ + echo "#endif /* APOS_ASM_OFFSETS_H */" >> $@ + +CLEANUP += $(ARCH_SOURCE)/include/gen/* diff --git a/arch/riscv64/include/regs.h b/arch/riscv64/include/regs.h new file mode 100644 index 0000000..699af8b --- /dev/null +++ b/arch/riscv64/include/regs.h @@ -0,0 +1,9 @@ +#ifndef APOS_RISCV_REGS_H +#define APOS_RISCV_REGS_H + +struct riscv_regs { + long ra, sp, gp, tp, t0, t1, t2, s0, s1, a0, a1, a2, a3, a4, a5, a6, a7, + s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, t3, t4, t5, t6; +}; + +#endif /* APOS_RISCV_REGS_H */ diff --git a/arch/riscv64/include/vmem.h b/arch/riscv64/include/vmem.h index 9816110..222d54b 100644 --- a/arch/riscv64/include/vmem.h +++ b/arch/riscv64/include/vmem.h @@ -4,16 +4,20 @@ #include #include -#define RISCV_NUM_LEAVES (4096 / sizeof(void *)) +#if __riscv_xlen == 64 +#define RISCV_NUM_LEAVES 512 +#else +#define RISCV_NUM_LEAVES 1024 +#endif -#define VM_V (1 << 0) -#define VM_R (1 << 1) -#define VM_W (1 << 2) -#define VM_X (1 << 3) -#define VM_U (1 << 4) -#define VM_G (1 << 5) -#define VM_A (1 << 6) -#define VM_D (1 << 7) +#define VM_V (1 << 0) +#define VM_R (1 << 1) +#define VM_W (1 << 2) +#define VM_X (1 << 3) +#define VM_U (1 << 4) +#define VM_G (1 << 5) +#define VM_A (1 << 6) +#define VM_D (1 << 7) enum mm_mode { Sv48, 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 #include #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 diff --git a/arch/riscv64/kernel/irq.c b/arch/riscv64/kernel/irq.c index d350426..fdcd21e 100644 --- a/arch/riscv64/kernel/irq.c +++ b/arch/riscv64/kernel/irq.c @@ -3,6 +3,8 @@ #include #include +extern void handle_irq(void); + void init_irq(void *fdt) { UNUSED(fdt); diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c index 66325ec..8653254 100644 --- a/arch/riscv64/kernel/proc.c +++ b/arch/riscv64/kernel/proc.c @@ -1,10 +1,12 @@ #include #include +#include #include stat_t jump_to_userspace(struct tcb *t, int argc, char **argv) { csr_write(CSR_SEPC, t->entry); + csr_write(CSR_SSCRATCH, t); __asm__ volatile("mv sp, %0\n" ::"r"(t->proc_stack_top) : "memory"); __asm__ volatile("sret\n" ::: "memory"); /* we should never reach this */ @@ -16,3 +18,18 @@ stat_t return_to_userspace(struct tcb *t) /* lol */ return ERR_ADDR; } + +stat_t prepare_thread(struct tcb *t) +{ + /* get location of registers in memory */ + /* TODO: check alignment, should be fine but just to be sure */ + struct riscv_regs *r = (struct riscv_regs *)t; + r--; + + r->sp = (long)t->proc_stack_top; + r->tp = (long)t; + + /* set entry point */ + csr_write(CSR_SEPC, t->entry); + return OK; +} diff --git a/arch/riscv64/source.mk b/arch/riscv64/source.mk index fec5f80..8c1dfcb 100644 --- a/arch/riscv64/source.mk +++ b/arch/riscv64/source.mk @@ -1,8 +1,9 @@ -KERNEL_LOCAL != echo arch/riscv64/kernel/*.[cS] +KERNEL_LOCAL != echo $(ARCH_SOURCE)/kernel/*.[cS] KERNEL_SOURCES += $(KERNEL_LOCAL) -INIT_SOURCES += arch/riscv64/init/*.[cS] +INIT_SOURCES += $(ARCH_SOURCE)/init/*.[cS] -CLEANUP_CMD := ./arch/riscv64/conf/rmimage.sh +# this doesn't work for rv32, but fine for now */ +CLEANUP_CMD := $(ARCH_SOURCE)/conf/rmimage.sh ARCH_CFLAGS := -mcmodel=medany ARCH_LDFLAGS := @@ -15,4 +16,9 @@ ARCH_LDFLAGS := #LINKFLAGS := -fuse-ld=bfd run: - ./arch/riscv64/conf/mkimage.sh + $(ARCH_SOURCE)/conf/mkimage.sh + +include $(ARCH_SOURCE)/gen/source.mk + +# dependecy generation +$(ARCH_BUILD)/kernel/head.o: $(ARCH_SOURCE)/include/gen/asm-offsets.h -- cgit v1.3