aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/tcb.c38
-rw-r--r--common/uapi/conf.c16
-rw-r--r--common/uapi/ipc.c69
3 files changed, 12 insertions, 111 deletions
diff --git a/common/tcb.c b/common/tcb.c
index d6194e8..e69f2f0 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -84,42 +84,6 @@ static id_t __alloc_tid(struct tcb *t)
}
/**
- * Setup RPC stack.
- *
- * RPC stack is local to each thread, and should not be visible to other threads
- * in the same process. Currently maps the RPC stack in BASE_PAGE increments, to
- * hopefully allow us to later quickly disallow access to programs lower down in
- * the RPC call chain by turning off all stack pages lower than the current
- * stack pointer. We shall see if this actually works or not.
- *
- * @param t Thread to setup RPC stack for.
- * @param bytes Minimum size of RPC stack.
- * @return Base of allocated RPC stack.
- *
- * \todo add error checking */
-static vm_t __setup_rpc_stack(struct tcb *t, size_t bytes)
-{
- pm_t offset = 0;
- size_t pages = __pages(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->rpc.vmem, offset,
- RPC_STACK_TOP - BASE_PAGE_SIZE * i,
- flags, BASE_PAGE);
-
- /* map stack into both process and rpc vmem since we want to
- * optimistically write data into it during initialization of an
- * rpc. */
- map_vpage(t->proc.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;
-}
-
-/**
* Setup thread stack.
*
* @param t Thread to setup stack for.
@@ -179,7 +143,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);
+ setup_rpc_stack(t);
t->regs = (vm_t)t;
diff --git a/common/uapi/conf.c b/common/uapi/conf.c
index 13be3ee..894b98a 100644
--- a/common/uapi/conf.c
+++ b/common/uapi/conf.c
@@ -18,14 +18,12 @@
/** \todo stack size should really be set on a per-thread basis, and are the
* conf*-syscalls even necessary? */
size_t __thread_stack_size = SZ_2M;
-size_t __call_stack_size = SZ_2M;
size_t __rpc_stack_size = SZ_512K;
/** IDs for configuration parameters. */
/** @todo should probably be moved somewhere so it can be shared with userspace */
enum conf_param {
CONF_THREAD_STACK = 0,
- CONF_CALL_STACK,
CONF_RPC_STACK,
};
@@ -49,10 +47,6 @@ SYSCALL_DEFINE1(conf_get)(struct tcb *t, sys_arg_t param)
val = __thread_stack_size;
break;
- case CONF_CALL_STACK:
- val = __call_stack_size;
- break;
-
case CONF_RPC_STACK:
val = __rpc_stack_size;
break;
@@ -85,17 +79,9 @@ SYSCALL_DEFINE2(conf_set)(struct tcb *t, sys_arg_t param, sys_arg_t val)
__thread_stack_size = align_up(val, BASE_PAGE_SIZE);
break;
- case CONF_CALL_STACK:
- size = align_up(val, BASE_PAGE_SIZE);
- if (size < __rpc_stack_size)
- return_args(t, SYS_RET1(ERR_MISC));
-
- __call_stack_size = size;
- break;
-
case CONF_RPC_STACK:
size = align_up(val, BASE_PAGE_SIZE);
- if (size > __call_stack_size)
+ if (size > max_rpc_size())
return_args1(t, ERR_MISC);
__rpc_stack_size = size;
diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c
index f9b2817..13682c7 100644
--- a/common/uapi/ipc.c
+++ b/common/uapi/ipc.c
@@ -11,43 +11,6 @@
#include <kmi/ipi.h>
#include <kmi/conf.h>
-/**
- * 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--)
- clear_vpage_flags(t->rpc.vmem, start + pages * page_size, 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)
-{
- /** @todo this could still be optimized with arch-specific stuff I would
- * imagine, as set_vpage_flags() has to traverse the whole tree for each
- * page to mark. Instead it should be possible to mark the pages
- * continuously once they've been traversed once. Or maybe even keep
- * around a pointer to where the last stack left off? */
- size_t page_size = BASE_PAGE_SIZE;
- size_t size = end - start;
- size_t pages = size / page_size;
- while (pages--)
- set_vpage_flags(t->rpc.vmem, start + pages * page_size, VM_U);
-}
-
/** Structure for maintaining the required context data for an rpc call. */
struct call_ctx {
/** Execution continuation point. */
@@ -93,7 +56,7 @@ enum ipc_kind {
* @param r Process to migrate to.
* @param sd RPC stack regions to mark inaccessible.
*/
-static void finalize_rpc(struct tcb *t, struct tcb *r, struct stack_diff sd)
+static void finalize_rpc(struct tcb *t, struct tcb *r, vm_t s)
{
clone_uvmem(r->proc.vmem, t->rpc.vmem);
set_return(t, r->callback);
@@ -101,7 +64,7 @@ static void finalize_rpc(struct tcb *t, struct tcb *r, struct stack_diff sd)
t->pid = r->rid;
/* make sure updates are visible when swapping to the new virtual memory */
- mark_rpc_inaccessible(t, sd.start, sd.end);
+ mark_rpc_invalid(t, s);
use_vmem(t->rpc.vmem);
}
@@ -115,18 +78,10 @@ static void finalize_rpc(struct tcb *t, struct tcb *r, struct stack_diff sd)
* @param kind Kind of IPC we're doing. Essentially toggles kick boolean.
* @return RPC stack difference that should be passed to finalize_rpc().
*/
-static struct stack_diff enter_rpc(struct tcb *t, struct sys_ret a,
+static vm_t enter_rpc(struct tcb *t, struct sys_ret a,
enum ipc_kind kind)
{
- vm_t rpc_stack = t->rpc_stack;
- if (is_rpc(t))
- /** @todo what if user uses their own stack? Or is a dick and
- * sets the stack pointer to RPC_STACK_TOP or something? It'll
- * likely only cause a fuckup in the process who did the dumb
- * thing, so maybe just consider it user error? Except by
- * causing the stack of the next rpc to run out of memory... */
- rpc_stack = align_down(get_stack(t), BASE_PAGE_SIZE);
-
+ vm_t rpc_stack = rpc_position(t);
struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
ctx->regs = t->regs;
@@ -148,7 +103,6 @@ static struct stack_diff enter_rpc(struct tcb *t, struct sys_ret a,
* return a status? except it shouldn't happen after we've run
* enough_rpc_stack(). */
vm_t new_stack = rpc_stack - BASE_PAGE_SIZE;
- struct stack_diff sd = {new_stack, t->rpc_stack};
/** @todo what if each stack is only some number of pages, and if a proc
* goes over the limit is is seen as programming error? Possibly user
@@ -162,7 +116,7 @@ static struct stack_diff enter_rpc(struct tcb *t, struct sys_ret a,
* */
t->rpc_stack = new_stack;
set_stack(t, new_stack);
- return sd;
+ return new_stack;
}
/**
@@ -190,7 +144,7 @@ static void leave_rpc(struct tcb *t, struct sys_ret a)
set_return(t, ctx->exec);
/* if we're returning from a failed rpc, this should essentially be a
* no-op */
- mark_rpc_accessible(t, t->rpc_stack, top);
+ mark_rpc_valid(t, top);
t->rpc_stack = ctx->rpc_stack;
t->pid = ctx->pid;
t->eid = ctx->eid;
@@ -211,13 +165,11 @@ static void leave_rpc(struct tcb *t, struct sys_ret a)
static bool enough_rpc_stack(struct tcb *t)
{
/* get top of call stack */
- vm_t top = RPC_STACK_BASE + __call_stack_size;
- /* get start of the next rpc stack instance */
- vm_t rpc_stack = t->rpc_stack + BASE_PAGE_SIZE;
+ vm_t top = rpc_position(t);
/* if we can still fit an rpc stack into the call stack, we can safely
* do the migration. */
- return top - rpc_stack >= __rpc_stack_size;
+ return (top - BASE_PAGE_SIZE) >= (t->rpc_stack - __rpc_stack_size);
}
/**
@@ -263,8 +215,7 @@ static void do_ipc(struct tcb *t,
if (unlikely(!enough_rpc_stack(t)))
return_args1(t, ERR_OOMEM);
- struct stack_diff sd =
- enter_rpc(t, SYS_RET6(OK, t->eid, d0, d1, d2, d3), kind);
+ vm_t s = enter_rpc(t, SYS_RET6(OK, t->eid, d0, d1, d2, d3), kind);
struct tcb *r = get_tcb(pid);
if (unlikely(!r)) {
@@ -282,7 +233,7 @@ static void do_ipc(struct tcb *t,
if (kind != IPC_REQ)
t->eid = t->pid;
- finalize_rpc(t, r, sd);
+ finalize_rpc(t, r, s);
/* I tested out passing the return values as arguments to
* ret_userspace_fast, but apparently that causes enough stack shuffling
* to be slower overall. */