aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv64')
-rwxr-xr-xarch/riscv64/conf/initbin1096 -> 1096 bytes
-rw-r--r--arch/riscv64/conf/initrdbin1536 -> 1536 bytes
-rw-r--r--arch/riscv64/conf/s.S10
-rw-r--r--arch/riscv64/gen/asm-offsets.c44
-rw-r--r--arch/riscv64/gen/source.mk8
-rw-r--r--arch/riscv64/include/regs.h9
-rw-r--r--arch/riscv64/include/vmem.h22
-rw-r--r--arch/riscv64/kernel/head.S136
-rw-r--r--arch/riscv64/kernel/irq.c2
-rw-r--r--arch/riscv64/kernel/proc.c17
-rw-r--r--arch/riscv64/source.mk14
11 files changed, 207 insertions, 55 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init
index c415457..0a67c41 100755
--- a/arch/riscv64/conf/init
+++ b/arch/riscv64/conf/init
Binary files differ
diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd
index 6d2ac10..6021c8f 100644
--- a/arch/riscv64/conf/initrd
+++ b/arch/riscv64/conf/initrd
Binary files 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 <apos/utils.h>
+#include <regs.h>
+
+/* 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 <apos/types.h>
#include <apos/attrs.h>
-#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 <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
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 <arch/irq.h>
#include <csr.h>
+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 <apos/tcb.h>
#include <apos/elf.h>
+#include <regs.h>
#include <csr.h>
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