aboutsummaryrefslogtreecommitdiff
path: root/common/uapi
diff options
context:
space:
mode:
Diffstat (limited to 'common/uapi')
-rw-r--r--common/uapi/cap.c94
-rw-r--r--common/uapi/conf.c115
-rw-r--r--common/uapi/dispatch.c89
-rw-r--r--common/uapi/ipc.c348
-rw-r--r--common/uapi/irq.c29
-rw-r--r--common/uapi/mem.c158
-rw-r--r--common/uapi/proc.c188
-rw-r--r--common/uapi/timers.c120
8 files changed, 0 insertions, 1141 deletions
diff --git a/common/uapi/cap.c b/common/uapi/cap.c
deleted file mode 100644
index 157ef47..0000000
--- a/common/uapi/cap.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2023 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-#include <kmi/uapi.h>
-#include <kmi/caps.h>
-#include <kmi/tcb.h>
-
-/**
- * @file cap.c
- * Sycalls handlers for thread capabilities.
- */
-
-/**
- * Check that values are legal for thread ID and offset.
- *
- * @param tid Thread ID of thread whose caps should be fetched.
- * @param off Offset of capabilities.
- * @return Pointer to capabilities of \p tid, \c 0 otherwise.
- */
-static capflags_t *__get_tcb_caps(id_t tid, size_t off)
-{
- if (!cap_off_ok(off))
- return NULL;
-
- struct tcb *t = get_tcb(tid);
- if (!t)
- return NULL;
-
- return &t->caps;
-}
-
-/**
- * Set capabilities.
- *
- * @param t Current tcb.
- * @param tid Thread ID whose capabilities to set.
- * @param off Offset of capability, multiple of \c bits(cap).
- * @param caps Mask of capabilities to set.
- * @return \ref OK on success, \ref ERR_INVAL on invalid input.
- */
-SYSCALL_DEFINE3(set_cap)(struct tcb *t, sys_arg_t tid, sys_arg_t off,
- sys_arg_t caps)
-{
- if (!is_set(t->caps, CAP_CAPS))
- return_args1(t, ERR_PERM);
-
- capflags_t *c;
- if (!(c = __get_tcb_caps(tid, off)))
- return_args1(t, ERR_INVAL);
-
- set_caps(*c, off, caps);
- return_args1(t, OK);
-}
-
-/**
- * Get capabilities.
- *
- * @param t Current tcb.
- * @param tid Thread ID whose capabilities to get.
- * @param off Offset of capability, multiple of \c bits(cap).
- * @return \ref OK, capabilities.
- */
-SYSCALL_DEFINE2(get_cap)(struct tcb *t, sys_arg_t tid, sys_arg_t off)
-{
- capflags_t *c;
- if (!(c = __get_tcb_caps(tid, off)))
- return_args1(t, ERR_INVAL);
-
- return_args2(t, OK, get_caps(*c, off));
-}
-
-/**
- * Clear capabilities.
- *
- * @param t Current tcb.
- * @param tid Thread ID whose capabilities to clear.
- * @param off Offset of capability, multiple of \c bits(cap).
- * @param caps Mask of capabilities to clear.
- * @return ERR_LERM if invalid permissions, ERR_INVAL if \p tid doesn't exist,
- * otherwise OK.
- */
-SYSCALL_DEFINE3(clear_cap)(struct tcb *t, sys_arg_t tid, sys_arg_t off,
- sys_arg_t caps)
-{
- if (!is_set(t->caps, CAP_CAPS))
- return_args1(t, ERR_PERM);
-
- capflags_t *c;
- if (!(c = __get_tcb_caps(tid, off)))
- return_args1(t, ERR_INVAL);
-
- clear_caps(*c, off, caps);
- return_args1(t, OK);
-}
diff --git a/common/uapi/conf.c b/common/uapi/conf.c
deleted file mode 100644
index 894b98a..0000000
--- a/common/uapi/conf.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * @file conf.c
- * Runtime configuration sycall implementations.
- *
- * At the moment there are not runtime configuration parameters.
- */
-
-#include <kmi/power.h>
-#include <kmi/sizes.h>
-#include <kmi/uapi.h>
-#include <kmi/conf.h>
-
-#include <arch/proc.h>
-
-/** \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 __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_RPC_STACK,
-};
-
-/**
- * Configuration parameter read syscall handler.
- *
- * \todo Implement parameters.
- *
- * @param t Current tcb.
- * @param param Parameter to read.
- * @return \ref OK and parameter value.
- */
-SYSCALL_DEFINE1(conf_get)(struct tcb *t, sys_arg_t param)
-{
- if (!has_cap(t->caps, CAP_CONF))
- return_args1(t, ERR_PERM);
-
- long val = 0;
- switch (param) {
- case CONF_THREAD_STACK:
- val = __thread_stack_size;
- break;
-
- case CONF_RPC_STACK:
- val = __rpc_stack_size;
- break;
-
- default:
- return_args1(t, ERR_NF);
- }
-
- return_args2(t, OK, val);
-}
-
-/**
- * Configuration parameter write syscall handler.
- *
- * \todo Implement parameters.
- *
- * @param t Current tcb.
- * @param param Parameter to write.
- * @param val Value to set \c param to.
- * @return \ref OK and \c 0.
- */
-SYSCALL_DEFINE2(conf_set)(struct tcb *t, sys_arg_t param, sys_arg_t val)
-{
- if (!has_cap(t->caps, CAP_CONF))
- return_args1(t, ERR_PERM);
-
- size_t size = 0;
- switch (param) {
- case CONF_THREAD_STACK:
- __thread_stack_size = align_up(val, BASE_PAGE_SIZE);
- break;
-
- case CONF_RPC_STACK:
- size = align_up(val, BASE_PAGE_SIZE);
- if (size > max_rpc_size())
- return_args1(t, ERR_MISC);
-
- __rpc_stack_size = size;
- break;
- }
-
- return_args1(t, OK);
-}
-
-/**
- * Poweroff syscall handler.
- *
- * @param t Current tcb.
- * @param type Type of poweroff.
- * @return \ref ERR_INVAL and \c 0 if incorrect poweroff \c type give, otherwise
- * does not return.
- */
-SYSCALL_DEFINE1(poweroff)(struct tcb *t, sys_arg_t type)
-{
- if (!(has_cap(t->caps, CAP_POWER)))
- return_args1(t, ERR_PERM);
-
- switch (type) {
- case SHUTDOWN:
- case COLD_REBOOT:
- case WARM_REBOOT:
- return_args2(t, OK, poweroff(type));
- };
-
- return_args1(t, ERR_INVAL);
-}
diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c
deleted file mode 100644
index 5b523cc..0000000
--- a/common/uapi/dispatch.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * @file dispatch.c
- * Syscall dispatch.
- */
-
-#include <kmi/canary.h>
-#include <kmi/debug.h>
-#include <kmi/uapi.h>
-
-/* not sure why doxygen requires these two definitions to state their return
- * values, when they don't actually return anything but eh */
-
-/**
- * Noop syscall handler.
- *
- * @param t Current tcb.
- *
- * @return \ref OK and \c 0.
- */
-SYSCALL_DEFINE0(noop)(struct tcb *t)
-{
- info("sys_noop\n");
- set_args1(t, OK);
-}
-
-/**
- * Putch syscall handler.
- *
- * @param t Current tcb.
- * @param a Character to put.
- *
- * @return \ref OK and 0.
- */
-SYSCALL_DEFINE1(putch)(struct tcb *t, sys_arg_t a)
-{
- dbg("%c", (char)a);
- set_args1(t, OK);
-}
-
-void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b,
- sys_arg_t c, sys_arg_t d, sys_arg_t e, struct tcb *t)
-{
- adjust_syscall(t);
-
- switch (syscall) {
- case SYS_NOOP: sys_noop(t, a, b, c, d, e); break;
- case SYS_PUTCH: sys_putch(t, a, b, c, d, e); break;
- case SYS_REQ_MEM: sys_req_mem(t, a, b, c, d, e); break;
- case SYS_REQ_PAGE: sys_req_page(t, a, b, c, d, e); break;
- case SYS_REQ_PMEM: sys_req_pmem(t, a, b, c, d, e); break;
- case SYS_REQ_FIXMEM: sys_req_fixmem(t, a, b, c, d, e); break;
- case SYS_REQ_SHAREDMEM: sys_req_sharedmem(t, a, b, c, d, e); break;
- case SYS_FREE_MEM: sys_free_mem(t, a, b, c, d, e); break;
- case SYS_TIMEBASE: sys_timebase(t, a, b, c, d, e); break;
- case SYS_TICKS: sys_ticks(t, a, b, c, d, e); break;
- case SYS_REQ_REL_TIMER: sys_req_rel_timer(t, a, b, c, d, e); break;
- case SYS_REQ_ABS_TIMER: sys_req_abs_timer(t, a, b, c, d, e); break;
- case SYS_IPC_SERVER: sys_ipc_server(t, a, b, c, d, e); break;
- case SYS_IPC_REQ: sys_ipc_req(t, a, b, c, d, e); break;
- case SYS_IPC_FWD: sys_ipc_fwd(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_NOTIFY: sys_ipc_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;
- case SYS_SPAWN: sys_spawn(t, a, b, c, d, e); break;
- case SYS_KILL: sys_kill(t, a, b, c, d, e); break;
- case SYS_SWAP: sys_swap(t, a, b, c, d, e); break;
- case SYS_CONF_SET: sys_conf_set(t, a, b, c, d, e); break;
- case SYS_CONF_GET: sys_conf_get(t, a, b, c, d, e); break;
- case SYS_SET_CAP: sys_set_cap(t, a, b, c, d, e); break;
- case SYS_GET_CAP: sys_get_cap(t, a, b, c, d, e); break;
- case SYS_CLEAR_CAP: sys_clear_cap(t, a, b, c, d, e); break;
- case SYS_POWEROFF: sys_poweroff(t, a, b, c, d, e); break;
- case SYS_IRQ_REQ: sys_irq_req(t, a, b, c, d, e); break;
- default:
- error("Syscall %zu outside allowed range [0 - %i]\n", syscall,
- SYS_NUM - 1);
- set_args1(t, ERR_INVAL);
- };
-
- if (check_canary(t)) {
- bug("Syscall %zu overwrote stack canary\n", syscall);
- }
-}
diff --git a/common/uapi/ipc.c b/common/uapi/ipc.c
deleted file mode 100644
index cb2ce28..0000000
--- a/common/uapi/ipc.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * @file ipc.c
- * Interprocess communication syscall implementations.
- */
-
-#include <kmi/uapi.h>
-#include <kmi/tcb.h>
-#include <kmi/ipi.h>
-#include <kmi/conf.h>
-
-/** Structure for maintaining the required context data for an rpc call. */
-struct call_ctx {
- /** Execution continuation point. */
- vm_t exec;
-
- /** Register save area. */
- vm_t regs;
-
- /** Position in rpc stack. */
- vm_t rpc_stack;
-
- /** Effective process ID. */
- id_t eid;
-
- /** Current process ID. */
- id_t pid;
-
- /** Whether this context should be skipped when responding. */
- bool kick;
-};
-
-/**
- * Represents difference between where rpc stack was before rpc call and during.
- * Used to figure out which areas should be marked inaccessible.
- */
-struct stack_diff {
- /** Current stack start. Keep in mind that stacks grow down. */
- vm_t start;
- /** Difference end, i.e. previous stack start. */
- vm_t end;
-};
-
-/** Enumerator for IPC kind. Used by do_ipc(). */
-enum ipc_kind {
- IPC_REQ, IPC_FWD, IPC_KICK
-};
-
-/**
- * Now that we know we're doing an rpc, clone virtual memories and do
- * the slow stuff.
- *
- * @param t Thread to migrate.
- * @param r Process to migrate to.
- * @param s RPC stack regions to mark inaccessible.
- */
-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);
- reference_proc(r);
- t->pid = r->rid;
-
- /* make sure updates are visible when swapping to the new virtual memory */
- mark_rpc_invalid(t, s);
- use_vmem(t->rpc.vmem);
-}
-
-/**
- * Optimistically assume we're going to take the rpc and do some preparations
- * for it. Most notably, write the arguments as early as possible to
- * free up registers for the compiler to play with.
- *
- * @param t Thread to migrate.
- * @param a RPC arguments.
- * @param kind Kind of IPC we're doing. Essentially toggles kick boolean.
- * @return RPC stack difference that should be passed to finalize_rpc().
- */
-static vm_t enter_rpc(struct tcb *t, struct sys_ret a,
- enum ipc_kind kind)
-{
- vm_t rpc_stack = rpc_position(t);
-
- struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
- ctx->regs = t->regs;
- t->regs = (vm_t)ctx;
-
- /* try to get rid of args as fast as possible to free up registers for
- * later use */
- set_args(t, 6, a);
-
- ctx->exec = t->exec;
- ctx->pid = t->pid;
- ctx->eid = t->eid;
- ctx->rpc_stack = rpc_stack;
-
- /* only rpcs can be kicked forward */
- ctx->kick = kind == IPC_KICK && is_rpc(t);
-
- /** @todo if we run out of rpc_stack space we should just stop, likely
- * return a status? except it shouldn't happen after we've run
- * enough_rpc_stack(). */
- vm_t new_stack = 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.
- * */
- t->rpc_stack = new_stack;
- set_stack(t, new_stack);
- return new_stack;
-}
-
-/**
- * Jump back to process where rpc came from, assuming such a thing exists.
- *
- * @param t Thread to do return migration on.
- * @param a Arguments to pass along.
- */
-static void leave_rpc(struct tcb *t, struct sys_ret a)
-{
- vm_t rpc_stack = t->rpc_stack + BASE_PAGE_SIZE;
- struct call_ctx *ctx = (struct call_ctx *)(rpc_stack) - 1;
- vm_t top = ctx->rpc_stack;
-
- /* find first instance of not kicked context */
- while (ctx->kick) {
- rpc_stack = ctx->rpc_stack + BASE_PAGE_SIZE;
- ctx = (struct call_ctx *)(rpc_stack) - 1;
- unreference_proc(get_tcb(ctx->pid));
- }
-
- t->regs = ctx->regs;
- /* again, get rid of args as fast as possible */
- set_args(t, 6, a);
-
- set_return(t, ctx->exec);
- /* if we're returning from a failed rpc, this should essentially be a
- * no-op */
- mark_rpc_valid(t, top);
- t->rpc_stack = ctx->rpc_stack;
- t->pid = ctx->pid;
- t->eid = ctx->eid;
-
- if (is_rpc(t))
- use_vmem(t->rpc.vmem);
- else
- use_vmem(t->proc.vmem);
-}
-
-/**
- * Check that there's enough stack left for an rpc invocation.
- *
- * @param t Thread whose migration to check.
- * @return \c true if there's enough stack left to safely do migration,
- * \c false otherwise.
- */
-static bool enough_rpc_stack(struct tcb *t)
-{
- /* get top of call stack */
- 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 - BASE_PAGE_SIZE - __rpc_stack_size >= RPC_STACK_BASE;
-}
-
-/**
- * IPC server notification syscall handler.
- *
- * @param t Current tcb.
- * @param callback Address of server callback.
- * @return \ref OK and \c 0.
- */
-SYSCALL_DEFINE1(ipc_server)(struct tcb *t, sys_arg_t callback)
-{
- get_cproc(t)->callback = callback;
- return_args1(t, OK);
-}
-
-/**
- * Actual IPC syscall handler.
- *
- * @param t Current tcb.
- * @param pid Process to request RPC to.
- * @param d0 IPC argument 0.
- * @param d1 IPC argument 1.
- * @param d2 IPC argument 2.
- * @param d3 IPC argument 3.
- * @param kind Which kind of IPC to perform.
- *
- * Returns \ref ERR_OOMEM if there isn't enough IPC stack left, \ref ERR_INVAL
- * if the the target process doesn't exist, \ref ERR_NOINIT if the target
- * process hasn't defined a callback. Otherwise \ref OK and whatever the target
- * process sends back.
- *
- * @todo should all static functions have double underscores? I seem to be
- * inconsistent.
- */
-static void do_ipc(struct tcb *t,
- sys_arg_t pid,
- sys_arg_t d0,
- sys_arg_t d1,
- sys_arg_t d2,
- sys_arg_t d3,
- enum ipc_kind kind)
-{
- if (unlikely(!enough_rpc_stack(t)))
- return_args1(t, ERR_OOMEM);
-
- vm_t s = enter_rpc(t, SYS_RET6(t->eid, t->tid, d0, d1, d2, d3), kind);
-
- struct tcb *r = get_tcb(pid);
- if (unlikely(!r)) {
- leave_rpc(t, SYS_RET1(ERR_INVAL));
- return;
- }
-
- r = get_rproc(r);
- if (unlikely(r->dead)) {
- leave_rpc(t, SYS_RET1(ERR_INVAL));
- return;
- }
-
- if (unlikely(!r->callback)) {
- leave_rpc(t, SYS_RET1(ERR_NOINIT));
- return;
- }
-
- if (kind != IPC_REQ)
- t->eid = t->pid;
-
- 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. */
- ret_userspace_fast();
-}
-/**
- * IPC request syscall handler.
- *
- * @param t Current tcb.
- * @param pid Process to request RPC to.
- * @param d0 IPC argument 0.
- * @param d1 IPC argument 1.
- * @param d2 IPC argument 2.
- * @param d3 IPC argument 3.
- * @return When succesful: OK, thread id of the caller and the arguments as-is.
- */
-SYSCALL_DEFINE5(ipc_req)(struct tcb *t, sys_arg_t pid,
- sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3)
-{
- do_ipc(t, pid, d0, d1, d2, d3, IPC_REQ);
-}
-
-/**
- * IPC forwarding syscall handler.
- *
- * @param t Current tcb.
- * @param pid Process to request RPC to.
- * @param d0 IPC argument 0.
- * @param d1 IPC argument 1.
- * @param d2 IPC argument 2.
- * @param d3 IPC argument 3.
- * @return When succesful: OK, thread id of the caller and the arguments as-is.
- */
-SYSCALL_DEFINE5(ipc_fwd)(struct tcb *t, sys_arg_t pid,
- sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3)
-{
- do_ipc(t, pid, d0, d1, d2, d3, IPC_FWD);
-}
-
-/**
- * IPC kicking syscall handler.
- *
- * @param t Current tcb.
- * @param pid Process to request RPC to.
- * @param d0 IPC argument 0.
- * @param d1 IPC argument 1.
- * @param d2 IPC argument 2.
- * @param d3 IPC argument 3.
- * @return When succesful: OK, thread id of the caller and the arguments as-is.
- */
-SYSCALL_DEFINE5(ipc_kick)(struct tcb *t, sys_arg_t pid,
- sys_arg_t d0, sys_arg_t d1, sys_arg_t d2,
- sys_arg_t d3)
-{
- do_ipc(t, pid, d0, d1, d2, d3, IPC_KICK);
-}
-
-/**
- * IPC response syscall handler.
- *
- * @param t Current tcb.
- * @param d0 IPC return value 0.
- * @param d1 IPC return value 1.
- * @param d2 IPC return value 2.
- * @param d3 IPC return value 3.
- * @return \c d0 and \c d1.
- */
-SYSCALL_DEFINE4(ipc_resp)(struct tcb *t, sys_arg_t d0, sys_arg_t d1,
- sys_arg_t d2,
- sys_arg_t d3)
-{
- /* if we're not in an rpc, the user messed something up. */
- /** @todo choose or come up with more fitting error value. */
- if (unlikely(!is_rpc(t)))
- return_args1(t, ERR_MISC);
-
- leave_rpc(t, SYS_RET6(OK, t->tid, d0, d1, d2, d3));
-}
-
-/**
- * Notify syscall handler.
- *
- * \todo Implement.
- *
- * @param t Current tcb.
- * @param tid Thread ID to notify.
- * @return \ref OK and 0.
- */
-SYSCALL_DEFINE1(ipc_notify)(struct tcb *t, sys_arg_t tid){
- if (!has_cap(t->caps, CAP_CALL))
- return_args1(t, ERR_PERM);
-
- struct tcb *r = get_tcb(tid);
- if (r->notify_state == NOTIFY_QUEUED)
- return_args1(t, OK);
-
- if (r->notify_state == NOTIFY_RUNNING) {
- t->notify_state = NOTIFY_QUEUED;
- return_args1(t, OK);
- }
-
- r->notify_state = NOTIFY_QUEUED;
- if (running(r))
- send_ipi(r);
-
- return_args1(t, OK);
-}
diff --git a/common/uapi/irq.c b/common/uapi/irq.c
deleted file mode 100644
index 6687826..0000000
--- a/common/uapi/irq.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2023, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * @file irq.c
- * IRQ request syscall handling implementation.
- */
-
-#include <kmi/uapi.h>
-#include <kmi/irq.h>
-
-/**
- * Actual IRQ handling request syscall handler.
- *
- * @param t Current tcb.
- * @param id IRQ id to request to handle.
- *
- * @return OK on success, non-zero otherwise.
- */
-SYSCALL_DEFINE1(irq_req)(struct tcb *t, sys_arg_t id)
-{
- if (!has_cap(t->caps, CAP_IRQ))
- return_args1(t, ERR_PERM);
-
- if (!t->callback)
- return_args1(t, ERR_NF);
-
- return_args1(t, register_irq(t, id));
-}
diff --git a/common/uapi/mem.c b/common/uapi/mem.c
deleted file mode 100644
index d54390a..0000000
--- a/common/uapi/mem.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * @file mem.c
- * Memory handling syscall implementations.
- * \todo Should we return more error information?
- */
-
-#include <kmi/uapi.h>
-#include <kmi/utils.h>
-#include <kmi/vmem.h>
-#include <kmi/dmem.h>
-
-/**
- * Memory request syscall handler.
- *
- * @param t Current tcb.
- * @param size Minimum size of allocation.
- * @param flags Flags of allocation.
- * @return \ref OK and start of allocation when succesful,
- * \ref ERR_OOMEM and \c NULL otherwise.
- */
-SYSCALL_DEFINE2(req_mem)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
-{
- struct tcb *r = get_cproc(t);
- vm_t start = 0;
- /** @todo expose flags to users */
- if (!(start = alloc_uvmem(r, size, flags)))
- return_args1(t, ERR_OOMEM);
-
- return_args2(t, OK, start);
-}
-
-/**
- * Allocate single page to program.
- *
- * @param t Current tcb.
- * @param size Size of the allocation.
- * @param flags Flags of allocation.
- * @return \ref ERR_OOMEM if unsucessful, otherwise \ref OK, virtual address,
- * actual size, physical address, in that order.
- */
-SYSCALL_DEFINE2(req_page)(struct tcb *t, sys_arg_t size, sys_arg_t flags)
-{
- struct tcb *r = get_cproc(t);
- vm_t start = 0; pm_t paddr = 0; size_t asize = size;
- if (!(start = alloc_uvpage(r, asize, flags, &asize, &paddr)))
- return_args1(t, ERR_OOMEM);
-
- return_args4(t, OK, start, asize, paddr);
-}
-
-/**
- * Fixed memory request syscall handler.
- *
- * @param t Current tcb.
- * @param fixed Address which should be included in allocation.
- * @param size Minimum size of allocation after \c start.
- * @param flags Flags of allocation.
- * @return \ref OK and start of allocation when succesful,
- * \ref ERR_OOMEM and \c NULL otherwise.
- */
-SYSCALL_DEFINE3(req_fixmem)(struct tcb *t, sys_arg_t fixed, sys_arg_t size,
- sys_arg_t flags)
-{
- struct tcb *r = get_cproc(t);
- vm_t start = 0;
- if (!(start = alloc_fixed_uvmem(r, fixed, size, flags)))
- return_args1(t, ERR_OOMEM);
-
- return_args2(t, OK, start);
-}
-
-/**
- * Free memory syscall handler.
- *
- * @param t Current tcb.
- * @param start Start of allocation to free.
- * @return \ref OK and \c 0 when succesful, \ref ERR_NF and \c 0 otherwise.
- */
-SYSCALL_DEFINE1(free_mem)(struct tcb *t, sys_arg_t start)
-{
- struct tcb *r = get_cproc(t);
- vm_t vm_start = (vm_t)start;
-
- stat_t status = OK;
- /* try freeing normal user memory first, if that fails, try device
- * memory, otherwise just assume the address is borked. */
- if (!(status = free_uvmem(r, vm_start)))
- return_args1(t, OK);
-
- if (!(status = free_devmem(r, vm_start)))
- return_args1(t, OK);
-
- return_args1(t, status);
-}
-
-/**
- * Request physical memory syscall handler.
- *
- * @param t Current tcb.
- * @param paddr Physical address to map.
- * @param size Minimum size of allocation.
- * @param flags Flags of allocation.
- * @return \ref OK and start of allocation when succesful,
- * \ref ERR_OOMEM and \c NULL otherwise.
- */
-SYSCALL_DEFINE3(req_pmem)(struct tcb *t, sys_arg_t paddr, sys_arg_t size,
- sys_arg_t flags)
-{
- /* this will require some pondering, but essentially this syscall should
- * only be used for device access, so any addresses requested should be
- * outside the RAM area, and I'll probably have to implement some method
- * that keeps track of used regions outside of RAM. We'll see.
- */
- struct tcb *r = get_cproc(t);
- vm_t start = 0;
- if (!(start = alloc_devmem(r, paddr, size, flags)))
- return_args1(t, ERR_OOMEM);
-
- return_args2(t, OK, start);
-}
-
-/**
- * Request shared memory syscall handler.
- *
- * @param t Current tcb.
- * @param tid Thread to share memory with.
- * @param size Minimum size of allocation.
- * @param sflags Flags of allocation for \p t.
- * @param cflags Flags of allocation for \p tid.
- * @return \ref OK and start of \p t allocation and start of \p tid allocation,
- * in that order, \ref ERR_OOMEM otherwise.
- *
- * @todo should we also take the thread who should get the other end of the
- * memory?
- */
-SYSCALL_DEFINE4(req_sharedmem)(struct tcb *t, sys_arg_t tid,
- sys_arg_t size, sys_arg_t sflags,
- sys_arg_t cflags)
-{
- /** @todo check capability for shared memory */
- struct tcb *u = get_tcb(tid);
- if (!u)
- return_args1(t, ERR_INVAL);
-
- struct tcb *s = get_cproc(t);
- struct tcb *c = get_rproc(u);
-
- vm_t sstart, cstart;
- if (alloc_shared_uvmem(s, c, size, sflags, cflags, &sstart, &cstart))
- return_args1(t, ERR_OOMEM);
-
- return_args3(t, OK, sstart, cstart);
-}
-
-/** \todo add some way to specify who gets to access the shared memory? */
diff --git a/common/uapi/proc.c b/common/uapi/proc.c
deleted file mode 100644
index e7fa49d..0000000
--- a/common/uapi/proc.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * @file proc.c
- * Process/thread handling syscall implementations.
- */
-
-#include <kmi/elf.h>
-#include <kmi/uapi.h>
-#include <kmi/proc.h>
-#include <kmi/bits.h>
-#include <kmi/mem_regions.h>
-
-/**
- * Create syscall handler.
- *
- * @param t Current tcb.
- * @param func Function to jump to at thread creation.
- * @param d0 Argument 0.
- * @param d1 Argument 1.
- * @param d2 Argument 2.
- * @param d3 Argument 3.
- *
- * @return ERR_OOMEM if thread creation was unsuccessful, otherwise OK and the
- * thread id.
- */
-SYSCALL_DEFINE5(create)(struct tcb *t, sys_arg_t func,
- sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3)
-{
- struct tcb *c = create_thread(t);
- if (!c)
- return_args1(t, ERR_OOMEM);
-
- alloc_stack(c);
-
- set_args5(c, c->tid, d0, d1, d2, d3);
- set_return(c, func);
-
- return_args2(t, OK, c->tid);
-}
-
-/**
- * Fork syscall handler.
- *
- * \todo Not entirely sure how I should handle forks/execs etc, mostly whether I
- * should allow forks/execs to be called directly or only though the process
- * manager. Probably though the process manager, although that will add in a
- * slight bit of delay.
- *
- * I suppose I could add in a runtime parameter
- * that would allow them to be called directly, and then the process manager
- * would have to periodically ask the kernel about all threads it is aware of
- * via sys_sync. Dunno.
- *
- * @param t Current tcb.
- * @return \ref OK and 0.
- */
-SYSCALL_DEFINE0(fork)(struct tcb *t)
-{
- struct tcb *c = get_cproc(t);
- if (!(has_cap(c->caps, CAP_PROC)))
- return_args1(t, ERR_PERM);
-
- struct tcb *n = create_proc(get_eproc(t));
- if (!n)
- return_args1(t, ERR_OOMEM);
-
- /* prepare args for when we eventually swap to the new proc, giving
- * parent ID as third return value */
- set_args3(n, OK, 0, get_eproc(t)->pid);
-
- return_args2(t, OK, n->pid);
-}
-
-/**
- * Exec syscall handler.
- *
- * @param t Current tcb.
- * @param bin Binary to execute.
- * @param interp Optional interpreter binary.
- *
- * @return \see prepare_proc().
- */
-SYSCALL_DEFINE2(exec)(struct tcb *t, sys_arg_t bin, sys_arg_t interp)
-{
- /** @todo probably make sure thread is root thread of process? */
- /* mark binary to be kept */
- struct mem_region *b = find_used_region(&t->sp_r, bin);
- if (!b)
- return_args1(t, ERR_INVAL);
-
- set_bit(b->flags, MR_KEEP);
-
- struct mem_region *i = 0;
- if (interp) {
- /* mark interpreter to be kept */
- i = find_used_region(&t->sp_r, interp);
- if (!i)
- return_args1(t, ERR_INVAL);
-
- set_bit(i->flags, MR_KEEP);
- }
-
- /* free everything except regions to be kept */
- clear_uvmem(t);
-
- /* restore to normal */
- clear_bit(b->flags, MR_KEEP);
- if (interp)
- clear_bit(b->flags, MR_KEEP);
-
- return_args1(t, prepare_proc(t, bin, interp));
-}
-
-/**
- * Spawn syscall handler.
- *
- * @param t Current tcb.
- * @param bin Binary to execute.
- * @param interp Optional interpreter binary.
- *
- * @return \see prepare_proc() and process id of the new process.
- */
-SYSCALL_DEFINE2(spawn)(struct tcb *t, sys_arg_t bin, sys_arg_t interp)
-{
- struct tcb *c = get_proc(t);
- if (!(has_cap(c->caps, CAP_PROC)))
- return_args1(t, ERR_PERM);
-
- struct tcb *n = create_proc(NULL);
- if (!n)
- return_args1(t, ERR_OOMEM);
-
- return_args2(t, prepare_proc(n, bin, interp), n->pid);
-}
-
-/**
- * Kill syscall handler.
- *
- * @param t Current tcb.
- * @param tid Thread to kill.
- * \todo Implement.
- *
- * @return ERR_PERM if not capable to kill, otherwise OK.
- */
-SYSCALL_DEFINE1(kill)(struct tcb *t, sys_arg_t tid)
-{
- struct tcb *c = get_cproc(t);
- if (!(has_cap(c->caps, CAP_PROC)))
- return_args1(t, ERR_PERM);
-
- /** @todo implement */
- /** @todo remember to unregister IRQ handlers */
-
- return_args1(t, OK);
-}
-
-/**
- * Swap syscall handler.
- *
- * \todo Implement.
- * \todo Should swap return the registers of the new thread that would be used
- * for message passing?
- *
- * @param t Current tcb.
- * @param tid Thread ID to swap to.
- *
- * @return \ref OK.
- */
-SYSCALL_DEFINE1(swap)(struct tcb *t, sys_arg_t tid){
- struct tcb *c = get_cproc(t);
- if (!(has_cap(c->caps, CAP_PROC)))
- return_args1(t, ERR_PERM);
-
- struct tcb *s = get_tcb(tid);
- if (!s)
- return_args1(t, ERR_INVAL);
-
- /* switch over to new thread */
- use_tcb(s);
-
- /* set return value for current thread */
- set_args1(t, OK);
-
- /* get register state for new thread */
- return_args(s, get_args(s));
-}
diff --git a/common/uapi/timers.c b/common/uapi/timers.c
deleted file mode 100644
index b119fcc..0000000
--- a/common/uapi/timers.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* SPDX-License-Identifier: copyleft-next-0.3.1 */
-/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
-
-/**
- * @file timers.c
- * Timer syscall implementations.
- */
-
-#include <kmi/timer.h>
-#include <kmi/uapi.h>
-
-#include <arch/timer.h>
-
-/**
- * Convert arch-specific register values \p ticks and \p mult to \ref ticks_t.
- *
- * If we're on a 32bit system, one register can't contain a tick value,
- * so we use two registers and combine them into one value and let the compiler
- * handle the rest.
- *
- * @param ticks Register width tick value.
- * @param mult Register width repeat value.
- * @return Corresponding \ref ticks_t value.
- */
-static ticks_t scaled_ticks(sys_arg_t ticks, sys_arg_t mult)
-{
-#if defined(_LP64)
- UNUSED(mult);
- return ticks;
-#else
- return (ticks_t)ticks * (ticks_t)mult;
-#endif
-}
-
-/**
- * Timebase syscall handler.
- *
- * @param t Current tcb.
- * @return \ref OK and timebase in second argument if 64bit, otherwise high 32
- * bits of timebase in second argument and low 32 bits in third argument.
- */
-SYSCALL_DEFINE0(timebase)(struct tcb *t)
-{
- ticks_t tm = secs_to_ticks(1);
-#if defined(_LP64)
- return_args2(t, OK, tm);
-#else
- return_args3(t, OK, tm >> 32, tm);
-#endif
-}
-
-/**
- * Current ticks syscall handler.
- *
- * Note that most platforms allow user level read access to hardware timers, and
- * should be preferred over this syscall on such platforms. Still, for
- * completeness sake.
- *
- * @param t Current tcb.
- * @return \ref OK and the current ticks when on 64bit systems, otherwise high
- * 32 bits of ticks in second argument and low 32 bits in third.
- */
-SYSCALL_DEFINE0(ticks)(struct tcb *t)
-{
- ticks_t tm = current_ticks();
-#if defined(_LP64)
- return_args2(t, OK, tm);
-#else
- return_args3(t, OK, tm >> 32, tm);
-#endif
-}
-
-/**
- * Relative timer request syscall handler.
- *
- * \note On 64bit systems, \p mult is ignored as \p ticks register is large
- * enough to contain essentially any timepoint we want. A couple thousand years
- * when the clock runs at 5GHz, if I'm not completely mistaken.
- *
- * @param t Current tcb.
- * @param ticks Number of ticks from now.
- * @param mult Multiply \c ticks by this value.
- * @return \ref OK and \c cid of created timer.
- */
-SYSCALL_DEFINE2(req_rel_timer)(struct tcb *t, sys_arg_t ticks, sys_arg_t mult)
-{
- return_args2(t, OK, new_rel_timer(t->tid, scaled_ticks(ticks, mult)));
-}
-
-/**
- * Absolute timer request syscall handler.
- *
- * @param t Current tcb.
- * @param ticks Absolute timepoint relative to some start point defined at boot.
- * @param mult Multiply \c ticks by this value.
- * @return \ref OK and \c cid of created timer.
- * \see req_rel_timer().
- */
-SYSCALL_DEFINE2(req_abs_timer)(struct tcb *t, sys_arg_t ticks, sys_arg_t mult)
-{
- return_args2(t, OK, new_abs_timer(t->tid, scaled_ticks(ticks, mult)));
-}
-
-/**
- * Free timer request syscall handler.
- *
- * @param t Current tcb.
- * @param cid \c cid of timer to free.
- * @return \ref ERR_NF and \c 0if no timer could be found with \c cid, \ref OK
- * and 0 otherwise.
- */
-SYSCALL_DEFINE1(free_timer)(struct tcb *t, sys_arg_t cid)
-{
- struct timer *timer = find_timer(cid);
- if (!timer)
- return_args1(t, ERR_NF);
-
- remove_timer(timer);
- return_args1(t, OK);
-}