diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/link.c | 1 | ||||
| -rw-r--r-- | sys/objdir.c | 114 | ||||
| -rw-r--r-- | sys/objdir.h | 27 | ||||
| -rw-r--r-- | sys/syscall.c | 33 | ||||
| -rw-r--r-- | sys/syscall.h | 1 | ||||
| -rw-r--r-- | sys/syscall_pcb.c | 11 | ||||
| -rw-r--r-- | sys/syscall_untyped.c | 43 |
7 files changed, 214 insertions, 16 deletions
@@ -1,5 +1,6 @@ #include "link.h" #include "arch/x86_64/hal/obj.h" +#include "sys/objdir.h" #include "hal/memory.h" #include "lib/printf.h" #include "jove.h" diff --git a/sys/objdir.c b/sys/objdir.c new file mode 100644 index 0000000..c448e85 --- /dev/null +++ b/sys/objdir.c @@ -0,0 +1,114 @@ +#include "api/error.h" +#include "arch/x86_64/hal/obj.h" +#include "hal/memory.h" +#include "hal/obj.h" +#include "lib/string.h" +#include "jove.h" +#include <errno.h> + +int +objdir_new(jove_owned_obj_t *untyped_obj) +{ + jove_untyped_t *untyped = obj_deref(untyped_obj); + if((uintptr_t)untyped & (JOVE_OBJDIR_SIZE - 1)) return -EALIGN; + if(untyped->limit != JOVE_OBJDIR_SIZE) return -EBADSIZE; + + memset(untyped, 0, JOVE_OBJDIR_SIZE); + obj_settype(untyped_obj, JOVE_OBJ_OBJDIR); + return 0; +} + +jove_obj_t +objdir_peeklocal( + jove_owned_obj_t *objdir_obj, + uint16_t entry) +{ + if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) { + errno = EBADOBJ; + return (jove_obj_t) { 0 }; + } + if(entry >= JOVE_OBJDIR_ENTRIES) { + errno = EBADPATH; + return (jove_obj_t) { 0 }; + } + + jove_objdir_t *objtab = obj_deref(objdir_obj); + return objtab->entries[entry]; +} + +jove_owned_obj_t* +objdir_getlocal( + jove_owned_obj_t *objdir_obj, + uint16_t entry) +{ + if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) { + reterr(EBADOBJ); + } + if(entry >= JOVE_OBJDIR_ENTRIES) { + reterr(EBADPATH); + } + + jove_objdir_t *objtab = obj_deref(objdir_obj); + return obj_take(&objtab->entries[entry]); +} + +jove_owned_obj_t* +objdir_trygetlocal( + jove_owned_obj_t *objdir_obj, + uint16_t entry) +{ + if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) { + reterr(EBADOBJ); + } + if(entry >= JOVE_OBJDIR_ENTRIES) { + reterr(EBADPATH); + } + + jove_objdir_t *objtab = obj_deref(objdir_obj); + return obj_trytake(&objtab->entries[entry]); +} + +jove_owned_obj_t* +objdir_getobj( + jove_owned_obj_t *objdir_obj, + const uint16_t *path, + size_t path_len) +{ + errno = 0; + if(path_len == 0) { + return objdir_obj; + } + { + jove_owned_obj_t *child_objdir = objdir_getlocal(objdir_obj, path[0]); + if(child_objdir == 0) { + reterr(EBADPATH); + } + + jove_owned_obj_t *target_obj = objdir_getobj(child_objdir, path + 1, path_len - 1); + obj_release(child_objdir); + return target_obj; + } +} + +jove_owned_obj_t* +objdir_trygetobj( + jove_owned_obj_t *objdir_obj, + const uint16_t *path, + size_t path_len) +{ + errno = 0; + if(path_len == 0) { + return objdir_obj; + } + { + jove_owned_obj_t *child_objdir = objdir_trygetlocal(objdir_obj, path[0]); + if(child_objdir == 0) { + return 0; + } + + jove_owned_obj_t *target_obj = objdir_trygetobj(child_objdir, path + 1, path_len - 1); + obj_release(child_objdir); + return target_obj; + } +} + diff --git a/sys/objdir.h b/sys/objdir.h new file mode 100644 index 0000000..54e9618 --- /dev/null +++ b/sys/objdir.h @@ -0,0 +1,27 @@ +#ifndef _JOVE_SYS_OBJDIR_H +#define _JOVE_SYS_OBJDIR_H 1 + +#include "hal/obj.h" + +int objdir_new(jove_owned_obj_t *untyped_obj); +/*Returns the n'th entry of the object directory passed. + * If the passed object is not an objdir, returns NULL and sets errno to EBADOBJ. + * If the passed entry index is out of bounds, returns NULL and sets errno to EOOB.*/ +jove_owned_obj_t *objdir_getlocal(jove_owned_obj_t *objdir_obj, uint16_t entry); +/*Same as objdir_getlocal except does not block if entry obj is taken.*/ +jove_owned_obj_t *objdir_trygetlocal(jove_owned_obj_t *objdir_obj, uint16_t entry); +jove_obj_t objdir_peeklocal(jove_owned_obj_t *objdir_obj, uint16_t entry); + +/*Recursively seeks through an object directory for an object following the passed + * path variable. + * If the path length is zero, returns the passed object. + * If the passed object is not an objdir, returns NULL and sets errno to EBADOBJ. + * If any object excluding the object at the end of the path is not an objdir, + * returns NULL and sets errno to EBADOBJ. + * If any entry in the path is out of bounds, returns NULL and sets errno to EBADOBJ.*/ +jove_owned_obj_t *objdir_getobj(jove_owned_obj_t *objdir_obj, const uint16_t *path, size_t path_len); +/*Same as objdir_getobj but does not block if child objects are locked.*/ +jove_owned_obj_t *objdir_trygetobj(jove_owned_obj_t *objdir_obj, const uint16_t *path, size_t path_len); + + +#endif diff --git a/sys/syscall.c b/sys/syscall.c index 05eeb58..0c40418 100644 --- a/sys/syscall.c +++ b/sys/syscall.c @@ -87,6 +87,7 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) ctx.pcb = process_current(); pcb_t *pcb = obj_deref(ctx.pcb); + ctx.objdir = lockstack_push(&ctx.lockstack, obj_take(pcb_getrootdir(pcb))); ctx.message = link_try_traverse_objdir( @@ -113,8 +114,8 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) goto release_return; } - uintptr_t message_vptr = message_unmap(ctx.message.obj, - (jove_owned_obj_t*)pcb_getpagedir(pcb)); + jove_owned_obj_t *pagedir = lockstack_push(&ctx.lockstack, pcb_getpagedir(ctx.objdir)); + uintptr_t message_vptr = message_unmap(ctx.message.obj, pagedir); size_t messagelen = 0x1000; void *messagedata = (void*)message_getdata(ctx.message.obj); @@ -135,27 +136,31 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) ctx.target = link_try_traverse_objdir( ctx.objdir, &ctx.lockstack, ctx.header->pathlen, ctx.header->path); - if(ctx.target.obj != 0) { - sysret = _syscall_handle_switch(&ctx); - }else{ - //Check if we're trying to reference the PCB. If we are, we should set it as the target - //regardless of lock. - if(ctx.header->pathlen == 1 && - objdir_peeklocal(ctx.objdir, ctx.header->path[0]).data == ctx.pcb->locked.data) - { - ctx.target = (jove_perm_obj_t) { .permissions = 0xFF, .obj = ctx.pcb }; - sysret = _syscall_handle_switch(&ctx); - + if(ctx.target.obj == 0) { + //Check if we're trying to reference objects we've already locked in this function. + //If we are, we should set it as the target regardless of lock, + //since we're the ones with the lock already. + if(ctx.header->pathlen == 1) { + if(ctx.header->path[0] == PCB_ROOTDIR_SELF_I) + ctx.target = (jove_perm_obj_t) { .permissions = 0xFF, .obj = ctx.pcb }; + else if(ctx.header->path[0] == PCB_ROOTDIR_PAGEDIR_I) + ctx.target = (jove_perm_obj_t) { .permissions = 0xFF, .obj = pagedir }; + else + goto fail_target_busy; }else{ +fail_target_busy: //Could not find payload target in pcb rootdir. klogf("Process %i tried to call syscall with bad target path %P : %s\n", pcb_getpid(pcb), header->path, header->pathlen, errstr(errno)); sysret = -errno; + goto remap_return; } } + sysret = _syscall_handle_switch(&ctx); + remap_return: - message_remap(ctx.message.obj, (jove_owned_obj_t*)pcb_getpagedir(pcb), message_vptr); + message_remap(ctx.message.obj, pagedir, message_vptr); release_return: lockstack_popall(&ctx.lockstack); diff --git a/sys/syscall.h b/sys/syscall.h index 6387d79..946417c 100644 --- a/sys/syscall.h +++ b/sys/syscall.h @@ -4,6 +4,7 @@ #include "config.h" #include "api/syscall.h" #include "hal/obj.h" +#include "sys/objdir.h" #include "lockstack.h" #include "link.h" #include <stdint.h> diff --git a/sys/syscall_pcb.c b/sys/syscall_pcb.c index b77be95..a37e4bb 100644 --- a/sys/syscall_pcb.c +++ b/sys/syscall_pcb.c @@ -1,14 +1,21 @@ #include "api/error.h" +#include "jove.h" #include "lib/printf.h" +#include "proc/process.h" +#include "proc/scheduler.h" #include "syscall.h" +#include "errno.h" int s_syscall_pcb_yield(jove_owned_obj_t *pcb_obj, size_t bytes_left, void *payload_data) { - kprintf("%s: Stub!\n", __func__); - return 0; + size_t bytes_needed = sizeof(pid_t); + CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); + + pid_t subject_pid = *((pid_t*)payload_data); + return scheduler_yield(subject_pid); } int diff --git a/sys/syscall_untyped.c b/sys/syscall_untyped.c index 8fe592d..1ec21c7 100644 --- a/sys/syscall_untyped.c +++ b/sys/syscall_untyped.c @@ -2,6 +2,7 @@ #include "hal/memory.h" #include "jove.h" #include "lib/printf.h" +#include "proc/process.h" #include "syscall.h" static int @@ -73,6 +74,27 @@ s_syscall_untyped_merge( return sysret; } +int +s_syscall_untyped_retype_pcb(jove_owned_obj_t *untyped_obj, + lockstack_t *lockstack, + jove_owned_obj_t *rootdir, + struct syscall_header *header) +{ + jove_untyped_t *untyped = obj_deref(untyped_obj); + CHECK_TOOSMALL(PCB_MINSIZE, untyped->limit, "Untyped object too small for PCB"); + + jove_perm_obj_t objdir_obj = link_try_traverse_objdir( + rootdir, lockstack, header->pathlen - 1, header->path); + if(errno) { + klogf("Unable to retrieve parent objdir at %P\n", + header->path, header->pathlen - 1); + return -errno; + } + CHECK_OBJPERM(objdir_obj, JOVE_PERM_ALL, "New PCB needs full access to it's root objdir!"); + + obj_settype(untyped_obj, JOVE_OBJ_PCB); + return pcb_new(untyped_obj, untyped->limit, objdir_obj.obj); +} int _syscall_handle_untyped(syscall_context_t *ctx) { @@ -99,6 +121,27 @@ int _syscall_handle_untyped(syscall_context_t *ctx) &ctx->lockstack, ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload); return -EPERM; + case SYSCALL_UNTYPED_RETYPE_OBJDIR: + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) + return objdir_new(ctx->target.obj); + return -EPERM; + + case SYSCALL_UNTYPED_RETYPE_PAGEDIR: + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) + return pagedir_new(ctx->target.obj); + return -EPERM; + + case SYSCALL_UNTYPED_RETYPE_SHMEMORY: + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) + return shmem_new(ctx->target.obj); + return -EPERM; + + case SYSCALL_UNTYPED_RETYPE_PCB: + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) + return s_syscall_untyped_retype_pcb( + ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->header); + return -EPERM; + default: return -EBADCALL; } |
