aboutsummaryrefslogtreecommitdiff
path: root/src/uapi
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-08-22 14:57:14 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-08-22 14:57:14 +0300
commitc3ea570bae8f7daeac8e0614a958e983fcf9940e (patch)
treea6060c571a2ce715037f98df139562cb161cf91e /src/uapi
parentfcd4d35ab52e26942f7adbd555be4d563ad06980 (diff)
downloadkmi-c3ea570bae8f7daeac8e0614a958e983fcf9940e.tar.gz
kmi-c3ea570bae8f7daeac8e0614a958e983fcf9940e.zip
add ipc_notify testcase, remove ipc_ghost
+ A bit easier to implement just ignoring the ipc_resp() arguments than try to enforce that a notification is exited from by ipc_ghost(), especially in cases where the root process has been killed.
Diffstat (limited to 'src/uapi')
-rw-r--r--src/uapi/dispatch.c3
-rw-r--r--src/uapi/ipc.c35
2 files changed, 15 insertions, 23 deletions
diff --git a/src/uapi/dispatch.c b/src/uapi/dispatch.c
index 399f02b..859543a 100644
--- a/src/uapi/dispatch.c
+++ b/src/uapi/dispatch.c
@@ -65,9 +65,8 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
case SYS_IPC_TAIL: sys_ipc_tail(t, a, b, c, d, e); break;
case SYS_IPC_KICK: sys_ipc_kick(t, a, b, c, d, e); break;
case SYS_IPC_RESP: sys_ipc_resp(t, a, b, c, d, e); break;
- case SYS_IPC_GHOST: sys_ipc_ghost(t, a, b, c, d, e); break;
+ case SYS_IPC_NOTIFY: sys_ipc_notify(t, a, b, c, d, e); break;
case SYS_SET_HANDLER: sys_set_handler(t, a, b, c, d, e); break;
- case SYS_NOTIFY: sys_notify(t, a, b, c, d, e); break;
case SYS_CREATE: sys_create(t, a, b, c, d, e); break;
case SYS_FORK: sys_fork(t, a, b, c, d, e); break;
case SYS_EXEC: sys_exec(t, a, b, c, d, e); break;
diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c
index 3d77639..850178c 100644
--- a/src/uapi/ipc.c
+++ b/src/uapi/ipc.c
@@ -31,6 +31,10 @@ struct call_ctx {
/** 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;
};
/**
@@ -51,7 +55,8 @@ enum ipc_flags {
* process. */
IPC_TAIL = (1 << 0),
/** Don't update the effective ID. */
- IPC_FORWARD = (1 << 1)
+ IPC_FORWARD = (1 << 1),
+ IPC_NOTIFY = (1 << 2),
};
/**
@@ -102,6 +107,7 @@ static inline vm_t enter_rpc(struct tcb *t, struct sys_ret a,
ctx->exec = t->exec;
ctx->pid = t->pid;
ctx->eid = t->eid;
+ ctx->notify = flags & IPC_NOTIFY;
ctx->rpc_stack = rpc_stack;
/** @todo if we run out of rpc_stack space we should just stop, likely
@@ -173,7 +179,7 @@ static __noreturn void __run_notify(struct tcb *t, struct tcb *r)
* ("pid 0"), and we are notifying the current thread */
vm_t s = enter_rpc(t,
SYS_RET5(0, t->tid, code, flags, t->eid),
- 0);
+ IPC_NOTIFY);
finalize_rpc(t, r, s);
@@ -239,7 +245,8 @@ static void leave_rpc(struct tcb *t, struct sys_ret a)
t->regs = ctx->regs;
/* again, get rid of args as fast as possible */
- set_ret(t, 6, a);
+ if (!ctx->notify)
+ set_ret(t, 6, a);
struct tcb *r = get_tcb(ctx->pid);
while (!r || !is_proc(r) || zombie(r)) {
@@ -252,12 +259,13 @@ 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;
r = get_tcb(ctx->pid);
/* equivalent to return_args1 but without returning so we can
* handle other cases in the loop. */
- /** @todo is set_args useful? */
- set_ret2(t, 0, ERR_NF);
+ if (!ctx->notify)
+ set_args1(t, ERR_NF);
}
if (orphan(t) && !is_rpc(t))
@@ -442,21 +450,6 @@ SYSCALL_DEFINE4(ipc_resp)(struct tcb *t, sys_arg_t d0, sys_arg_t d1,
}
/**
- * Ghost return, resetting register state.
- *
- * @param t Current tcb.
- * @return The previous registers of thread.
- */
-SYSCALL_DEFINE0(ipc_ghost)(struct tcb *t)
-{
- if (unlikely(!is_rpc(t)))
- return_args1(t, ERR_MISC);
-
- enable_irqs();
- leave_rpc(t, get_ret(t));
-}
-
-/**
* Notify syscall handler.
*
* \todo Implement.
@@ -465,7 +458,7 @@ SYSCALL_DEFINE0(ipc_ghost)(struct tcb *t)
* @param tid Thread ID to notify.
* @return \ref OK and 0.
*/
-SYSCALL_DEFINE1(notify)(struct tcb *t, sys_arg_t tid){
+SYSCALL_DEFINE1(ipc_notify)(struct tcb *t, sys_arg_t tid){
if (t->tid != tid && !has_cap(t->caps, CAP_NOTIFY))
return_args1(t, ERR_PERM);