diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-10-29 21:17:31 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-10-29 21:17:31 +0200 |
| commit | 5976ad390a15726c3ddfacf8c8b282c8350f9554 (patch) | |
| tree | 24a55fcd7e6f28d048ac074da59f428b54a81cb0 /src | |
| parent | 314bca3dc19a864c76153bfcd5a58be8c40000f9 (diff) | |
| download | kmi-5976ad390a15726c3ddfacf8c8b282c8350f9554.tar.gz kmi-5976ad390a15726c3ddfacf8c8b282c8350f9554.zip | |
start moving towards threads always being in rpc
Diffstat (limited to 'src')
| -rw-r--r-- | src/bkl.c | 5 | ||||
| -rw-r--r-- | src/elf.c | 4 | ||||
| -rw-r--r-- | src/main.c | 1 | ||||
| -rw-r--r-- | src/orphanage.c | 4 | ||||
| -rw-r--r-- | src/panic.c | 20 | ||||
| -rw-r--r-- | src/tcb.c | 35 | ||||
| -rw-r--r-- | src/uapi/conf.c | 8 | ||||
| -rw-r--r-- | src/uapi/ipc.c | 37 |
8 files changed, 51 insertions, 63 deletions
@@ -12,6 +12,11 @@ /** The Big Kernel Lock. */ static spinlock_t bkl = 0; +void bkl_init() +{ + bkl = 0; +} + void bkl_lock() { spin_lock(&bkl); @@ -47,6 +47,8 @@ static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, size_t phnum, size_t phsize) { assert(t && is_proc(t)); + /* temporarily visit process virtual memory */ + use_vmem(t->proc.vmem); /** \todo take alignment into consideration? */ /** \todo take overlapping memory regions into account, probably mostly @@ -91,6 +93,8 @@ static void __map_exec(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, mod_vpage(t->b_r, va, paddr, uvflags); */ } + + use_vmem(t->rpc.vmem); } /** @@ -86,6 +86,7 @@ __noreturn void kernel(void *fdt, uintptr_t load_addr, struct vmem *d) init_proc(fdt, &proc_fdt, &proc_initrd); /* lock kernel since we're about to start other threads as well */ + bkl_init(); bkl_lock(); /* try to bring up other cores on system */ smp_bringup(d, fdt); diff --git a/src/orphanage.c b/src/orphanage.c index 797468d..6de520f 100644 --- a/src/orphanage.c +++ b/src/orphanage.c @@ -39,8 +39,8 @@ void unorphanize(struct tcb *t) t->pid = 1; t->eid = 1; - t->proc = init->proc; - use_vmem(t->proc.vmem); + clone_uvmem(init->proc.vmem, t->rpc.vmem); + use_vmem(t->rpc.vmem); alloc_stack(t); assert(init->callback); diff --git a/src/panic.c b/src/panic.c index 5495ebe..34bfa69 100644 --- a/src/panic.c +++ b/src/panic.c @@ -9,12 +9,28 @@ #include <kmi/syscalls.h> #include <kmi/power.h> #include <kmi/debug.h> +#include <kmi/tcb.h> void kernel_panic(void *pc, void *addr, long cause) { /* could be useful to print out register values as well? */ - error("kernel paniced at pc: %p with address %p and cause %lx\n", - pc, addr, cause); + error("thread %d kernel paniced at pc: %p with address %p and cause %lx\n", + cur_tcb()->cpu_id, pc, addr, cause); + + info("attempting to reboot\n"); + + poweroff(SYS_COLD_REBOOT); + + /* spin if poweroff failed for some reason */ + error("reboot failed, spinning in place\n"); + while (1); +} + +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); info("attempting to reboot\n"); @@ -90,38 +90,22 @@ static id_t __alloc_tid(struct tcb *t) return ERR_NF; } -/** - * Setup thread stack. - * - * @param t Thread to setup stack for. - * @param bytes Minimum size of stack. - * @return Base of allocated stack. - */ -static vm_t __setup_thread_stack(struct tcb *t, size_t bytes) -{ - return alloc_uvmem(t, bytes, VM_V | VM_R | VM_W | VM_U); -} - stat_t alloc_stack(struct tcb *t) { /* get parent process */ struct tcb *p = get_tcb(t->eid); assert(p); - t->thread_stack = __setup_thread_stack(p, thread_stack_size()); - if (!t->thread_stack) + if (setup_rpc_stack(t)) return ERR_OOMEM; - /** \todo this only allows for a global stack size, what if a user wants - * per thread stack sizes? I guess allocate them yourself in userspace - * or something? */ - t->thread_stack_size = thread_stack_size(); + t->regs = t->rpc_stack - sizeof(struct call_ctx); return OK; } void free_stack(struct tcb *t) { - free_uvmem(get_proc(t), t->thread_stack); + destroy_rpc_stack(t); } static stat_t __init_free_thread(struct tcb *t) @@ -158,10 +142,9 @@ static stat_t __init_owned_thread(struct tcb *p, struct tcb *t) t->eid = p->rid; t->pid = p->rid; t->rid = p->rid; - /** @todo I'm assuming two threads can share the same vmem - * structure, this works on riscv but in the event that other - * systems don't we can easily turn this into a clone_uvmem. */ - t->proc.vmem = p->proc.vmem; + + /* someone else owns our vmem */ + t->proc.vmem = NULL; t->callback = p->callback; if (!(t->rpc.vmem = create_vmem())) @@ -207,7 +190,9 @@ struct tcb *create_thread(struct tcb *p) } - t->regs = (vm_t)t; + struct tcb *parent = get_rproc(t); + clone_uvmem(parent->proc.vmem, t->rpc.vmem); + reference_thread(t); set_canary(t); return t; @@ -370,7 +355,7 @@ void use_tcb(struct tcb *t) __cpu_tcb[t->cpu_id] = t; - use_vmem(t->proc.vmem); + use_vmem(t->rpc.vmem); } struct tcb *get_tcb(id_t tid) diff --git a/src/uapi/conf.c b/src/uapi/conf.c index 24a4706..6706a8a 100644 --- a/src/uapi/conf.c +++ b/src/uapi/conf.c @@ -12,6 +12,7 @@ #include <kmi/sizes.h> #include <kmi/uapi.h> #include <kmi/conf.h> +#include <kmi/bkl.h> #include <arch/irq.h> #include <arch/proc.h> @@ -160,5 +161,10 @@ SYSCALL_DEFINE0(sleep)(struct tcb *t) /* presumably we want to wake up on an interrupt */ enable_irqs(); - return_args1(t, sleep()); + + bkl_unlock(); + stat_t r = sleep(); + bkl_lock(); + + return_args1(t, r); } diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c index 5f2aad1..f1db76f 100644 --- a/src/uapi/ipc.c +++ b/src/uapi/ipc.c @@ -15,28 +15,6 @@ #include <kmi/irq.h> #include <kmi/conf.h> -/** Structure for maintaining the required context data for an rpc call. */ -struct call_ctx { - /** Execution continuation point. */ - vm_t exec; - - /** Register save area. */ - vm_t regs; - - /** Position in rpc stack. */ - vm_t rpc_stack; - - /** Effective process ID. */ - id_t eid; - - /** Current process ID. */ - id_t pid; - - /** If this frame was due to a notification, which means leaving the - * frame must restore registers as they were */ - bool notify; -}; - /** * Represents difference between where rpc stack was before rpc call and during. * Used to figure out which areas should be marked inaccessible. @@ -76,7 +54,6 @@ static inline void finalize_rpc(struct tcb *t, struct tcb *r, vm_t s) /* make sure updates are visible when swapping to the new virtual memory */ mark_rpc_invalid(t, s); - use_vmem(t->rpc.vmem); } /** @@ -93,11 +70,10 @@ static inline vm_t enter_rpc(struct tcb *t, struct sys_ret a, enum ipc_flags flags) { /* 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); + vm_t rpc_stack = (is_set(flags, IPC_TAIL) && is_rpc(t)) + ? t->rpc_stack : rpc_position(t); struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1; - ctx->regs = t->regs; t->regs = (vm_t)ctx; /* try to get rid of args as fast as possible to free up registers for @@ -242,8 +218,8 @@ static void leave_rpc(struct tcb *t, struct sys_ret a) { vm_t rpc_stack = t->rpc_stack + BASE_PAGE_SIZE; struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1; + t->regs = (vm_t)ctx; - t->regs = ctx->regs; /* again, get rid of args as fast as possible */ if (!ctx->notify) set_ret(t, 6, a); @@ -259,7 +235,7 @@ static void leave_rpc(struct tcb *t, struct sys_ret a) rpc_stack = ctx->rpc_stack + BASE_PAGE_SIZE; ctx = (struct call_ctx *)(rpc_stack) - 1; - t->regs = ctx->regs; + t->regs = (vm_t)ctx; r = get_tcb(ctx->pid); /* equivalent to return_args1 but without returning so we can @@ -283,11 +259,6 @@ static void leave_rpc(struct tcb *t, struct sys_ret a) if (t->notify_flags) notify(t, 0); - if (is_rpc(t)) - use_vmem(t->rpc.vmem); - else - use_vmem(t->proc.vmem); - if (!ctx->notify) { bkl_unlock(); ret_userspace_partial(); |
