aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv64/kernel
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2023-10-09 14:57:18 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2023-10-09 16:15:06 +0300
commit9c9d589ea310f1290e4d6d2019fc8b51d9a86e42 (patch)
tree81694631f4e848728774c22256baf6cded4f910d /arch/riscv64/kernel
parentb2f0f82e18665cb754b93d9795a6f1fb9dfc7c93 (diff)
downloadkmi-9c9d589ea310f1290e4d6d2019fc8b51d9a86e42.tar.gz
kmi-9c9d589ea310f1290e4d6d2019fc8b51d9a86e42.zip
move rpc stack handling to arch-specific code
+ Fairly considerable speedup, as we don't have to look up the rpc pte every time separately, instead cacheing them. Adds an architecture specific limitation to total rpc stack size, though.
Diffstat (limited to 'arch/riscv64/kernel')
-rw-r--r--arch/riscv64/kernel/entry.S4
-rw-r--r--arch/riscv64/kernel/smp.c3
-rw-r--r--arch/riscv64/kernel/vmem.c81
3 files changed, 85 insertions, 3 deletions
diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S
index 2959e2f..815694b 100644
--- a/arch/riscv64/kernel/entry.S
+++ b/arch/riscv64/kernel/entry.S
@@ -67,7 +67,7 @@ handle_trap:
call kernel_panic
continue_trap:
- sr sp, offsetof_tcbd(tp)
+ sr sp, offsetof_arch(tp)
lr sp, offsetof_regs(tp)
addi sp, sp, -sizeof_registers
csrrw tp, CSR_SSCRATCH, tp
@@ -78,7 +78,7 @@ continue_trap:
/* get current tcb into tp and set scratch to 0 so we can figure out if
* exception occured in kernel or userspace */
csrrw tp, CSR_SSCRATCH, x0
- lr t5, offsetof_tcbd(tp)
+ lr t5, offsetof_arch(tp)
sr t5, offsetof_sp(sp)
/* load supervisor cause */
diff --git a/arch/riscv64/kernel/smp.c b/arch/riscv64/kernel/smp.c
index cacb3b7..8d04491 100644
--- a/arch/riscv64/kernel/smp.c
+++ b/arch/riscv64/kernel/smp.c
@@ -114,6 +114,9 @@ void core_bringup(long hartid)
{
/* assume smp_bringup assigned our cpuid correctly */
id_t cpuid = hartid_to_cpuid(hartid);
+
+ /* output is somewhat messed up due to no synchronisation but I guess
+ * that's fine for now */
info("core %ld online\n", (long)cpuid);
/* realistically stuff after this point could probably be placed
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c
index e2d0fa3..7d1d3cc 100644
--- a/arch/riscv64/kernel/vmem.c
+++ b/arch/riscv64/kernel/vmem.c
@@ -6,6 +6,7 @@
* riscv64 implementation of arch-specific virtual memory handling.
*/
+#include <kmi/assert.h>
#include <kmi/string.h>
#include <kmi/pmem.h>
#include <kmi/vmem.h>
@@ -375,7 +376,7 @@ void flush_tlb_full()
void flush_tlb_all()
{
- /** @todo this only works on a single core atm. */
+ /** @todo this only works on a single core atm. needs to do an IPI */
__asm__ volatile ("sfence.vma\n" ::: "memory");
}
@@ -490,3 +491,81 @@ void clone_uvmem(struct vmem * restrict r, struct vmem * restrict b)
b->leaf[i] = 0;
}
}
+
+size_t max_rpc_size()
+{
+ return SZ_512K;
+}
+
+void setup_rpc_stack(struct tcb *t)
+{
+ /* by default rpc stack is marked inaccessible to generate segfaults on
+ * access so as to ease stack usage tracking */
+ vmflags_t flags = VM_V | VM_R | VM_W | VM_U;
+
+ size_t pages = order_size(MM_O1) / BASE_PAGE_SIZE;
+ for (size_t i = 0; i < pages; ++i) {
+ pm_t page = alloc_page(BASE_PAGE);
+ map_vpage(t->rpc.vmem, page,
+ RPC_STACK_BASE + BASE_PAGE_SIZE * i,
+ flags, BASE_PAGE);
+
+ map_vpage(t->proc.vmem, page,
+ RPC_STACK_BASE + BASE_PAGE_SIZE * i,
+ flags, BASE_PAGE);
+ }
+
+ /* we allocated a second order page for rpc stack usage */
+ t->rpc_stack = RPC_STACK_BASE + order_size(MM_O1);
+ /* slightly hacky maybe but we know the first pte is at RPC_STACK_BASE,
+ * which means that it must also be the leaf */
+ t->arch.rpc_leaf = (struct vmem *)__find_vmem(t->rpc.vmem,
+ RPC_STACK_BASE, BASE_PAGE);
+ /* 'reserve' top page of stack for kernel use */
+ t->arch.rpc_idx = 511;
+}
+
+vm_t rpc_position(struct tcb *t)
+{
+ /** @todo we assume rpc_idx is updated on every segfault of the rpc stack */
+ /** @todo hmm, technically speaking we always know that on riscv the base
+ * page size if 4096, would it be a good idea to replace BASE_PAGE_SIZE in
+ * riscv-specific code with a RISCV_BASE_PAGE_SIZE or something? */
+ return RPC_STACK_BASE + (BASE_PAGE_SIZE * t->arch.rpc_idx);
+}
+
+void mark_rpc_invalid(struct tcb *t, vm_t top)
+{
+ struct vmem *b = t->arch.rpc_leaf;
+ int top_idx = t->arch.rpc_idx;
+ int bottom_idx = (top - RPC_STACK_BASE) / BASE_PAGE_SIZE;
+ catastrophic_assert(bottom_idx < top_idx);
+
+ while (top_idx != bottom_idx) {
+ pm_t *pte = (pm_t *)&b->leaf[top_idx];
+ /* make page not accessible from userspace */
+ clear_bits(*pte, vp_flags(VM_U));
+ top_idx--;
+ }
+
+ t->arch.rpc_idx = top_idx;
+}
+
+void mark_rpc_valid(struct tcb *t, vm_t bottom)
+{
+ struct vmem *b = t->arch.rpc_leaf;
+ int bottom_idx = t->arch.rpc_idx;
+ int top_idx = (bottom - RPC_STACK_BASE) / BASE_PAGE_SIZE;
+ catastrophic_assert(bottom_idx < top_idx);
+
+ while (top_idx != bottom_idx) {
+ pm_t *pte = (pm_t *)&b->leaf[bottom_idx];
+ /* make page accessible from userspace */
+ set_bits(*pte, vp_flags(VM_U));
+ /* clear used bits */
+ clear_bits(*pte, vp_flags(VM_A | VM_D));
+ bottom_idx++;
+ }
+
+ t->arch.rpc_idx = bottom_idx;
+}