diff options
author | Jon Santmyer <jon@jonsantmyer.com> | 2025-08-19 15:04:04 -0400 |
---|---|---|
committer | Jon Santmyer <jon@jonsantmyer.com> | 2025-08-19 15:04:04 -0400 |
commit | 858a52c06a4615bd58a6a906333f2ad707d41c0a (patch) | |
tree | 16870cd4d67da283567a72a74d28c04464da292a | |
parent | 65ba015d6c1f248d36ad01a653bc49637804b15b (diff) | |
download | jove-os-858a52c06a4615bd58a6a906333f2ad707d41c0a.tar.gz jove-os-858a52c06a4615bd58a6a906333f2ad707d41c0a.tar.bz2 jove-os-858a52c06a4615bd58a6a906333f2ad707d41c0a.zip |
usermode pager
27 files changed, 890 insertions, 116 deletions
@@ -58,7 +58,7 @@ test: $(TEST_HDD) $(KERNEL_BIN) $(INITRD_TAR) $(SYSROOTDIR) sudo umount $(TEST_HDD_DIR) sudo losetup -d $$LOOPBACK_DEV sudo rm -rf $(TEST_HDD_DIR) - qemu-system-x86_64 -m 512M -M q35 -bios ovmf-x64/OVMF.fd -net none -smp 4 -hda test.hdd -serial stdio -no-shutdown -no-reboot -s -d int -d guest_errors + qemu-system-x86_64 -m 512M -M q35 -bios ovmf-x64/OVMF.fd -net none -smp 4 -hda test.hdd -serial stdio -no-shutdown -no-reboot -s .PHONY: $(TEST_HDD) $(TEST_HDD): diff --git a/apps/init/Makefile b/apps/init/Makefile index 642ca38..1834d0b 100644 --- a/apps/init/Makefile +++ b/apps/init/Makefile @@ -1,11 +1,12 @@ include $(CONFIG) CFILES := $(wildcard *.c) +CFILES += $(wildcard arch/$(TARGET_MACHINE)/*.c) OFILES := $(patsubst %.c,%.o,$(CFILES)) OFILES += $(STATICLIBS) CFLAGS := -ffreestanding -nostdlib -g -LDFLAGS := -T $(TARGET_MACHINE).ld +LDFLAGS := -T arch/$(TARGET_MACHINE)/link.ld OCFLAGS := -O binary \ --set-section-flags .bss=alloc,load,contents diff --git a/apps/init/x86_64.ld b/apps/init/arch/x86_64/link.ld index 45b08f5..45b08f5 100644 --- a/apps/init/x86_64.ld +++ b/apps/init/arch/x86_64/link.ld diff --git a/apps/init/arch/x86_64/paging.c b/apps/init/arch/x86_64/paging.c new file mode 100644 index 0000000..6c1c386 --- /dev/null +++ b/apps/init/arch/x86_64/paging.c @@ -0,0 +1,109 @@ +#include "../../memory.h" +#include "jove/object-dir.h" +#include "jove/jove.h" +#include <jove/arch/x86_64/object-pagemap.h> +#include <stdbool.h> + +KernelObjectPageMap init_pagemap; +unsigned d_cache[3] = { -1, -1, -1 }; +uintptr_t vptr_cache = 0; + +KernelObjectUntyped work_page; + +#define PMLI_SHL(d) (((4 - d) * 9) + 3) +#define PMLI_DL(v, d) ((v >> PMLI_SHL(d)) % 512) + +uint64_t +pager_write_path(uintptr_t vptr, uint8_t depth) +{ + uint64_t r = 0; + if(depth >= 4) return -1; + + uint16_t *path = (uint16_t*)&r; + for(uint8_t i = 0; i < depth; i++) path[i] = PMLI_DL(vptr, i); + return r; +} + +bool +pager_depth_exists(uintptr_t vptr, uint8_t depth) +{ + uint64_t path = pager_write_path(vptr, depth); + if(path == -1) return false; + + return jove_pagemap_exists(&init_pagemap, depth, (uint16_t*)&path); +} +/* Places new page in work_page. */ +JoveError +pager_alloc_page_untyped(void) +{ + uint8_t lastmemb = jove_objdir_lastmemb(&untypedDirectory); + if(jove_errno) { + JoveError err = jove_errno; + jove_errno = EJOVE_OK; + return err; + } + + KernelObjectUntyped last_untyped; + _jove_alloc_untyped_inplace(&last_untyped, &untypedDirectory, lastmemb); + + if(jove_untyped_size(&last_untyped) == 0x1000) { + jove_objdir_move(&untypedDirectory, lastmemb, &__rootdir, work_page.typed.membi); + return EJOVE_OK; + } + + return jove_untyped_split_inplace(&last_untyped, 0x1000, &work_page); +} + +JoveError +pager_ensure_at_depth(uint8_t depth, uint16_t *path) +{ + int exists = jove_pagemap_exists(&init_pagemap, depth, path); + if(exists) { + return EJOVE_OK; + } + + JoveError pagealloc_err = pager_alloc_page_untyped(); + if(pagealloc_err) { + jove_kprintf("Failed to allocate page with error %i\n", pagealloc_err); + return pagealloc_err; + } + return jove_pagemap_map(&init_pagemap, depth, path, &work_page); +} + +#define PAGER_CACHE_ENSURE_DEPTH(path_seg, d) \ + if(path_seg[d] != d_cache[d]) { \ + JoveError d_err = pager_ensure_at_depth(d, path_seg); \ + if(d_err) return d_err; \ + d_cache[d] = path_seg[d]; \ + } + +JoveError +pager_ensure(uintptr_t vptr) +{ + uint64_t path = pager_write_path(vptr, 3); + if(path == -1) return EJOVE_BADARG; + + vptr &= ~0xFFFULL; + uint16_t *path_seg = (uint16_t*)&path; + jove_kprintf("%x:%x:%x:%x\n", path_seg[0], path_seg[1], path_seg[2], path_seg[3]); + + PAGER_CACHE_ENSURE_DEPTH(path_seg, 0); + PAGER_CACHE_ENSURE_DEPTH(path_seg, 1); + PAGER_CACHE_ENSURE_DEPTH(path_seg, 2); + if(vptr != vptr_cache) { + return pager_ensure_at_depth(3, path_seg); + } + return EJOVE_OK; +} + +void +pager_setup(void) +{ + _jove_alloc_objdir_inplace(&untypedDirectory, &__rootdir, INIT_OBJECT_UNTYPED_DIR); + _jove_alloc_pagemap_inplace(&init_pagemap, &__rootdir, INIT_OBJECT_PAGEMAP); + + size_t lastfree = jove_objdir_lastmemb(&__rootdir) + 1; + _jove_alloc_untyped_inplace(&work_page, &__rootdir, lastfree++); + + pager_ensure(0x00000000F0000000); +} diff --git a/apps/init/arch/x86_64/start.c b/apps/init/arch/x86_64/start.c new file mode 100644 index 0000000..8329523 --- /dev/null +++ b/apps/init/arch/x86_64/start.c @@ -0,0 +1,11 @@ +extern void main(void*); + +__attribute__((section(".text.start"))) +__attribute__((naked)) +void +_start(void) +{ + __asm__ volatile("\ + popq %%rdi; \ + jmp main"::); +} diff --git a/apps/init/main.c b/apps/init/main.c index c8dabdf..17b825e 100644 --- a/apps/init/main.c +++ b/apps/init/main.c @@ -4,11 +4,12 @@ #include <jove/jove.h> #include <jove/object.h> #include <jove/syscall.h> -#include <jove/arch/x86_64/object-pagemap.h> + +#include "memory.h" /**This program acts as a memory and process server.*/ -#define INIT_HEAP_START_BYTES 4096 +#define INIT_HEAP_START_BYTES 8192 __attribute__((section(".bss.heap"))) uint8_t init_heap[INIT_HEAP_START_BYTES]; size_t init_heap_start = (uintptr_t)init_heap; @@ -28,76 +29,18 @@ init_bumpalloc(size_t bytes) return r; } -KernelObjectTyped _logObject; -KernelObjectDirectory _untypedDirectory; -KernelObjectDirectory _processorDirectory; -KernelObjectPageMapping _pageMapping; -KernelObjectDirectory _initrd; -KernelObjectMessage _messageObject; - -#define POPULATE_ROOTDIR_MEMB(memb, i) \ -{ KernelObjectTyped *typed = JOVE_OBJECT_TYPED(memb); \ - __rootdir.children[i] = typed; \ - typed->parent = JOVE_OBJECT_TYPED(&__rootdir); \ - typed->membi = i; \ - if(_syscall_invoke_objdir_getmemb(&__rootdir, i, &typed->type) != 0) { \ - jove_kprintf("Failed to populate objdir root member %i\n", i); \ - spin_fail(); \ - } \ -} - -static void -s_populate_rootdir(init_data_t *init_data) -{ - __rootdir.typed.parent = NULL; - __rootdir.children[0] = JOVE_OBJECT_TYPED(&__rootdir); - - POPULATE_ROOTDIR_MEMB(&_logObject, init_data->log_object); - POPULATE_ROOTDIR_MEMB(&_untypedDirectory, init_data->untyped_data_dir); - POPULATE_ROOTDIR_MEMB(&_processorDirectory, init_data->processor_dir); - POPULATE_ROOTDIR_MEMB(&_pageMapping, init_data->pm_object); - POPULATE_ROOTDIR_MEMB(&_initrd, init_data->initrd_dir); - POPULATE_ROOTDIR_MEMB(&_messageObject, init_data->message_object); - - //Populate untyped table - for(int i = 1; i < 256; i++) { - KernelObjectUntyped untyped; - untyped.typed.parent = &_untypedDirectory; - untyped.typed.membi = i; - if(_syscall_invoke_objdir_getmemb(&_untypedDirectory, i, &untyped.typed.type) != 0) { - jove_kprintf("Failed to get member %i of untyped directory\n", i); - spin_fail(); - } - if(untyped.typed.type != KO_MEMORY_UNTYPED) continue; - _untypedDirectory.children[i] = init_bumpalloc(sizeof(KernelObjectUntyped)); - memcpy(_untypedDirectory.children[i], &untyped, sizeof(KernelObjectUntyped)); - - _syscall_invoke_untyped_size(&untyped, &untyped.bytes); - _syscall_invoke_untyped_alignment(&untyped, &untyped.alignment); - - jove_kprintf("Untyped %i size %X align %X\n", i, untyped.bytes, untyped.alignment); - } -} +KernelObjectDirectory untypedDirectory; void -main(init_data_t *init_data) +main(void *message_ptr) { libjove_init( - (uintmax_t)init_data->message_object, - (void*)init_data->message_object_address); - jove_kprintf("Hello, Userland!\n"); + INIT_OBJECT_MESSAGE, + message_ptr); + _jove_alloc = init_bumpalloc; - s_populate_rootdir(init_data); + jove_kprintf("Hello, Userland!\n"); + pager_setup(); for(;;); } - -__attribute__((section(".text.start"))) -__attribute__((naked)) -void -_start(void) -{ - __asm__ volatile("\ - popq %%rdi; \ - jmp main"::); -} diff --git a/apps/init/memory.h b/apps/init/memory.h index 61d16d6..378de60 100644 --- a/apps/init/memory.h +++ b/apps/init/memory.h @@ -1,6 +1,10 @@ #ifndef _INIT_MEMORY_H #define _INIT_MEMORY_H 1 +#include <jove/object.h> +extern KernelObjectDirectory untypedDirectory; + +void pager_setup(); #endif diff --git a/initrd/files/bin/init b/initrd/files/bin/init Binary files differindex 6fa149d..c86f9d1 100755 --- a/initrd/files/bin/init +++ b/initrd/files/bin/init diff --git a/kernel b/kernel -Subproject c4f8ef91f18d854a4ede7a94e95b2eab898d696 +Subproject 772717dc22e04b4d168d0f77bee6b6357118768 diff --git a/lib/libc-headless/stdio/sprintf.c b/lib/libc-headless/stdio/sprintf.c index 2881bd5..dd78572 100644 --- a/lib/libc-headless/stdio/sprintf.c +++ b/lib/libc-headless/stdio/sprintf.c @@ -108,7 +108,7 @@ conversion_int: for(uintmax_t v = value, i = numc - 1; v != 0; v /= radix, i--) { if(written + i >= size) continue; int digit = v % radix; - char c = digit > 10 ? (digit + 'a' - 10) : (digit + '0'); + char c = digit >= 10 ? (digit + 'a' - 10) : (digit + '0'); if(is_caps) c = toupper(c); str[written + i] = c; } diff --git a/lib/libjove/Makefile b/lib/libjove/Makefile index cc5f347..024d4fe 100644 --- a/lib/libjove/Makefile +++ b/lib/libjove/Makefile @@ -1,8 +1,11 @@ include $(CONFIG) -CDIRS := syscall object arch/$(TARGET_MACHINE) +CDIRS := syscall object + CFILES := $(wildcard *.c) CFILES += $(foreach dir,$(CDIRS),$(wildcard $(dir)/*.c)) +CFILES += $(wildcard arch/$(TARGET_MACHINE)/*.c) +CFILES += $(foreach dir,$(CDIRS),$(wildcard arch/$(TARGET_MACHINE)/$(dir)/*.c)) OFILES := $(patsubst %.c,%.o,$(CFILES)) diff --git a/lib/libjove/arch/x86_64/invoke-pagemap.c b/lib/libjove/arch/x86_64/invoke-pagemap.c index 8357904..e3f3dff 100644 --- a/lib/libjove/arch/x86_64/invoke-pagemap.c +++ b/lib/libjove/arch/x86_64/invoke-pagemap.c @@ -1,3 +1,4 @@ +#include "arch/x86_64/syscall.h" #include <arch/x86_64/object-pagemap.h> #include <kernel/syscall.h> #include <kernel/arch/x86_64/syscall.h> @@ -7,14 +8,41 @@ #include <jove/jove.h> int -_syscall_invoke_mapping_get(KernelObjectPageMapping *mapping, uint16_t pmli, KernelObjectPageMapping *dest) +_syscall_invoke_mapping_exists(KernelObjectPageMap *map, uint8_t depth, uint16_t *path) { uint8_t *syscallData = _syscall_message_ptr; int syscall_at = 0; - SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, mapping); - SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_MAPPING_GET, uint8_t); - SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, pmli, uint16_t); + SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, map); + SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_MAPPING_EXISTS, uint8_t); + SYSCALL_PAYLOAD_PUTPML(syscallData, syscall_at, depth, path); + + return _syscall_invoke(); +} + +int +_syscall_invoke_mapping_map(KernelObjectPageMap *map, uint8_t depth, uint16_t *path, KernelObjectUntyped *untyped) +{ + uint8_t *syscallData = _syscall_message_ptr; + int syscall_at = 0; + + SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, map); + SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_MAPPING_MAP, uint8_t); + SYSCALL_PAYLOAD_PUTPML(syscallData, syscall_at, depth, path); + SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, untyped); + + return _syscall_invoke(); +} + +int +_syscall_invoke_mapping_unmap(KernelObjectPageMap *map, uint8_t depth, uint16_t *path, KernelObjectUntyped *dest) +{ + uint8_t *syscallData = _syscall_message_ptr; + int syscall_at = 0; + + SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, map); + SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_MAPPING_UNMAP, uint8_t); + SYSCALL_PAYLOAD_PUTPML(syscallData, syscall_at, depth, path); SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, dest); return _syscall_invoke(); diff --git a/lib/libjove/arch/x86_64/object/directory.c b/lib/libjove/arch/x86_64/object/directory.c new file mode 100644 index 0000000..01f57c4 --- /dev/null +++ b/lib/libjove/arch/x86_64/object/directory.c @@ -0,0 +1,15 @@ +#include <object.h> +#include <arch/x86_64/object-pagemap.h> + +JoveError +_jove_objdir_sync_at_arch(KernelObjectDirectory *dir, uint8_t i, obj_type_t type, KernelObjectTyped **memb) +{ + KernelObjectTyped *dirmemb = NULL; + switch(type) { + case KO_MEMORY_MAPPING: + dirmemb = JOVE_OBJECT_TYPED(_jove_alloc_pagemap(dir, i)); + if(memb) *memb = dirmemb; + break; + } + return EJOVE_OK; +} diff --git a/lib/libjove/arch/x86_64/object/pagemap.c b/lib/libjove/arch/x86_64/object/pagemap.c new file mode 100644 index 0000000..c58d7c6 --- /dev/null +++ b/lib/libjove/arch/x86_64/object/pagemap.c @@ -0,0 +1,105 @@ +#include <object.h> +#include <jove.h> +#include <error.h> +#include <kernel/error.h> +#include <string.h> +#include <arch/x86_64/object-pagemap.h> +#include <arch/x86_64/syscall.h> + +KernelObjectPageMap* +jove_object_as_pagemap(KernelObjectTyped *typed) +{ + if(typed->type == KO_MEMORY_MAPPING) return (KernelObjectPageMap*)typed; + jove_errno = EJOVE_BADOBJ; + return NULL; +} + +void +_jove_alloc_pagemap_inplace( + KernelObjectPageMap *pagemap, + KernelObjectDirectory *dir, + uint8_t memb) +{ + *pagemap = (KernelObjectPageMap) { + .typed = (KernelObjectTyped) { + .parent = dir, + .type = KO_MEMORY_MAPPING, + .membi = memb + }, + }; + dir->children[memb] = JOVE_OBJECT_TYPED(pagemap); +} + +KernelObjectPageMap* +_jove_alloc_pagemap( + KernelObjectDirectory *dir, + uint8_t memb) +{ + if(_jove_alloc == NULL) { + jove_errno = EJOVE_NOALLOC; + return NULL; + } + if(dir->children[memb] != NULL) { + jove_errno = EJOVE_FULL; + return NULL; + } + + KernelObjectPageMap *pagemap = _jove_alloc(sizeof(KernelObjectPageMap)); + if(pagemap == NULL) return NULL; + + _jove_alloc_pagemap_inplace(pagemap, dir, memb); + jove_errno = EJOVE_OK; + return pagemap; +} + +int +jove_pagemap_exists( + KernelObjectPageMap *map, + uint8_t depth, + uint16_t *path + ) +{ + if(!_jove_alloc) { + jove_errno = EJOVE_NOALLOC; + return 0; + } + int kerr = _syscall_invoke_mapping_exists(map, depth, path); + if(kerr == KE_DNE) return 0; + + int jerr = jove_error_from_kerror(kerr); + + if(jerr) { + jove_errno = jerr; + return 0; + } + return 1; +} + +JoveError +jove_pagemap_map( + KernelObjectPageMap *map, + uint8_t depth, + uint16_t *path, + KernelObjectUntyped *untyped) +{ + if(jove_untyped_size(untyped) != 0x1000) { + return EJOVE_BADSIZE; + } + + return jove_error_from_kerror(_syscall_invoke_mapping_map(map, depth, path, untyped)); +} + +JoveError +jove_pagemap_unmap( + KernelObjectPageMap *map, + uint8_t depth, + uint16_t *path, + KernelObjectUntyped *untyped) +{ + JoveError err = jove_error_from_kerror(_syscall_invoke_mapping_unmap(map, depth, path, untyped)); + if(err) return err; + + untyped->alignment = 0x1000; + untyped->bytes = 0x1000; + return EJOVE_OK; +} diff --git a/lib/libjove/error.c b/lib/libjove/error.c new file mode 100644 index 0000000..4c0d043 --- /dev/null +++ b/lib/libjove/error.c @@ -0,0 +1,22 @@ +#include <error.h> +#include <kernel/error.h> + +JoveError +jove_error_from_kerror(int kerror) +{ + switch(kerror) { + case KE_OK: + return EJOVE_OK; + case KE_BADMSG: + case KE_BADOBJ: + return EJOVE_BADOBJ; + case KE_BADCALL: + case KE_BADFUNC: + return EJOVE_NOIMPL; + case KE_BADSIZE: + return EJOVE_BADSIZE; + case KE_DNE: + return EJOVE_DNE; + default: return EJOVE_KERROR; + } +} diff --git a/lib/libjove/include/arch/x86_64/object-pagemap.h b/lib/libjove/include/arch/x86_64/object-pagemap.h index 55b0570..48e959e 100644 --- a/lib/libjove/include/arch/x86_64/object-pagemap.h +++ b/lib/libjove/include/arch/x86_64/object-pagemap.h @@ -2,13 +2,51 @@ #define _LIBJOVE_ARCH_x86_64_OBJECT_PAGEMAP_H 1 #include <jove/object-typed.h> +#include <jove/object-dir.h> +#include <jove/object-untyped.h> -typedef struct KernelObjectPageMapping +typedef struct KernelObjectPageMap { KernelObjectTyped typed; - uint8_t level; -} KernelObjectPageMapping; +} KernelObjectPageMap; +KernelObjectPageMap *jove_object_as_pagemap(KernelObjectTyped *typed); +/**@FUNC Populates a given region of memory for a page map value. + * @PARAM pagemap address of pagemap cache object. + * @PARAM dir directory this memory is a member of. + * @PARAM memb index into directory to place object.*/ +void _jove_alloc_pagemap_inplace( + KernelObjectPageMap *pagemap, + KernelObjectDirectory *dir, + uint8_t memb); + +/**@FUNC Allocates a region of memory to represent a page map. + * @PARAM dir directory to place new value in. + * @PARAM memb index into directory to place object. + * @RETURN newly allocated object. NULL on failure. + * Possible failures: + * EJOVE_FULL: Slot is already taken by an existing object. + * EJOVE_NOALLOC: libjove does not have an allocator yet.*/ +KernelObjectPageMap* _jove_alloc_pagemap( + KernelObjectDirectory *dir, + uint8_t memb); + +int jove_pagemap_exists( + KernelObjectPageMap *map, + uint8_t depth, + uint16_t *path); + +JoveError jove_pagemap_map( + KernelObjectPageMap *map, + uint8_t depth, + uint16_t *path, + KernelObjectUntyped *page); + +JoveError jove_pagemap_map_unmap( + KernelObjectPageMap *map, + uint8_t depth, + uint16_t *path, + KernelObjectUntyped *dest); #endif diff --git a/lib/libjove/include/arch/x86_64/syscall.h b/lib/libjove/include/arch/x86_64/syscall.h index 1d7df53..74fb389 100644 --- a/lib/libjove/include/arch/x86_64/syscall.h +++ b/lib/libjove/include/arch/x86_64/syscall.h @@ -4,9 +4,17 @@ #include <stdint.h> #include <kernel/object.h> -#include <jove/object-path.h> +#include <jove/arch/x86_64/object-pagemap.h> +#include <jove/syscall.h> -int _syscall_invoke_mapping_get(KernelObjectPath path, uint16_t pmli, KernelObjectPath destPath); +#define SYSCALL_PAYLOAD_PUTPML(payload, payload_at, depth, path) \ + if(payload_at + 1 + ((depth + 1) * sizeof(uint16_t)) > KO_MESSAGE_BYTES) return -1; \ + *((uint8_t*)&payload[payload_at++]) = depth; \ + for(uint8_t i = 0; i < depth + 1; i++) *((uint16_t*)&payload[payload_at + (i * 2)]) = path[i]; \ + payload_at += (depth + 1) * 2 +int _syscall_invoke_mapping_exists(KernelObjectPageMap *map, uint8_t depth, uint16_t *path); +int _syscall_invoke_mapping_map(KernelObjectPageMap *map, uint8_t depth, uint16_t *path, KernelObjectUntyped *untyped); +int _syscall_invoke_mapping_unmap(KernelObjectPageMap *map, uint8_t depth, uint16_t *path, KernelObjectUntyped *dest); #endif diff --git a/lib/libjove/include/error.h b/lib/libjove/include/error.h new file mode 100644 index 0000000..bbf7a51 --- /dev/null +++ b/lib/libjove/include/error.h @@ -0,0 +1,22 @@ +#ifndef _LIBJOVE_ERROR_H +#define _LIBJOVE_ERROR_H 1 + +typedef enum _JoveError{ + EJOVE_OK = 0, + EJOVE_KERROR, + EJOVE_NOALLOC, + EJOVE_NOFREE, + EJOVE_NOIMPL, + EJOVE_FULL, + EJOVE_BADOBJ, + EJOVE_BADSIZE, + EJOVE_BADARG, + EJOVE_DNE, + EJOVE_TOOBIG +} JoveError; + +extern JoveError jove_errno; + +JoveError jove_error_from_kerror(int kerror); + +#endif diff --git a/lib/libjove/include/jove.h b/lib/libjove/include/jove.h index 2efef3e..87eecb3 100644 --- a/lib/libjove/include/jove.h +++ b/lib/libjove/include/jove.h @@ -2,10 +2,15 @@ #define _LIBJOVE_JOVE_H 1 #include <stdint.h> +#include <stddef.h> extern uintmax_t _syscall_message_box; extern void *_syscall_message_ptr; +extern void *(*_jove_alloc)(size_t); +extern void (*_jove_free)(void*); +extern void *(*_jove_realloc)(void*, size_t); + void libjove_init(uintmax_t box, void *boxptr); void jove_kprintf(const char *restrict fmt, ...); diff --git a/lib/libjove/include/object-dir.h b/lib/libjove/include/object-dir.h index f258089..e4d9aaf 100644 --- a/lib/libjove/include/object-dir.h +++ b/lib/libjove/include/object-dir.h @@ -6,12 +6,92 @@ #include <kernel/object.h> #include <jove/object-typed.h> +#include <jove/error.h> -/**@STRUCT Represents a kobjdir.*/ +/**@STRUCT Represents cached information about a KO_OBJDIR. + * To update the information this struct contains, call jove_objdir_sync.*/ typedef struct _KernelObjectDirectory { KernelObjectTyped typed; + + uint8_t lastmemb; + uint8_t firstfree; + KernelObjectTyped *children[256]; } KernelObjectDirectory; extern KernelObjectDirectory __rootdir; +KernelObjectDirectory *jove_object_as_objdir(KernelObjectTyped *typed); + +/**@FUNC Populates a objdir struct for an empty directory at dir:memb. + * @PARAM dir address to populate. + * @PARAM parent directory to make dir child of. + * @PARAM memb index to place new objdir.*/ +void _jove_alloc_objdir_inplace( + KernelObjectDirectory *dir, + KernelObjectDirectory *parent, + uint8_t memb); + +/**@FUNC Allocates a block of memory to represent a kernel objdir. + * @PARAM parent directory to place new member into. + * @PARAM memb index to place new objdir. + * @RETURN pointer to new objdir. + * Possible failures: + * EJOVE_NOALLOC: libjove is missing an allocator. + * EJOVE_FULL: space at memb is already taken.*/ +KernelObjectDirectory *_jove_alloc_objdir( + KernelObjectDirectory *parent, + uint8_t memb); + +/**@FUNC Updates the dir struct with information obtained through the kernel. + * @PARAM dir directory to sync. + * @RETURN error code. 0 on success*/ +JoveError jove_objdir_sync(KernelObjectDirectory *dir); + +/**@FUNC Updates the dir struct at the given index with information obtained + * through the kernel. + * @PARAM dir directory to sync. + * @PARAM i index to sync. + * @PARAM memb pointer to place typed object in. Nullable + * @RETURN error code. 0 on success.*/ +JoveError jove_objdir_sync_at(KernelObjectDirectory *dir, uint8_t i, KernelObjectTyped** memb); + +/**@FUNC Returns the number of populated entries this directory holds. + * @PARAM dir directory to check + * @RETURN number of entries. negative return values indicate an error.*/ +int jove_objdir_nmemb(KernelObjectDirectory *dir); + +/**@FUNC Gets the highest populated index in a given directory. + * @PARAM dir directory to check. + * @RETURN last populated entry. negative return values indicate an error.*/ +int jove_objdir_lastmemb(KernelObjectDirectory *dir); + +/**@FUNC Gets the kernel object at a given index. + * This function only checks the cached result. If the directory has changed + * without updating the cache, jove_objdir_sync MUST be called first. + * + * @PARAM dir directory to check in. + * @PARAM index index to check. + * @RETURN the object at the given index. NULL if the spot is empty.*/ +KernelObjectTyped *jove_objdir_get(KernelObjectDirectory *dir, uint8_t index); + +/**@FUNC Moves a kernel object in this directory to a different place/directory. + * @PARAM dir directory holding the object. + * @PARAM memb member index of the object. + * @PARAM dest_dir destination directory. + * @PARAM dest_memb destination member.*/ +JoveError jove_objdir_move( + KernelObjectDirectory *dir, + uint8_t memb, + KernelObjectDirectory *dest_dir, + uint8_t dest_memb); + +JoveError jove_object_move( + KernelObjectTyped *typed, + KernelObjectDirectory *dest_dir, + uint8_t dest_memb); + +JoveError jove_object_move_inplace( + KernelObjectTyped *typed, + KernelObjectTyped *dest); + #endif diff --git a/lib/libjove/include/object-untyped.h b/lib/libjove/include/object-untyped.h index ea1185d..e7715b0 100644 --- a/lib/libjove/include/object-untyped.h +++ b/lib/libjove/include/object-untyped.h @@ -2,38 +2,73 @@ #define _LIBJOVE_OBJECT_UNTYPED_H 1 #include <jove/object-typed.h> +#include <jove/object-dir.h> /**@STRUCT Represents a KO_MEMOY_UNTYPED*/ -typedef struct KernelObjectUntyped +typedef struct _KernelObjectUntyped { KernelObjectTyped typed; - size_t bytes, alignment; + size_t bytes; + intmax_t alignment; + + KernelObjectTyped *children_head; + KernelObjectTyped *sibling; } KernelObjectUntyped; -/**@FUNC Gets the size of the given untyped memory block. - * @PARAM untyped block of memory to get size of. - * @PARAM bytes address to put size variable into. - * @RETURN error code. 0 on success.*/ -int jove_untyped_size(KernelObjectUntyped *untyped, size_t *bytes); - -/**@FUNC Splits an untyped block of memory into a given size and the remainder. - * @PARAM untyped block of memory to split. - * @PARAM bytes number of bytes to split for. - * @PARAM dest destination slot to place the new block. - * @RETURN error code. 0 on success.*/ -int jove_untyped_split(KernelObjectUntyped *untyped, size_t bytes, KernelObjectUntyped *dest); - -/**@FUNC Merges two untyped memory blocks into a single memory block. - * The two blocks are expected to be adjacent. - * If successful, b is merged _into_ a and becomes empty. - * @PARAM a first block. - * @PARAM b second block. - * @RETURN error code. 0 on success.*/ -int jove_untyped_merge(KernelObjectUntyped *a, KernelObjectUntyped *b); - -/**@FUNC Gets the page alignment of the given untyped memory block. - * @PARAM untyped block of memory to get alignment of. - * @PARAM align pointer to returned value. - * @RETURN error code. 0 on success.*/ -int jove_untyped_alignment(KernelObjectUntyped *untyped, size_t *align); +/**@FUNC INTERNAL FUNCTION DO NOT USE. + * Initializes a block of memory as an untyped object. + * @PARAM untyped pointer to new block of memory. + * @PARAM parent directory this new object is a member of. + * @PARAM membi index to place this new object.*/ +void _jove_alloc_untyped_inplace(KernelObjectUntyped *untyped, struct _KernelObjectDirectory *parent, uint8_t membi); + +/**@FUNC INTERNAL FUNCTION DO NOT USE. + * Allocates a block of memory representing an untyped object into the heap. + * @PARAM parent directory this new object is a member of. + * @PARAM membi index to place this new object. + * @RETURN pointer to allocated object. NULL on failure. + * Possible failures: + * EJOVE_NOALLOC: libjove does not have an allocator set yet. + * EJOVE_FULL: destination is already taken.*/ +KernelObjectUntyped *_jove_alloc_untyped(struct _KernelObjectDirectory *parent, uint8_t membi); + +/**@FUNC Changes pointer type of typed object to untyped if correct. + * @PARAM typed pointer to convert. + * @RETURN pointer as KernelObjectUntyped*, NULL on failure. + * Possible failures: + * EJOVE_BADOBJ: passed object is not an untyped.*/ +KernelObjectUntyped *jove_object_as_untyped(KernelObjectTyped *typed); + +/**@FUNC Gets the number of bytes a given untyped block represents. + * @PARAM untyped block of untyped memory. + * @RETURN number of bytes. negative on failure. + * Possible failures: + * EJOVE_BADOBJ: passed object does not exist / is not an untyped. */ +int jove_untyped_size(KernelObjectUntyped *untyped); + +/**@FUNC Gets the byte alignment of a given untyped block up to a page. + * @PARAM untyped block of untyped memory. + * @RETURN alignment in bytes. negative on failure.*/ +int jove_untyped_alignment(KernelObjectUntyped *untyped); + +/**@FUNC Splits a given untyped block of memory into a block with the given size + * and the remainder. New untyped object is stored in dest at destmemb. + * @PARAM untyped block of untyped memory to split. + * @PARAM bytes number of bytes the new block should have. + * Minimum sizeof(size_t) + * @PARAM dest directory to store the new block. + * @PARAM destmemb index in dest to store new block. + * @RETURN Newly created block of memory. NULL on failure. + * Possible failures: + * EJOVE_BADSIZE: bytes < sizeof(size_t) + * EJOVE_BADOBJ: dest or untyped are incorrect types / do not exist.*/ +KernelObjectUntyped *jove_untyped_split( + KernelObjectUntyped *untyped, size_t bytes, + KernelObjectDirectory *dest, uint8_t destmemb); + +JoveError jove_untyped_split_inplace( + KernelObjectUntyped *untyped, + size_t bytes, + KernelObjectUntyped *dest); + #endif diff --git a/lib/libjove/include/syscall.h b/lib/libjove/include/syscall.h index 432be85..5d872a3 100644 --- a/lib/libjove/include/syscall.h +++ b/lib/libjove/include/syscall.h @@ -7,25 +7,28 @@ #include <jove/object.h> #define SYSCALL_PAYLOAD_PUTL(buf, at, v, type) \ - if(at + sizeof(type) > KO_MESSAGE_BYTES) return -1; \ + if(at + sizeof(type) > KO_MESSAGE_BYTES) return EJOVE_TOOBIG; \ *((type*)(&buf[at])) = v; \ at += sizeof(type) #define SYSCALL_PAYLOAD_SAVEPTR(buf, at, type, val) \ - if(at + sizeof(type) >= KO_MESSAGE_BYTES) return -1; \ + if(at + sizeof(type) >= KO_MESSAGE_BYTES) return EJOVE_TOOBIG; \ val = (type*)(&buf[at]); \ at += sizeof(type) #define SYSCALL_PAYLOAD_PUTOBJ(buf, at, obj) \ at = path_tobuf(JOVE_OBJECT_TYPED(obj), buf, at, KO_MESSAGE_BYTES); \ - if(at < 0) return at + if(at < 0) return -at int _syscall_invoke(void); void _syscall_debug_putc(char c); -int _syscall_invoke_objdir_nmemb(KernelObjectDirectory *dir, uint8_t *result); int _syscall_invoke_objdir_getmemb(KernelObjectDirectory *dir, uint8_t member, obj_type_t *result); +int _syscall_invoke_objdir_lastmemb(KernelObjectDirectory *dir, uint8_t *result); +int _syscall_invoke_objdir_move( + KernelObjectDirectory *dir, uint8_t memb, + KernelObjectDirectory *dest_dir, uint8_t dest_memb); int _syscall_invoke_untyped_size(KernelObjectUntyped *untyped, size_t *bytes); int _syscall_invoke_untyped_split(KernelObjectUntyped *path, size_t bytes, KernelObjectUntyped *dest); diff --git a/lib/libjove/libjove.c b/lib/libjove/libjove.c index fe1c080..5ad45ac 100644 --- a/lib/libjove/libjove.c +++ b/lib/libjove/libjove.c @@ -1,8 +1,15 @@ #include "include/jove.h" +#include "error.h" uintmax_t _syscall_message_box = 0; void *_syscall_message_ptr = 0; +JoveError jove_errno; + +void *(*_jove_alloc)(size_t) = NULL; +void (*_jove_free)(void*) = NULL; +void *(*_jove_realloc)(void*, size_t) = NULL; + void libjove_init(uint64_t box, void *boxptr) { diff --git a/lib/libjove/object/directory.c b/lib/libjove/object/directory.c index a9487e8..9c12d5b 100644 --- a/lib/libjove/object/directory.c +++ b/lib/libjove/object/directory.c @@ -1,4 +1,191 @@ +#include "object-dir.h" #include <object.h> +#include <jove.h> #include <syscall.h> KernelObjectDirectory __rootdir; + +KernelObjectDirectory* +jove_object_as_objdir(KernelObjectTyped *typed) +{ + if(typed->type == KO_OBJECT_DIRECTORY) return (KernelObjectDirectory*)typed; + return NULL; +} + +void +_jove_alloc_objdir_inplace( + KernelObjectDirectory *dir, + KernelObjectDirectory *parent, + uint8_t memb) +{ + *dir = (KernelObjectDirectory) { + .typed = (KernelObjectTyped) { + .parent = parent, + .membi = memb, + .type = KO_OBJECT_DIRECTORY + }, + .lastmemb = 0, + .firstfree = 0, + .children = { 0 } + }; + + parent->children[memb] = JOVE_OBJECT_TYPED(dir); +} + +KernelObjectDirectory* +_jove_alloc_objdir( + KernelObjectDirectory *parent, + uint8_t memb) +{ + if(!_jove_alloc) { + jove_errno = EJOVE_NOALLOC; + return NULL; + } + if(parent->children[memb]) { + jove_errno = EJOVE_FULL; + return NULL; + } + + KernelObjectDirectory *dir = _jove_alloc(sizeof(KernelObjectDirectory)); + if(dir == NULL) return NULL; + + _jove_alloc_objdir_inplace(dir, parent, memb); + jove_errno = 0; + return dir; +} + +JoveError +jove_objdir_sync(KernelObjectDirectory *dir) +{ + if(dir->lastmemb) return dir->lastmemb; + + int kerr = _syscall_invoke_objdir_lastmemb(dir, &dir->lastmemb); + jove_errno = jove_error_from_kerror(kerr); + + return dir->lastmemb; +} + +extern JoveError +_jove_objdir_sync_at_arch( + KernelObjectDirectory *dir, + uint8_t i, + obj_type_t type, + KernelObjectTyped **memb + ); + +JoveError +jove_objdir_sync_at(KernelObjectDirectory *dir, uint8_t i, KernelObjectTyped** memb) +{ + obj_type_t type; + int err = _syscall_invoke_objdir_getmemb(dir, i, &type); + if(err != 0) return err; + + KernelObjectTyped *dirmemb = dir->children[i]; + if(dirmemb != NULL) { + if(dirmemb->type == type) { + if(memb) *memb = dirmemb; + return EJOVE_OK; + } + if(_jove_free == NULL) { + return EJOVE_NOFREE; + } + _jove_free(dirmemb); + } + if(_jove_alloc == NULL) + return EJOVE_NOALLOC; + + switch(type) { + case KO_NONE: + return EJOVE_OK; + case KO_OBJECT_DIRECTORY: + dirmemb = JOVE_OBJECT_TYPED(_jove_alloc_objdir(dir, i)); + if(memb) *memb = dirmemb; + break; + case KO_MEMORY_UNTYPED: + { + dirmemb = JOVE_OBJECT_TYPED(_jove_alloc_untyped(dir, i)); + if(memb) *memb = dirmemb; + break; + } + default: + return _jove_objdir_sync_at_arch(dir, i, type, memb); + } + return EJOVE_OK; +} + +int +jove_objdir_nmemb(KernelObjectDirectory *dir) +{ + int nmemb = 0; + for(unsigned i = 1; i < 256; i++) { + if(dir->children[i] != NULL) nmemb++; + } + return nmemb; +} + +int +jove_objdir_lastmemb(KernelObjectDirectory *dir) +{ + if(dir->lastmemb) return dir->lastmemb; + JoveError err = jove_error_from_kerror(_syscall_invoke_objdir_lastmemb(dir, &dir->lastmemb)); + if(err) { + jove_errno = err; + return 0; + } + return dir->lastmemb; +} + +KernelObjectTyped* +jove_objdir_get(KernelObjectDirectory *dir, uint8_t i) +{ + return dir->children[i]; +} + +JoveError +jove_objdir_move( + KernelObjectDirectory *dir, + uint8_t memb, + KernelObjectDirectory *dest_dir, + uint8_t dest_memb) +{ + if(!memb) + return EJOVE_BADOBJ; + if(!dir->children[memb]) + return EJOVE_BADOBJ; + + if(dest_memb) + return EJOVE_BADOBJ; + if(dest_dir->children[dest_memb]) + return EJOVE_FULL; + + int kerr = _syscall_invoke_objdir_move(dir, memb, dest_dir, dest_memb); + if(kerr) return jove_error_from_kerror(kerr); + + KernelObjectTyped *move = dir->children[memb]; + dir->children[memb] = NULL; + dest_dir->children[dest_memb] = move; + + if(dir->lastmemb == move->membi) { + dir->lastmemb = 0; + } + + move->parent = dest_dir; + move->membi = dest_memb; + return EJOVE_OK; +} + +JoveError jove_object_move( + KernelObjectTyped *typed, + KernelObjectDirectory *dest_dir, + uint8_t dest_memb) +{ + return jove_objdir_move(typed->parent, typed->membi, dest_dir, dest_memb); +} + +JoveError jove_object_move_inplace( + KernelObjectTyped *typed, + KernelObjectTyped *dest) +{ + return jove_objdir_move(typed->parent, typed->membi, dest->parent, dest->membi); +} + diff --git a/lib/libjove/object/untyped.c b/lib/libjove/object/untyped.c new file mode 100644 index 0000000..281bb60 --- /dev/null +++ b/lib/libjove/object/untyped.c @@ -0,0 +1,127 @@ +#include <jove.h> +#include <object.h> +#include <syscall.h> +#include <error.h> +#include <string.h> + +void +_jove_alloc_untyped_inplace( + KernelObjectUntyped *untyped, + KernelObjectDirectory *parent, + uint8_t membi + ) +{ + *untyped = (KernelObjectUntyped) { + .typed = (KernelObjectTyped) { + .type = KO_MEMORY_UNTYPED, + .parent = parent, + .membi = membi + }, + .bytes = 0, + .alignment = -1, + .children_head = NULL, + .sibling = NULL + }; + + parent->children[membi] = (KernelObjectTyped*)untyped; + parent->lastmemb = 0; +} + +KernelObjectUntyped* +_jove_alloc_untyped(KernelObjectDirectory *parent, uint8_t membi) +{ + if(_jove_alloc == NULL) { + jove_errno = EJOVE_NOALLOC; + return NULL; + } + if(parent->children[membi] != NULL) { + jove_errno = EJOVE_FULL; + } + + KernelObjectUntyped *untyped = _jove_alloc(sizeof(KernelObjectUntyped)); + + _jove_alloc_untyped_inplace(untyped, parent, membi); + return untyped; +} + +KernelObjectUntyped* +jove_object_as_untyped(KernelObjectTyped *typed) +{ + if(typed->type == KO_MEMORY_UNTYPED) return (KernelObjectUntyped*)typed; + jove_errno = EJOVE_BADOBJ; + return NULL; +} + +int +jove_untyped_size(KernelObjectUntyped *untyped) +{ + if(untyped->bytes != 0) + return untyped->bytes; + + int e = _syscall_invoke_untyped_size(untyped, &untyped->bytes); + if(e) return jove_error_from_kerror(e); + + return untyped->bytes; +} + +int +jove_untyped_alignment(KernelObjectUntyped *untyped) +{ + if(untyped->alignment >= 0) + return untyped->alignment; + + int e = _syscall_invoke_untyped_alignment(untyped, (size_t*)&untyped->alignment); + if(e) return jove_error_from_kerror(e); + + return untyped->alignment; +} + +KernelObjectUntyped* +jove_untyped_split( + KernelObjectUntyped *untyped, + size_t bytes, + KernelObjectDirectory *dest, + uint8_t destmemb + ) +{ + if(!_jove_alloc) { + jove_errno = EJOVE_NOALLOC; + return NULL; + } + + KernelObjectUntyped temp; + _jove_alloc_untyped_inplace(&temp, dest, destmemb); + + jove_errno = jove_untyped_split_inplace(untyped, bytes, &temp); + if(jove_errno) return NULL; + + KernelObjectUntyped *newuntyped = _jove_alloc(sizeof(KernelObjectUntyped)); + memcpy(newuntyped, &temp, sizeof(KernelObjectUntyped)); + + dest->children[destmemb] = JOVE_OBJECT_TYPED(newuntyped); + return newuntyped; +} + +JoveError jove_untyped_split_inplace( + KernelObjectUntyped *untyped, + size_t bytes, + KernelObjectUntyped *dest) +{ + if(jove_untyped_size(untyped) - sizeof(size_t) <= bytes) { + return EJOVE_BADSIZE; + } + if(bytes < sizeof(size_t)) { + return EJOVE_BADSIZE;; + } + + int e = _syscall_invoke_untyped_split(untyped, bytes, dest); + if(e) { + return jove_error_from_kerror(e); + } + + dest->bytes = bytes; + dest->alignment = -1; + untyped->bytes -= bytes; + + return EJOVE_OK; +} diff --git a/lib/libjove/syscall/invoke-objdir.c b/lib/libjove/syscall/invoke-objdir.c index 462c282..6ee39e4 100644 --- a/lib/libjove/syscall/invoke-objdir.c +++ b/lib/libjove/syscall/invoke-objdir.c @@ -22,18 +22,39 @@ _syscall_invoke_objdir_getmemb(KernelObjectDirectory *dir, uint8_t member, obj_t } int -_syscall_invoke_objdir_nmemb(KernelObjectDirectory *dir, uint8_t *result) +_syscall_invoke_objdir_lastmemb(KernelObjectDirectory *dir, uint8_t *result) { uint8_t *syscallData = _syscall_message_ptr; int syscall_at = 0; uint8_t *syscall_result; SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, dir); - SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_OBJDIR_NMEMB, uint8_t); + SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_OBJDIR_LASTMEMB, uint8_t); SYSCALL_PAYLOAD_SAVEPTR(syscallData, syscall_at, uint8_t, syscall_result); int status = _syscall_invoke(); *result = *syscall_result; - return status; } + +int +_syscall_invoke_objdir_move( + KernelObjectDirectory *dir, + uint8_t memb, + KernelObjectDirectory *dest_dir, + uint8_t dest_memb) +{ + uint8_t *syscallData = _syscall_message_ptr; + int syscall_at = 0; + + SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, dir); + SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, INVOKE_OBJDIR_MOVE, uint8_t); + SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, memb, uint8_t); + + size_t *dest_pathw = (size_t*)(syscallData + syscall_at); + SYSCALL_PAYLOAD_PUTOBJ(syscallData, syscall_at, dest_dir); + (*dest_pathw)++; + SYSCALL_PAYLOAD_PUTL(syscallData, syscall_at, dest_memb, uint8_t); + + return _syscall_invoke(); +} diff --git a/sysroot/boot/initrd.tar b/sysroot/boot/initrd.tar Binary files differindex b893e9b..171b978 100644 --- a/sysroot/boot/initrd.tar +++ b/sysroot/boot/initrd.tar |