aboutsummaryrefslogtreecommitdiff
path: root/arch
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
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')
-rw-r--r--arch/riscv64/asm/asm-offsets.c2
-rw-r--r--arch/riscv64/config.h3
-rw-r--r--arch/riscv64/include/tcb.h3
-rw-r--r--arch/riscv64/kernel/entry.S4
-rw-r--r--arch/riscv64/kernel/smp.c3
-rw-r--r--arch/riscv64/kernel/vmem.c81
6 files changed, 89 insertions, 7 deletions
diff --git a/arch/riscv64/asm/asm-offsets.c b/arch/riscv64/asm/asm-offsets.c
index a053996..80a48f2 100644
--- a/arch/riscv64/asm/asm-offsets.c
+++ b/arch/riscv64/asm/asm-offsets.c
@@ -98,7 +98,7 @@ void asm_offsets()
/* At the moment tcbd is just a single register slot, so this works, but
* if it's expanded in the future I'll need to figure out a way to
* target specific substructure members. */
- OFFSETOF(tcbd, struct tcb);
+ OFFSETOF(arch, struct tcb);
SIZEOF(tcb, struct tcb);
ENUM(SYS_IPC_RESP);
diff --git a/arch/riscv64/config.h b/arch/riscv64/config.h
index a2694d5..765aa6b 100644
--- a/arch/riscv64/config.h
+++ b/arch/riscv64/config.h
@@ -73,9 +73,6 @@
/** User virtual memory space end. */
#define UVMEM_END (SZ_256G - SZ_8G)
-/** RPC stack top. */
-#define RPC_STACK_TOP (UVMEM_END + SZ_1G)
-
/** RPC stack base. */
#define RPC_STACK_BASE (UVMEM_END)
diff --git a/arch/riscv64/include/tcb.h b/arch/riscv64/include/tcb.h
index 33e8fad..a804175 100644
--- a/arch/riscv64/include/tcb.h
+++ b/arch/riscv64/include/tcb.h
@@ -15,6 +15,9 @@
struct arch_tcbd {
/** Extra scratch register. */
long scratch;
+
+ struct vmem *rpc_leaf;
+ int rpc_idx;
};
#endif /* ARCH_RISCV_TCB_H */
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;
+}