From 44a73ecab6e91519627786a5101cd4f1a2f2b0d7 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 30 Oct 2024 00:57:33 +0200 Subject: most of the way to passing tests --- src/orphanage.c | 2 -- src/panic.c | 4 ++-- src/pmem.c | 4 +--- src/proc.c | 1 - src/tcb.c | 28 +++------------------------- src/uapi/ipc.c | 1 - src/uapi/proc.c | 26 +++++++++++++++----------- src/vmem.c | 23 +++++++++++++++++++++++ 8 files changed, 44 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/orphanage.c b/src/orphanage.c index 6de520f..6cde48a 100644 --- a/src/orphanage.c +++ b/src/orphanage.c @@ -31,7 +31,6 @@ void unorphanize(struct tcb *t) struct tcb *init = get_tcb(1); reference_thread(init); - free_stack(t); reset_rpc_stack(t); id_t old_rid = t->rid; @@ -41,7 +40,6 @@ void unorphanize(struct tcb *t) clone_uvmem(init->proc.vmem, t->rpc.vmem); use_vmem(t->rpc.vmem); - alloc_stack(t); assert(init->callback); set_ret4(t, 0, t->tid, SYS_USER_ORPHANED, old_rid); diff --git a/src/panic.c b/src/panic.c index 34bfa69..afb598e 100644 --- a/src/panic.c +++ b/src/panic.c @@ -14,8 +14,8 @@ void kernel_panic(void *pc, void *addr, long cause) { /* could be useful to print out register values as well? */ - error("thread %d kernel paniced at pc: %p with address %p and cause %lx\n", - cur_tcb()->cpu_id, pc, addr, cause); + error("kernel paniced at pc: %p with address %p and cause %lx\n", + pc, addr, cause); info("attempting to reboot\n"); diff --git a/src/pmem.c b/src/pmem.c index a0cd4ec..9c839f1 100644 --- a/src/pmem.c +++ b/src/pmem.c @@ -277,9 +277,7 @@ static pm_t __alloc_page(enum mm_order order) __get_bit(bucket, a, &set, &bit); bmap = __get_set(bucket, set); - /* hmm, I might be running into a compiler bug here. Adding this - * assert makes my error go away, weird. */ - assert(bmap->size <= order_width(order + 1)); + bmap->size = order_width(order + 1); bmap->next = NULL; bmap->prev = NULL; diff --git a/src/proc.c b/src/proc.c index 1c90fdc..62b3e42 100644 --- a/src/proc.c +++ b/src/proc.c @@ -25,7 +25,6 @@ stat_t prepare_proc(struct tcb *t, vm_t bin, vm_t interp) return ERR_INVAL; t->callback = entry; - alloc_stack(t); set_thread(t); set_return(t, entry); return OK; diff --git a/src/tcb.c b/src/tcb.c index eebaaa4..f5b1652 100644 --- a/src/tcb.c +++ b/src/tcb.c @@ -90,24 +90,6 @@ static id_t __alloc_tid(struct tcb *t) return ERR_NF; } -stat_t alloc_stack(struct tcb *t) -{ - /* get parent process */ - struct tcb *p = get_tcb(t->eid); - assert(p); - - if (setup_rpc_stack(t)) - return ERR_OOMEM; - - t->regs = t->rpc_stack - sizeof(struct call_ctx); - return OK; -} - -void free_stack(struct tcb *t) -{ - destroy_rpc_stack(t); -} - static stat_t __init_free_thread(struct tcb *t) { if (!(t->proc.vmem = create_vmem())) @@ -130,6 +112,7 @@ static stat_t __init_free_thread(struct tcb *t) return ERR_OOMEM; } + t->regs = t->rpc_stack - sizeof(struct call_ctx); t->pid = t->tid; t->eid = t->tid; t->rid = t->tid; @@ -156,6 +139,7 @@ static stat_t __init_owned_thread(struct tcb *p, struct tcb *t) return ERR_OOMEM; } + t->regs = t->rpc_stack - sizeof(struct call_ctx); reference_thread(p); return OK; } @@ -208,16 +192,12 @@ struct tcb *create_thread(struct tcb *p) static stat_t __copy_proc(struct tcb *p, struct tcb *n) { /** @todo setup rpc stack stuff */ - /** @todo I think keeping track of userspace stack stuff is unnecessary, - * unless we want unlimited stack size but that sounds dumb. Anycase, we - * need to duplicate stack info, whatever we do. */ n->exec = p->exec; n->callback = p->callback; - n->thread_stack = p->thread_stack; - n->thread_stack_size = p->thread_stack_size; copy_regs(n, p); copy_caps(n->caps, p->caps); + copy_rpc_stack(p, n); return copy_uvmem(n, p); } @@ -270,8 +250,6 @@ stat_t destroy_thread(struct tcb *t) /* if we're our own root process, we unreference ourselves later */ unreference_thread(r); - free_stack(t); - /* free memory backing rpc stack */ destroy_rpc_stack(t); diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c index f1db76f..6e33165 100644 --- a/src/uapi/ipc.c +++ b/src/uapi/ipc.c @@ -102,7 +102,6 @@ static inline vm_t enter_rpc(struct tcb *t, struct sys_ret a, * limit just give it more. * */ t->rpc_stack = new_stack; - set_stack(t, new_stack); return new_stack; } diff --git a/src/uapi/proc.c b/src/uapi/proc.c index b010220..3b65a04 100644 --- a/src/uapi/proc.c +++ b/src/uapi/proc.c @@ -38,19 +38,18 @@ SYSCALL_DEFINE5(create)(struct tcb *t, sys_arg_t func, if (!c) return_args1(t, ERR_OOMEM); - /** @todo there's quite a bit of overlap between this and what - * core_bringup() is doing, might separate this out into its own - * function? */ - if (alloc_stack(c)) { - destroy_thread(c); - return_args1(t, ERR_OOMEM); - } + /* temporarily jump into new thread memory to set arguments */ + use_vmem(c->rpc.vmem); + /* this visit is likely not the cheapest thing in the universe, are + * there ways to speed up thread creation? */ set_thread(c); - set_ret5(c, c->tid, d0, d1, d2, d3); set_return(c, func); + /* return back */ + use_vmem(t->rpc.vmem); + c->notify_id = t->notify_id; return_args1(t, c->tid); } @@ -81,9 +80,13 @@ SYSCALL_DEFINE0(fork)(struct tcb *t) if (!n) return_args1(t, ERR_OOMEM); + /* again, probably not fantastic that we're jumping between address + * spaces like this */ + use_vmem(n->rpc.vmem); /* prepare args for when we eventually swap to the new proc, giving * parent ID as third return value */ set_args2(n, 0, get_eproc(t)->pid); + use_vmem(t->rpc.vmem); n->notify_id = c->notify_id; return_args1(t, n->pid); @@ -189,6 +192,10 @@ SYSCALL_DEFINE2(spawn)(struct tcb *t, sys_arg_t bin, sys_arg_t interp) */ static void swap(struct tcb *t, struct tcb *s) { + /* set return value for current thread, important to do first since + * use_tcb() switches the register slots, really easy to miss, not great */ + set_args1(t, OK); + /* switch over to new thread */ use_tcb(s); @@ -201,9 +208,6 @@ static void swap(struct tcb *t, struct tcb *s) return; } - /* set return value for current thread */ - set_args1(t, OK); - /* handle possible queued notification */ if (s->notify_flags) notify(s, 0); diff --git a/src/vmem.c b/src/vmem.c index f4f1bf7..bd0cd7c 100644 --- a/src/vmem.c +++ b/src/vmem.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -408,3 +409,25 @@ vmflags_t sanitize_uvflags(vmflags_t flags) { return (flags & (VM_R | VM_W | VM_X)) | VM_V | VM_U; } + +void handle_pagefault(vm_t addr) +{ + struct tcb *t = cur_tcb(); + struct tcb *p = get_cproc(t); + + size_t ref = __page(addr); + + struct mem_region *m = find_closest_used_region(&p->uvmem.region, addr); + if (!m || (ref < m->start || ref > m->end) || !is_region_used(m)) { + error("cannot handle actual page fault just yet :(\n"); + kernel_panic(NULL, NULL, 0); + return; + } + + /* this is a valid address so presumably the proc virtual memory has + * some changes that haven't been reflected over in our rpc virtual + * memory so make them visible */ + clone_uvmem(p->proc.vmem, t->rpc.vmem); + flush_tlb_all(); + return; +} -- cgit v1.3