aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-11-13 17:16:28 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2022-11-13 17:16:28 +0200
commit1a0188fac0c0f265c4495b83592389b8b3645462 (patch)
treec1687724dd7f7ccf6d9d0d134c2766f14d3e39f5
parente6dc962ef7758c438039d7f8ac7e2bf3ebcb5c10 (diff)
downloadkmi-1a0188fac0c0f265c4495b83592389b8b3645462.tar.gz
kmi-1a0188fac0c0f265c4495b83592389b8b3645462.zip
outline rpc stack handling
-rw-r--r--common/tcb.c23
-rw-r--r--common/uapi/conf.c62
-rw-r--r--common/uapi/ipc.c3
-rw-r--r--include/apos/caps.h5
-rw-r--r--include/apos/conf.h14
-rw-r--r--include/apos/tcb.h8
6 files changed, 109 insertions, 6 deletions
diff --git a/common/tcb.c b/common/tcb.c
index 5121940..afc8442 100644
--- a/common/tcb.c
+++ b/common/tcb.c
@@ -432,7 +432,8 @@ void save_context(struct tcb *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? */
+ * 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);
@@ -443,8 +444,20 @@ void save_context(struct tcb *t)
ctx->regs = t->regs;
ctx->rpc_stack = rpc_stack;
+ /** @todo if we run out of rpc_stack space we should just stop, likely
+ * return a status? */
rpc_stack -= BASE_PAGE_SIZE;
+ /** @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
+ * configurable number as well, might actually use the config subsystem
+ * :D
+ * In such a case it would probably be smarter to mark all pages
+ * inaccessible at first, and then mark the first page accessible. If
+ * the process needs more stack space it'll cause a paging exception,
+ * we'll handle it separately and if the process isn't going over the
+ * limit just give it more.
+ * */
mark_rpc_inaccessible(t, rpc_stack, t->rpc_stack);
t->rpc_stack = rpc_stack;
t->regs = (vm_t)ctx;
@@ -461,3 +474,11 @@ void load_context(struct tcb *t)
t->eid = ctx->eid;
t->regs = ctx->regs;
}
+
+bool enough_rpc_stack(struct tcb *t)
+{
+ vm_t top = RPC_STACK_BASE + __call_stack_size;
+ vm_t rpc_stack = t->rpc_stack + BASE_PAGE_SIZE;
+
+ return top - rpc_stack >= __call_stack_size / 4;
+}
diff --git a/common/uapi/conf.c b/common/uapi/conf.c
index 2094604..596cb5c 100644
--- a/common/uapi/conf.c
+++ b/common/uapi/conf.c
@@ -16,6 +16,15 @@
* 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,
+};
/**
* Configuration parameter read syscall handler.
@@ -27,7 +36,29 @@ size_t __call_stack_size = SZ_2M;
*/
SYSCALL_DEFINE1(conf_get)(sys_arg_t param)
{
- return SYS_RET1(OK);
+ struct tcb *t = cur_tcb();
+ if (!has_cap(t->caps, CAP_CONF))
+ return SYS_RET1(ERR_PERM);
+
+ long val = 0;
+ switch (param) {
+ case CONF_THREAD_STACK:
+ val = __thread_stack_size;
+ break;
+
+ case CONF_CALL_STACK:
+ val = __call_stack_size;
+ break;
+
+ case CONF_RPC_STACK:
+ val = __rpc_stack_size;
+ break;
+
+ default:
+ return SYS_RET1(ERR_NF);
+ }
+
+ return SYS_RET2(OK, val);
}
/**
@@ -41,9 +72,32 @@ SYSCALL_DEFINE1(conf_get)(sys_arg_t param)
*/
SYSCALL_DEFINE2(conf_set)(sys_arg_t param, sys_arg_t val)
{
- UNUSED(param);
- UNUSED(val);
- /* no parameters supported atm */
+ struct tcb *t = cur_tcb();
+ if (!has_cap(t->caps, CAP_CONF))
+ return SYS_RET1(ERR_PERM);
+
+ size_t size = 0;
+ switch (param) {
+ case CONF_THREAD_STACK:
+ __thread_stack_size = align_up(val, BASE_PAGE_SIZE);
+ break;
+
+ case CONF_CALL_STACK:
+ size = align_up(val, 4 * BASE_PAGE_SIZE);
+ if (size < __rpc_stack_size * 4)
+ return 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 / 4)
+ return SYS_RET1(ERR_MISC);
+
+ __rpc_stack_size = size;
+ break;
+ }
return SYS_RET1(OK);
}
diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c
index 052e0ad..5d91588 100644
--- a/common/uapi/ipc.c
+++ b/common/uapi/ipc.c
@@ -41,6 +41,9 @@ static struct sys_ret do_ipc(sys_arg_t pid,
bool fwd)
{
struct tcb *t = cur_tcb();
+ if (!enough_rpc_stack(t))
+ return SYS_RET1(ERR_OOMEM);
+
struct tcb *r = get_tcb(pid);
if (!r)
return SYS_RET1(ERR_INVAL);
diff --git a/include/apos/caps.h b/include/apos/caps.h
index be64663..e762d0f 100644
--- a/include/apos/caps.h
+++ b/include/apos/caps.h
@@ -20,7 +20,7 @@ enum {
/** Thread is allowed to set capabilities of other threads. */
CAP_CAPS = (1 << 0),
- /** Thread is allowed to modify process statuses, exec/fork/etc. */
+ /** Thread is allowed to modify process statuses, create/exec/fork/etc. */
CAP_PROC = (1 << 1),
/** Thread is allowed to force interrupt to callback in other thread. */
@@ -28,6 +28,9 @@ enum {
/** Thread is allowed to shut down system. */
CAP_POWER = (1 << 3),
+
+ /** Thread is allowed to access configuration parameters. */
+ CAP_CONF = (1 << 4),
};
/**
diff --git a/include/apos/conf.h b/include/apos/conf.h
index 467b1e3..33fa8e5 100644
--- a/include/apos/conf.h
+++ b/include/apos/conf.h
@@ -23,10 +23,24 @@ extern size_t __thread_stack_size;
/**
* Provides access to the runtime global parameter.
+ * Must be at most RPC_STACK_TOP - RPC_STACK_BASE.
+ *
* \see __thread_stack_size.
* \global
* \todo This should probably also be a function instead.
*/
extern size_t __call_stack_size;
+/**
+ * Provides access to the runtime global parameter. This sets the maximum size
+ * a single rpc stack instance can be.
+ *
+ * Must be at most a fourth of \ref __call_stack_size?
+ * (that way we can maybe pretty quickly check that we're running out of memory
+ * for stack stuff and can return an error about it)
+ *
+ * \global
+ */
+extern size_t __rpc_stack_size;
+
#endif /* APOS_CONF_H */
diff --git a/include/apos/tcb.h b/include/apos/tcb.h
index 6097153..981f352 100644
--- a/include/apos/tcb.h
+++ b/include/apos/tcb.h
@@ -389,4 +389,12 @@ void save_context(struct tcb *t);
*/
void load_context(struct tcb *t);
+/**
+ * Check that we have enough rpc stack.
+ *
+ * @param t Thread whose rpc stack to check.
+ * @return \ref true if we have enough, \ref false otherwise.
+ */
+bool enough_rpc_stack(struct tcb *t);
+
#endif /* APOS_TCB_H */