aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv64/kernel/vmem.c10
-rw-r--r--include/arch/proc.h7
-rw-r--r--include/arch/tcb.h6
-rw-r--r--include/arch/vmem.h12
-rw-r--r--include/kmi/bkl.h5
-rw-r--r--include/kmi/panic.h10
-rw-r--r--include/kmi/vmem.h8
-rw-r--r--src/panic.c5
-rw-r--r--src/tcb.c17
-rw-r--r--src/uapi/ipc.c2
-rw-r--r--src/vmem.c15
11 files changed, 87 insertions, 10 deletions
diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c
index 1648706..d66ddec 100644
--- a/arch/riscv64/kernel/vmem.c
+++ b/arch/riscv64/kernel/vmem.c
@@ -581,11 +581,13 @@ void copy_rpc_stack(struct tcb *t, struct tcb *c)
* 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 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);
+ 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);
diff --git a/include/arch/proc.h b/include/arch/proc.h
index 7921e5c..b0f0944 100644
--- a/include/arch/proc.h
+++ b/include/arch/proc.h
@@ -127,6 +127,13 @@ __noreturn void run_init(struct tcb *t, vm_t fdt, vm_t initrd);
* so I'm not too worried.
*/
__noreturn void ret_userspace_fast();
+
+/**
+ * Return to userspace, restoring some registers.
+ * Mainly for returning from an ipc_resp, where the user is expected to save
+ * temporary registers on their own.
+ * Same as with \ref ret_userspace_fast(), skips canary checking.
+ */
__noreturn void ret_userspace_partial();
#endif /* KMI_ARCH_PROC_H */
diff --git a/include/arch/tcb.h b/include/arch/tcb.h
index 8eddb07..18386d3 100644
--- a/include/arch/tcb.h
+++ b/include/arch/tcb.h
@@ -42,6 +42,12 @@ stat_t setup_rpc_stack(struct tcb *t);
*/
void destroy_rpc_stack(struct tcb *t);
+/**
+ * Copy over contents in rpc stack from \p t to \p c.
+ *
+ * @param t 'Source'.
+ * @param c 'Destination'-
+ */
void copy_rpc_stack(struct tcb *t, struct tcb *c);
/**
diff --git a/include/arch/vmem.h b/include/arch/vmem.h
index 0f06cc5..ad32519 100644
--- a/include/arch/vmem.h
+++ b/include/arch/vmem.h
@@ -167,11 +167,21 @@ struct vmem *create_vmem();
void use_vmem(struct vmem *b);
/**
- * Destroy virtual memory space.
+ * Completely destroy virtual memory space.
+ * Should only be called for ->proc.vmem, as it is the only one that is sure to
+ * own all nodes.
*
* @param b Virtual memory to destroy.
*/
void destroy_vmem(struct vmem *b);
+
+/**
+ * Destroy 'regular' virtual memory space.
+ * Should be called for ->rpc.vmem, as rpc can have some references that it
+ * doesn't own into ->proc.vmem, and this function is careful not to free those.
+ *
+ * @param b Virtual memory to destroy.
+ */
void destroy_rpcmem(struct vmem *b);
/**
diff --git a/include/kmi/bkl.h b/include/kmi/bkl.h
index 8a56061..b77b08a 100644
--- a/include/kmi/bkl.h
+++ b/include/kmi/bkl.h
@@ -12,6 +12,11 @@
#include <kmi/lock.h>
+/**
+ * Initialize Big Kernel Lock.
+ * In theory, the BKL being statically initialized to 0 should be enough, but
+ * this feels a bit safer.
+ */
void bkl_init();
/** Lock the Big Kernel Lock. */
diff --git a/include/kmi/panic.h b/include/kmi/panic.h
index 121323c..0cfebc7 100644
--- a/include/kmi/panic.h
+++ b/include/kmi/panic.h
@@ -22,6 +22,16 @@
*/
__noreturn void kernel_panic(void *pc, void *addr, long cause);
+/**
+ * Call on some other, like userspace doing something that we currently can't
+ * deal with. Tries to reboot the system. Failing that, spin.
+ * Ideally registers and kernel state would be printed, but keep things simple
+ * for now.
+ *
+ * @param pc Address where fault occured. Should preferably be in the kernel.
+ * @param addr Possibly associated address.
+ * @param cause Possible error code associated with panic. Page fault, etc.
+ */
__noreturn void unhandled_panic(void *pc, void *addr, long cause);
#endif /* KMI_PANIC_H */
diff --git a/include/kmi/vmem.h b/include/kmi/vmem.h
index 9424e33..0f1832a 100644
--- a/include/kmi/vmem.h
+++ b/include/kmi/vmem.h
@@ -174,6 +174,14 @@ stat_t copy_uvmem(struct tcb *d, struct tcb *s);
*/
vmflags_t sanitize_uvflags(vmflags_t flags);
+/**
+ * Handle page faults.
+ * If a page fault was to some legal address, the TLB is repopulated and the
+ * access is attempted again. Kind of like COW.
+ * Otherwise, the process gets killed (TODO)
+ *
+ * @param addr Address that caused a page fault.
+ */
void handle_pagefault(vm_t addr);
#endif /* KMI_VMEM_H */
diff --git a/src/panic.c b/src/panic.c
index afb598e..69247de 100644
--- a/src/panic.c
+++ b/src/panic.c
@@ -29,8 +29,9 @@ void kernel_panic(void *pc, void *addr, long cause)
void unhandled_panic(void *pc, void *addr, long cause)
{
/* could be useful to print out register values as well? */
- error("thread %d unhandled panic at pc: %p with address %p and cause %lx\n",
- cur_tcb()->cpu_id, pc, addr, cause);
+ error(
+ "thread %d unhandled panic at pc: %p with address %p and cause %lx\n",
+ cur_tcb()->cpu_id, pc, addr, cause);
info("attempting to reboot\n");
diff --git a/src/tcb.c b/src/tcb.c
index 1281da2..818d4e7 100644
--- a/src/tcb.c
+++ b/src/tcb.c
@@ -90,6 +90,13 @@ static id_t __alloc_tid(struct tcb *t)
return ERR_NF;
}
+/**
+ * Initialize thread that isn't bound to any parent process, i.e. it will become
+ * a process in itself.
+ *
+ * @param t Partially constructed tcb to construct further.
+ * @return OK/ERR_OOMEM.
+ */
static stat_t __init_free_thread(struct tcb *t)
{
if (!(t->proc.vmem = create_vmem()))
@@ -102,7 +109,7 @@ static stat_t __init_free_thread(struct tcb *t)
if (!(t->rpc.vmem = create_vmem())) {
destroy_vmem(t->proc.vmem);
- return NULL;
+ return ERR_OOMEM;
}
if (setup_rpc_stack(t)) {
@@ -120,6 +127,13 @@ static stat_t __init_free_thread(struct tcb *t)
return OK;
}
+/**
+ * Initialize thread that is bound to some parent process.
+ *
+ * @param p Parent tcb.
+ * @param t Partially constructed tcb to construct further.
+ * @return OK/ERR_OOMEM.
+ */
static stat_t __init_owned_thread(struct tcb *p, struct tcb *t)
{
t->eid = p->rid;
@@ -220,7 +234,6 @@ struct tcb *create_proc(struct tcb *p)
* Destroy data associated with thread.
*
* @param t Thread whose data to destroy.
- * @return \ref OK.
*/
static void __destroy_thread_data(struct tcb *t)
{
diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c
index 6e33165..6f6862e 100644
--- a/src/uapi/ipc.c
+++ b/src/uapi/ipc.c
@@ -71,7 +71,7 @@ static inline vm_t enter_rpc(struct tcb *t, struct sys_ret a,
{
/* reuse current rpc stack location if we're being kicked */
vm_t rpc_stack = (is_set(flags, IPC_TAIL) && is_rpc(t))
- ? t->rpc_stack : rpc_position(t);
+ ? t->rpc_stack : rpc_position(t);
struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
t->regs = (vm_t)ctx;
diff --git a/src/vmem.c b/src/vmem.c
index bd0cd7c..0404202 100644
--- a/src/vmem.c
+++ b/src/vmem.c
@@ -64,6 +64,14 @@ static stat_t __copy_mapped_region(struct tcb *d, struct tcb *s,
return res;
}
+/**
+ * Reference shared memory, creating a link between the referrer and owner.
+ *
+ * @param d 'Owner' of \p orig.
+ * @param s Referrer of \p ref.
+ * @param ref Address of shared memory reference in \p s.
+ * @param orig Address of shared memory in \p d.
+ */
static void reference_mem(struct tcb *d, struct tcb *s, vm_t ref, vm_t orig)
{
struct mem_region *src = find_used_region(&s->uvmem.region, orig);
@@ -81,6 +89,13 @@ static void reference_mem(struct tcb *d, struct tcb *s, vm_t ref, vm_t orig)
static void __free_mapping(struct tcb *t, struct mem_region *m);
+/**
+ * Unreference memory region at address \p addr.
+ * Also unreferences owning process.
+ *
+ * @param s Reference holder of \p addr.
+ * @param addr Address to unreference. Or would dereference be better?
+ */
static void unreference_mem(struct tcb *s, vm_t addr)
{
struct mem_region *src = find_used_region(&s->uvmem.region, addr);