diff options
Diffstat (limited to 'sys/syscall.c')
| -rw-r--r-- | sys/syscall.c | 105 |
1 files changed, 56 insertions, 49 deletions
diff --git a/sys/syscall.c b/sys/syscall.c index 457b820..0da3475 100644 --- a/sys/syscall.c +++ b/sys/syscall.c @@ -24,28 +24,20 @@ int __syscall_generic_objpath(jove_owned_obj_t *objdir, size_t payload_bytes, vo } int -_syscall_handle_generic( - jove_owned_obj_t *pcb_obj, - jove_owned_obj_t *objdir, - jove_owned_obj_t *message_obj, - jove_owned_obj_t *target_obj, - struct syscall_header *header, - size_t bytes_left, - void *payload) +_syscall_handle_generic(syscall_context_t *ctx) { - pcb_t *pcb = obj_deref(pcb_obj); - klogf("Process %i encountered stub syscall on object %P\n", pcb_pid(pcb), header->path, header->pathlen); - return EBADOBJ; + pcb_t *pcb = obj_deref(ctx->pcb); + klogf("Process %i encountered stub syscall on object %P\n", pcb_pid(pcb), ctx->header->path, ctx->header->pathlen); + return -EBADOBJ; } static const syscall_handle_t s_syscall_handles[128] = { - [JOVE_OBJ_NONE] = NULL, [JOVE_OBJ_UNTYPED] = _syscall_handle_untyped, [JOVE_OBJ_OBJDIR] = _syscall_handle_objdir, [JOVE_OBJ_PAGEDIR] = _syscall_handle_pagedir, [JOVE_OBJ_PROCESSOR] = _syscall_handle_generic, - [JOVE_OBJ_HWMEMORY] = _syscall_handle_generic, - [JOVE_OBJ_PROCESS] = _syscall_handle_generic, + [JOVE_OBJ_SHMEMORY] = _syscall_handle_generic, + [JOVE_OBJ_PCB] = _syscall_handle_generic, [JOVE_OBJ_INT_HANDLE] = _syscall_handle_generic, [JOVE_OBJ_INITRD_FILE] = _syscall_handle_generic, [JOVE_OBJ_FRAMEBUFFER] = _syscall_handle_generic, @@ -55,36 +47,63 @@ static const syscall_handle_t s_syscall_handles[128] = { }; int +_syscall_handle_switch(syscall_context_t *ctx) +{ + uint8_t target_type = obj_gettype(ctx->target.obj); + if(target_type > 0x7F) { + return _syscall_handle_arch(ctx); + } + else { + syscall_handle_t call_handle = s_syscall_handles[target_type]; + if(call_handle == NULL) { + klogf("Tried to call syscall on object %P which doesn't support syscalls!\n", + ctx->header->path, ctx->header->pathlen); + return -EBADOBJ; + } + else { + return call_handle(ctx); + } + } +} + +int syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) { uint16_t *message_path = (uint16_t*)&message_path_raw; if(message_pathlen > sizeof(uintmax_t) >> 1) { - return EBADPATH; + return -EBADPATH; } - jove_owned_obj_t *pcb_obj = process_current(); - pcb_t *pcb = obj_deref(pcb_obj); - jove_owned_obj_t *objdir = pcb_rootdir(pcb); - jove_owned_obj_t *message_obj = objdir_trygetobj(objdir, message_path, message_pathlen); + syscall_context_t ctx; + ctx.lockstack.depth = 0; int sysret = 0; - if(message_obj == NULL) { - klogf("Process %i tried to call syscall with bad message %P : %s\n", + ctx.pcb = lockstack_push(&ctx.lockstack, process_current()); + pcb_t *pcb = obj_deref(ctx.pcb); + ctx.objdir = lockstack_push(&ctx.lockstack, obj_take(pcb_rootdir(pcb))); + + ctx.message = link_try_traverse( + lockstack_push(&ctx.lockstack, objdir_trygetobj( + ctx.objdir, message_path, message_pathlen)), + &ctx.lockstack); + + if(ctx.message.obj == NULL) { + klogf("Process %i failed to get message %P : %s\n", pcb_pid(pcb), message_path, message_pathlen, errstr(errno)); sysret = -errno; - goto release_premsg; + goto release_return; } - if(obj_gettype_linked(message_obj) != JOVE_OBJ_MESSAGE) { + if(obj_gettype(ctx.message.obj) != JOVE_OBJ_MESSAGE) { klogf("Process %i tried to call syscall with invalid object %P\n", pcb_pid(pcb), message_path, message_pathlen); sysret = -EBADOBJ; goto release_return; } - size_t messagelen = message_len(message_obj); - void *messagedata = message_data(message_obj); + size_t messagelen = message_len(ctx.message.obj); + void *messagedata = message_data(ctx.message.obj); struct syscall_header *header = messagedata; size_t bytes_needed = sizeof(struct syscall_header) + header->pathlen * 2; @@ -94,8 +113,14 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) sysret = -ETOOSMALL; goto release_return; } - jove_owned_obj_t *target = objdir_trygetobj(objdir, header->path, header->pathlen); - if(target == 0) { + + ctx.header = header; + ctx.bytes_left = messagelen - bytes_needed; + ctx.payload = (void*)((uintptr_t)header + bytes_needed); + + ctx.target.obj = lockstack_push(&ctx.lockstack, + objdir_trygetobj(ctx.objdir, header->path, header->pathlen)); + if(ctx.target.obj == 0) { //Could not find payload target in pcb rootdir. klogf("Process %i tried to call syscall with bad target path %P : %s\n", pcb_pid(pcb), header->path, header->pathlen, errstr(errno)); @@ -103,28 +128,10 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) goto release_return; } - uint8_t target_type = obj_gettype(target); - size_t bytes_left = messagelen - bytes_needed; - if(target_type > 0x7F) { - sysret = _syscall_handle_arch( - pcb_obj, objdir, message_obj, target, - header, bytes_left, messagedata + bytes_needed); - }else{ - syscall_handle_t call_handle = s_syscall_handles[obj_gettype(target)]; - if(call_handle == NULL) { - klogf("Process %i tried to call syscall on object %P which doesn't support syscalls!\n", - pcb_pid(pcb), header->path, header->pathlen); - sysret = -EBADOBJ; - }else - sysret = call_handle( - pcb_obj, objdir, message_obj, target, - header, bytes_left, messagedata + bytes_needed); - } - obj_release(target); + ctx.target.permissions = JOVE_PERM_ALL; + sysret = _syscall_handle_switch(&ctx); + release_return: - obj_release(message_obj); -release_premsg: - obj_release(objdir); - obj_release(pcb_obj); + lockstack_popall(&ctx.lockstack); return sysret; } |
