aboutsummaryrefslogtreecommitdiff
path: root/common/uapi
diff options
context:
space:
mode:
Diffstat (limited to 'common/uapi')
-rw-r--r--common/uapi/conf.c16
-rw-r--r--common/uapi/ipc.c69
2 files changed, 11 insertions, 74 deletions
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. */