aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-10-29 21:17:31 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2024-10-29 21:17:31 +0200
commit5976ad390a15726c3ddfacf8c8b282c8350f9554 (patch)
tree24a55fcd7e6f28d048ac074da59f428b54a81cb0 /src
parent314bca3dc19a864c76153bfcd5a58be8c40000f9 (diff)
downloadkmi-5976ad390a15726c3ddfacf8c8b282c8350f9554.tar.gz
kmi-5976ad390a15726c3ddfacf8c8b282c8350f9554.zip
start moving towards threads always being in rpc
Diffstat (limited to 'src')
-rw-r--r--src/bkl.c5
-rw-r--r--src/elf.c4
-rw-r--r--src/main.c1
-rw-r--r--src/orphanage.c4
-rw-r--r--src/panic.c20
-rw-r--r--src/tcb.c35
-rw-r--r--src/uapi/conf.c8
-rw-r--r--src/uapi/ipc.c37
8 files changed, 51 insertions, 63 deletions
diff --git a/src/bkl.c b/src/bkl.c
index 6ee58f4..e831451 100644
--- a/src/bkl.c
+++ b/src/bkl.c
@@ -12,6 +12,11 @@
/** The Big Kernel Lock. */
static spinlock_t bkl = 0;
+void bkl_init()
+{
+ bkl = 0;
+}
+
void bkl_lock()
{
spin_lock(&bkl);
diff --git a/src/elf.c b/src/elf.c
index 29c9c09..259c77e 100644
--- a/src/elf.c
+++ b/src/elf.c
@@ -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);
}
/**
diff --git a/src/main.c b/src/main.c
index 12d8514..171d1d1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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");
diff --git a/src/tcb.c b/src/tcb.c
index 70cad5a..eebaaa4 100644
--- a/src/tcb.c
+++ b/src/tcb.c
@@ -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();