aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-10-30 00:57:33 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2024-10-30 00:57:33 +0200
commit44a73ecab6e91519627786a5101cd4f1a2f2b0d7 (patch)
treef5c811050a4d5ee832f5883c4d0c27efddd60817 /arch/riscv64
parent5976ad390a15726c3ddfacf8c8b282c8350f9554 (diff)
downloadkmi-44a73ecab6e91519627786a5101cd4f1a2f2b0d7.tar.gz
kmi-44a73ecab6e91519627786a5101cd4f1a2f2b0d7.zip
most of the way to passing tests
Diffstat (limited to 'arch/riscv64')
-rw-r--r--arch/riscv64/kernel/entry.S19
-rw-r--r--arch/riscv64/kernel/except.c21
-rw-r--r--arch/riscv64/kernel/proc.c14
-rw-r--r--arch/riscv64/kernel/smp.c1
-rw-r--r--arch/riscv64/kernel/vmem.c17
5 files changed, 66 insertions, 6 deletions
diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S
index 0bc999e..f894e0d 100644
--- a/arch/riscv64/kernel/entry.S
+++ b/arch/riscv64/kernel/entry.S
@@ -62,6 +62,7 @@ handle_trap:
bnez tp, continue_trap
/* the trap came from the kernel, should never happen so just panic
* and abort or whatever */
+ csrw CSR_SSCRATCH, x0
csrr a0, CSR_SEPC
csrr a1, CSR_STVAL
csrr a2, CSR_SCAUSE
@@ -92,8 +93,16 @@ continue_trap:
save_caller
mv a0, s10
+ /* get actual kernel stack into sp */
+ mv sp, tp
call riscv_handle_interrupt
+ lr sp, offsetof_regs(tp)
+ addi sp, sp, -sizeof_registers
+ /* set execution continuation */
+ lr s10, offsetof_exec(tp)
+ csrw CSR_SEPC, s10
+
j _load_context
handle_exception:
@@ -108,7 +117,14 @@ handle_exception:
csrr a0, CSR_SEPC
csrr a1, CSR_STVAL
csrr a2, CSR_SCAUSE
- call unhandled_panic
+ mv sp, tp
+ call riscv_handle_exception
+
+ lr sp, offsetof_regs(tp)
+ addi sp, sp, -sizeof_registers
+ /* set execution continuation */
+ lr s10, offsetof_exec(tp)
+ csrw CSR_SEPC, s10
j _load_context
@@ -129,6 +145,7 @@ fast_dispatch:
csrr s10, CSR_SEPC
sr s10, offsetof_exec(tp)
/* jump to C */
+ mv sp, tp
call dispatch
/* if we had a thread switch, load kernel stack of current thread and
* restore its context */
diff --git a/arch/riscv64/kernel/except.c b/arch/riscv64/kernel/except.c
new file mode 100644
index 0000000..e46b584
--- /dev/null
+++ b/arch/riscv64/kernel/except.c
@@ -0,0 +1,21 @@
+#include <kmi/types.h>
+#include <kmi/panic.h>
+#include <kmi/vmem.h>
+#include <kmi/bkl.h>
+
+void riscv_handle_exception(void *pc, void *addr, unsigned long id)
+{
+ switch (id) {
+ case 12:
+ case 13:
+ case 15: {
+ bkl_lock();
+ handle_pagefault((vm_t)addr);
+ bkl_unlock();
+ break;
+ }
+
+ default:
+ unhandled_panic(pc, addr, id);
+ }
+}
diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c
index f012b20..3ae2e15 100644
--- a/arch/riscv64/kernel/proc.c
+++ b/arch/riscv64/kernel/proc.c
@@ -81,7 +81,7 @@ void set_thread(struct tcb *t)
struct riscv_regs *r = (struct riscv_regs *)(t->regs) - 1;
/* insert important values into register slots */
- r->sp = (long)t->thread_stack + t->thread_stack_size;
+ r->sp = (long)t->rpc_stack - BASE_PAGE_SIZE;
}
void set_stack(struct tcb *t, vm_t s)
@@ -99,9 +99,15 @@ vm_t get_stack(struct tcb *t)
void copy_regs(struct tcb *d, struct tcb *s)
{
- struct riscv_regs *rd = (struct riscv_regs *)(d->regs) - 1;
- struct riscv_regs *rs = (struct riscv_regs *)(s->regs) - 1;
- *rd = *rs;
+ struct riscv_regs rs = *((struct riscv_regs *)(s->regs) - 1);
+ /* again, not a fan of this, I guess we could query the underlying
+ * physical page? Would that be any faster? */
+ use_vmem(d->rpc.vmem);
+
+ struct riscv_regs *rd = ((struct riscv_regs *)(d->regs) - 1);
+ *rd = rs;
+
+ use_vmem(s->rpc.vmem);
}
void adjust_ipi(struct tcb *t)
diff --git a/arch/riscv64/kernel/smp.c b/arch/riscv64/kernel/smp.c
index acb5f04..5e30fee 100644
--- a/arch/riscv64/kernel/smp.c
+++ b/arch/riscv64/kernel/smp.c
@@ -139,7 +139,6 @@ __noreturn void core_bringup(long hartid)
struct tcb *t = create_thread(init);
assert(t);
- alloc_stack(t);
/* init is special in that all threads jump to the entrypoint of the
* program */
t->exec = init->exec;
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c
index cf1391e..5a44f53 100644
--- a/arch/riscv64/kernel/vmem.c
+++ b/arch/riscv64/kernel/vmem.c
@@ -563,6 +563,23 @@ size_t max_rpc_size()
return SZ_512K;
}
+void copy_rpc_stack(struct tcb *t, struct tcb *c)
+{
+ /* this is of terrible, copying 2MiB for every fork, not
+ * great. TODO: use the direct pointer to the rpc stack element? */
+ for (size_t i = 0; i < rpc_pages; ++i) {
+ pm_t p1, p2;
+ stat_t ok1 = stat_vpage(t->rpc.vmem, RPC_STACK_BASE + BASE_PAGE_SIZE * i,
+ &p1, NULL, NULL);
+
+ stat_t ok2 = stat_vpage(c->rpc.vmem, RPC_STACK_BASE + BASE_PAGE_SIZE * i,
+ &p2, NULL, NULL);
+
+ assert(ok1 == OK && ok2 == OK);
+ memcpy((void *)p2, (void *)p1, BASE_PAGE_SIZE);
+ }
+}
+
stat_t setup_rpc_stack(struct tcb *t)
{
/* by default rpc stack is marked inaccessible to generate segfaults on