aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
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;
+}