diff options
author | dzwdz | 2022-07-18 23:55:58 +0200 |
---|---|---|
committer | dzwdz | 2022-07-18 23:55:58 +0200 |
commit | 96f41ff64d8113307f1b60d2eb6852423db34d14 (patch) | |
tree | 5a85a9706a2a11d047f7f5c91f4964bd2167b1ee /src/kernel/execbuf.c | |
parent | 121794214fd5ae36609c30418dfaf1a073b8784c (diff) |
syscalls: implement execbuf
i have been planning to implement something like this for a while now.
it should be faster when doing consecutive syscalls (to be tested).
it will also be helpful in writing the elf loader
Diffstat (limited to 'src/kernel/execbuf.c')
-rw-r--r-- | src/kernel/execbuf.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/src/kernel/execbuf.c b/src/kernel/execbuf.c new file mode 100644 index 0000000..6136d0e --- /dev/null +++ b/src/kernel/execbuf.c @@ -0,0 +1,38 @@ +#include <kernel/execbuf.h> +#include <kernel/mem/alloc.h> +#include <kernel/panic.h> +#include <shared/execbuf.h> +#include <shared/mem.h> + +_Noreturn static void halt(struct process *proc) { + kfree(proc->execbuf.buf); + proc->execbuf.buf = NULL; + process_switch_any(); +} + +static void try_fetch(struct process *proc, uint64_t *buf, size_t amt) { + size_t bytes = amt * sizeof(uint64_t); + if (proc->execbuf.pos + bytes > proc->execbuf.len) + halt(proc); + memcpy(buf, proc->execbuf.buf + proc->execbuf.pos, bytes); + proc->execbuf.pos += bytes; +} + +_Noreturn void execbuf_run(struct process *proc) { + uint64_t buf[5]; + assert(proc == process_current); // idiotic, but needed because of _syscall. + assert(proc->state == PS_RUNNING); + assert(proc->execbuf.buf); + + for (;;) { + try_fetch(proc, buf, 1); + switch (buf[0]) { + case EXECBUF_SYSCALL: + try_fetch(proc, buf, 5); + _syscall(buf[0], buf[1], buf[2], buf[3], buf[4]); + break; + default: + halt(proc); + } + } +} |