aboutsummaryrefslogtreecommitdiff
path: root/common/tcb.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-11-12 16:41:36 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2022-11-12 16:41:36 +0200
commit41ead8de77963bae907375c1bb115dad3315f46b (patch)
tree4b364db137bd3bea69853f15329292af7662897d /common/tcb.c
parent1d37792fb7a47135f0e7b7fc245e83bb1d8fc496 (diff)
downloadkmi-41ead8de77963bae907375c1bb115dad3315f46b.tar.gz
kmi-41ead8de77963bae907375c1bb115dad3315f46b.zip
initial rpc implementations
Diffstat (limited to 'common/tcb.c')
-rw-r--r--common/tcb.c83
1 files changed, 75 insertions, 8 deletions
diff --git a/common/tcb.c b/common/tcb.c
index 0a676af..aa66d3f 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -96,11 +96,11 @@ static vm_t __setup_rpc_stack(struct tcb *t, size_t bytes)
vmflags_t flags = VM_V | VM_R | VM_W | VM_U;
for (size_t i = 1; i <= pages; ++i) {
offset = alloc_page(BASE_PAGE);
- map_vpage(t->proc.vmem, offset,
+ map_vpage(t->rpc.vmem, offset,
RPC_STACK_TOP - BASE_PAGE_SIZE * i,
flags, BASE_PAGE);
}
-
+ t->rpc_stack = RPC_STACK_TOP;
return RPC_STACK_TOP - BASE_PAGE_SIZE * pages;
}
@@ -116,7 +116,7 @@ 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_stacks(struct tcb *t)
+stat_t alloc_stack(struct tcb *t)
{
/* get parent process */
struct tcb *p = get_tcb(t->eid);
@@ -125,11 +125,6 @@ stat_t alloc_stacks(struct tcb *t)
if (!t->thread_stack)
return ERR_OOMEM;
- /* rpc stack always starts at the same place in vmem.
- * \todo: is this a security issue? */
- if (!__setup_rpc_stack(p, __call_stack_size))
- return ERR_OOMEM;
-
/** \todo this only allows for a global stack size, what if a user wants
* per thread stack sizes? */
t->thread_stack_top = t->thread_stack + __thread_stack_size;
@@ -166,6 +161,7 @@ struct tcb *create_thread(struct tcb *p)
t->eid = t->pid;
t->rid = p->rid;
t->rpc.vmem = create_vmem();
+ __setup_rpc_stack(t, __call_stack_size);
set_canary(t);
return t;
@@ -186,6 +182,10 @@ static stat_t __copy_proc(struct tcb *p, struct tcb *n)
* need to duplicate stack info, whatever we do. */
/** @todo should there be in-kernel child tracking? */
n->exec = p->exec;
+ n->callback = p->callback;
+ n->thread_stack = p->thread_stack;
+ n->thread_stack_top = p->thread_stack_top;
+
clone_regs(n, p);
copy_caps(n->caps, p->caps);
return clone_mem_regions(n, p);
@@ -374,3 +374,70 @@ bool running(struct tcb *t)
{
return cpu_tcb(t->cpu_id) == t;
}
+
+/**
+ * Mark rpc stack between \p start and \p end inaccessible.
+ *
+ * @param t Thread whose rpc stack to modify.
+ * @param start Start address of rpc stack to mark inaccessible.
+ * @param end End address of rpc stack to mark inaccessible.
+ */
+static void mark_rpc_inaccessible(struct tcb *t, vm_t start, vm_t end)
+{
+ size_t page_size = BASE_PAGE_SIZE;
+ size_t size = end - start;
+ size_t pages = size / page_size;
+ while (pages--) {
+ /** @todo something like mod_vpage_flags could be faster */
+ vmflags_t flags; pm_t paddr;
+ stat_vpage(t->rpc.vmem, start, &paddr, NULL, &flags);
+ mod_vpage(t->rpc.vmem, start, paddr, clear_bits(flags, VM_U));
+ }
+}
+
+/**
+ * Mark rpc stack between \p start and \p end accessible.
+ *
+ * @param t Thread whose rpc stack to modify.
+ * @param start Start address of rpc stack to mark accessible.
+ * @param end End address of rpc stack to mark accessible.
+ */
+static void mark_rpc_accessible(struct tcb *t, vm_t start, vm_t end)
+{
+ size_t page_size = BASE_PAGE_SIZE;
+ size_t size = end - start;
+ size_t pages = size / page_size;
+ while (pages--) {
+ /** @todo something like mod_vpage_flags could be faster */
+ vmflags_t flags; pm_t paddr;
+ stat_vpage(t->rpc.vmem, start, &paddr, NULL, &flags);
+ mod_vpage(t->rpc.vmem, start, paddr, set_bits(flags, VM_U));
+ }
+}
+
+void save_context(struct tcb *t)
+{
+ vm_t rpc_stack = t->rpc_stack;
+ if (is_rpc(t))
+ /** @todo what if user uses their own stack? */
+ rpc_stack = align_down(get_stack(t), BASE_PAGE_SIZE);
+
+ struct tcb *copy = (struct tcb *)(rpc_stack - sizeof(struct tcb));
+ memcpy(copy, t, sizeof(struct tcb));
+ clone_regs(copy, t);
+
+ rpc_stack -= BASE_PAGE_SIZE;
+ mark_rpc_inaccessible(t, rpc_stack, t->rpc_stack);
+ t->rpc_stack = rpc_stack;
+}
+
+void load_context(struct tcb *t)
+{
+ vm_t rpc_stack = t->rpc_stack;
+ struct tcb *copy =
+ (struct tcb *)(rpc_stack + BASE_PAGE_SIZE - sizeof(struct tcb));
+ memcpy(t, copy, sizeof(struct tcb));
+ clone_regs(t, copy);
+
+ mark_rpc_accessible(t, rpc_stack, t->rpc_stack);
+}