diff options
author | Jon Santmyer <jon@jonsantmyer.com> | 2025-08-10 15:40:19 -0400 |
---|---|---|
committer | Jon Santmyer <jon@jonsantmyer.com> | 2025-08-10 15:40:19 -0400 |
commit | c4f8ef91f18d854a4ede7a94e95b2eab898d6963 (patch) | |
tree | c2772c4f380a684b6fa347f03b13f9476bf9500c | |
parent | b905869a35f062a4e5072f10bec3a2ba3db0e365 (diff) | |
download | jove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.tar.gz jove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.tar.bz2 jove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.zip |
working usermode objdir iteration
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | arch/x86_64/lock.s | 19 | ||||
-rw-r--r-- | arch/x86_64/memory.c | 16 | ||||
-rw-r--r-- | arch/x86_64/page_directory.c | 11 | ||||
-rw-r--r-- | arch/x86_64/processor.c | 12 | ||||
-rw-r--r-- | arch/x86_64/sse.s | 46 | ||||
-rw-r--r-- | arch/x86_64/syscall-invoke-mapping.c | 124 | ||||
-rw-r--r-- | arch/x86_64/syscall.c | 32 | ||||
-rw-r--r-- | arch/x86_64/untyped_retype_page.c | 13 | ||||
-rw-r--r-- | arch/x86_64/usermode.c | 38 | ||||
-rw-r--r-- | config.mk | 30 | ||||
-rw-r--r-- | device/initrd.c | 4 | ||||
-rw-r--r-- | device/uart.c | 5 | ||||
-rw-r--r-- | include/arch/x86_64/object.h | 12 | ||||
-rw-r--r-- | include/arch/x86_64/page.h | 8 | ||||
-rw-r--r-- | include/arch/x86_64/syscall.h | 18 | ||||
-rw-r--r-- | include/device/uart.h | 3 | ||||
-rw-r--r-- | include/error.h | 17 | ||||
-rw-r--r-- | include/lock.h | 20 | ||||
-rw-r--r-- | include/memory.h | 3 | ||||
-rw-r--r-- | include/object.h | 22 | ||||
-rw-r--r-- | include/print.h | 2 | ||||
-rw-r--r-- | include/syscall.h | 44 | ||||
-rw-r--r-- | lib/objdir.c | 36 | ||||
-rw-r--r-- | lib/print.c | 2 | ||||
-rw-r--r-- | lib/printpath.c | 9 | ||||
-rw-r--r-- | syscall/handler.c | 76 | ||||
-rw-r--r-- | syscall/handles.h | 21 | ||||
-rw-r--r-- | syscall/invoke-untyped.c | 96 | ||||
-rw-r--r-- | syscall/invoke_objdir.c | 94 |
30 files changed, 683 insertions, 154 deletions
@@ -24,8 +24,8 @@ all: $(BIN) .PHONY: clean clean: - rm $(OBJFILES) - rm $(BIN) + -rm $(OBJFILES) + -rm $(BIN) $(BIN): ${OBJFILES} $(LD) $(LDFLAGS) ${OBJFILES} -o $(BIN) diff --git a/arch/x86_64/lock.s b/arch/x86_64/lock.s new file mode 100644 index 0000000..b63f078 --- /dev/null +++ b/arch/x86_64/lock.s @@ -0,0 +1,19 @@ +.global _mtx_acquire +.type _mtx_acquire @function +_mtx_acquire: + lock btsw $0, (%rdi) + jc .spin + ret +.spin: + pause + testb $1, (%rdi) + jnz .spin + jmp _mtx_acquire +.size _mtx_acquire, . - _mtx_acquire + +.global _mtx_release +.type _mtx_release @function +_mtx_release: + movb $0, (%rdi) + ret +.size _mtx_release, . - _mtx_release diff --git a/arch/x86_64/memory.c b/arch/x86_64/memory.c new file mode 100644 index 0000000..b32d4e7 --- /dev/null +++ b/arch/x86_64/memory.c @@ -0,0 +1,16 @@ +#include "memory.h" +#include "arch/x86_64/page.h" +#include <stdint.h> + +void* +ko_entry_data(objdir_entry_t *entry) +{ + if((intmax_t)entry->data < 0) return (void*)entry->data; + return vmem_phys_tovirt(entry->data); +} + +uintptr_t +ko_data_toentry(uintptr_t vptr) +{ + return vmem_ident_tophys((void*)vptr); +} diff --git a/arch/x86_64/page_directory.c b/arch/x86_64/page_directory.c index 0506703..bcc71cf 100644 --- a/arch/x86_64/page_directory.c +++ b/arch/x86_64/page_directory.c @@ -6,6 +6,7 @@ #include "object.h" #include "string.h" #include "jove.h" +#include <stdint.h> physptr_t s_kpbase(void); @@ -45,6 +46,12 @@ pmle_get_page(pmle_t entry) return vmem_phys_tovirt(pptr); } +uint8_t +pmle_level(pmle_t entry) +{ + return entry.osflg; +} + __attribute__((aligned(0x1000))) pmle_t s_kernel_pml4[512]; // Page L4 __attribute__((aligned(0x1000))) pmle_t s_kernel_pml3[512]; // Page L3 __attribute__((aligned(0x1000))) pmle_t s_kernel_pml2[512]; // Page directory @@ -107,8 +114,8 @@ vmem_setup(void) //Add page mapping object to init directory. uint8_t pm_i = _initDirectory.self.data++; _initDirectory.entries[pm_i] = (objdir_entry_t) { - .type = KO_MEMORY_MAPPING_PAGE, - .data = kernel_pml4_base + .type = KO_MEMORY_MAPPING, + .data = kernel_pml4_base | 3 }; _initData.pm_object = pm_i; } diff --git a/arch/x86_64/processor.c b/arch/x86_64/processor.c index b39ba63..666eb3d 100644 --- a/arch/x86_64/processor.c +++ b/arch/x86_64/processor.c @@ -88,9 +88,21 @@ processor_setup(void *_processor) (uint32_t)((uintptr_t)_processor >> 32)); } +void enable_fpu(void); +void enable_sse(void); +void enable_avx(void); + void bsp_setup(void) { +#ifdef ENABLE_SSE + enable_fpu(); + enable_sse(); +#endif +#ifdef ENABLE_AVX + enable_avx(); +#endif + uint64_t pd_i = _initDirectory.self.data++; _initDirectory.entries[pd_i] = (objdir_entry_t) { diff --git a/arch/x86_64/sse.s b/arch/x86_64/sse.s new file mode 100644 index 0000000..8065188 --- /dev/null +++ b/arch/x86_64/sse.s @@ -0,0 +1,46 @@ +.global enable_fpu +.type enable_fpu @function +enable_fpu: + fninit + fldcw [fcw_init] + ret +.size enable_fpu, . - enable_fpu + +.global enable_sse +.type enable_sse @function +enable_sse: + movq %cr0, %rax + //Disable coprocessor emulation + and $0xFFFB, %ax + //Set coprocessor monitoring + or $0x22, %ax + //Save cr0 + movq %rax, %cr0 + movq %cr4, %rax + //Set CR4.OSFXR and CR4.OSXMMEXCEPT + or $3 << 9, %ax + movq %rax, %cr4 + ret +.size enable_sse, . - enable_sse + +.global enable_avx +.type enable_avx, @function +enable_avx: + pushq %rax + pushq %rcx + pushq %rdx + + xorq %rcx, %rcx + xgetbv + or $7, %eax + xsetbv + + popq %rdx + popq %rcx + popq %rax + ret +.size enable_avx, . - enable_avx + +.data +fcw_init: + .word 0x037F diff --git a/arch/x86_64/syscall-invoke-mapping.c b/arch/x86_64/syscall-invoke-mapping.c new file mode 100644 index 0000000..efecbdf --- /dev/null +++ b/arch/x86_64/syscall-invoke-mapping.c @@ -0,0 +1,124 @@ +#include "syscall/handles.h" +#include "arch/x86_64/syscall.h" +#include "arch/x86_64/page.h" +#include <stddef.h> +#include "error.h" +#include "lock.h" + +static int +s_handle_invoke_mapping_release( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + target_entry->data = 0; + target_entry->type = KO_NONE; + return 0; +} + +static int +s_handle_invoke_mapping_get( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + pmli_t pmli; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t); + + if(pmli > 511) return -KE_OOB; + + uint8_t level = target_entry->data & 3; + pmle_t *target_pml = (pmle_t*)vmem_phys_tovirt(target_entry->data & ~3ULL); + if(level == 3 && pmli > 255) return -KE_OOB; + if(level == 0) return -KE_BADOBJ; + + size_t dest_pathw; + objdir_entry_t *dest_entry; + SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, dest_pathw, dest_entry); + if(dest_entry->type != KO_NONE) return -KE_FULL; + + pmle_t pmle = target_pml[pmli]; + if(!pmle.p) return -KE_DNE; + + *dest_entry = (objdir_entry_t) { + .type = KO_MEMORY_MAPPING, + .data = (((uintptr_t)target_pml[pmli].paddr) << 12ULL) | (level - 1) + }; + return 0; +} + +static int +s_handle_invoke_mapping_map( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + uint8_t level = target_entry->data & 3; + pmle_t *target_pml = (pmle_t*)vmem_phys_tovirt(target_entry->data & ~3ULL); + + pmli_t pmli; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, pmli, pmli_t); + + if(pmli > 511) return -KE_OOB; + if(level == 3 && pmli > 255) return -KE_OOB; + + size_t untyped_pathw; + objdir_entry_t *untyped_entry; + SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, untyped_pathw, untyped_entry); + + if(untyped_entry->type != KO_MEMORY_UNTYPED) return -KE_BADOBJ; + mtx_acquire(&untyped_entry->lock); + + if((untyped_entry->data & 0xFFF) != 0) { + mtx_release(&untyped_entry->lock); + return -KE_ALIGN; + } + size_t *untyped_data = (size_t*)untyped_entry->data; + size_t untyped_size = *untyped_data; + if(untyped_size != 0x1000) { + mtx_release(&untyped_entry->lock); + return -KE_BADSIZE; + } + + pmle_t pmle = target_pml[pmli]; + if(pmle.p) { + mtx_release(&untyped_entry->lock); + return -KE_OCCUPIED; + } + + target_pml[pmli].value = vmem_ident_tophys((void*)untyped_entry->data) | PAGE_RW | PAGE_US | PAGE_PRESENT; + untyped_entry->type = KO_MEMORY_MAPPING; + untyped_entry->data |= level - 1; + + mtx_release(&untyped_entry->lock); + return 0; +} + +static int (*s_invoke_handles[])(objdir_t*, objdir_entry_t*, uint8_t*, size_t) = { + [INVOKE_MAPPING_RELEASE] = s_handle_invoke_mapping_release, + [INVOKE_MAPPING_GET] = s_handle_invoke_mapping_get, + [INVOKE_MAPPING_MAP] = s_handle_invoke_mapping_map, +}; + +static size_t s_invoke_handles_count = sizeof(s_invoke_handles) / sizeof(void*); + +int +syscall_handle_invoke_mapping( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at + ) +{ + uint8_t funcid; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, funcid, uint8_t); + + if(funcid >= s_invoke_handles_count) return -KE_BADFUNC; + return s_invoke_handles[funcid](root_dir, target, payload, payload_at); +} diff --git a/arch/x86_64/syscall.c b/arch/x86_64/syscall.c index a563525..5582336 100644 --- a/arch/x86_64/syscall.c +++ b/arch/x86_64/syscall.c @@ -1,6 +1,36 @@ #include "arch/x86_64/processor.h" +#include "syscall/handles.h" +#include "print.h" +#include "lock.h" +#include "error.h" #include <stddef.h> - + +static inline int +s_invoke_release( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at, + int (*invoke)(objdir_t*, objdir_entry_t*, uint8_t*, size_t)) +{ + int e = invoke(root_dir, target, payload, payload_at); + mtx_release(&target->lock); + return e; +} + +int +_syscall_handler_arch(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at) +{ + switch(target->type) { + case KO_MEMORY_MAPPING: + return s_invoke_release(root_dir, target, payload, payload_at, syscall_handle_invoke_mapping); + default: + klogf("Missing implementation of invoke for type %i\n", target->type); + mtx_release(&target->lock); + return -KE_BADTYPE; + } +} + __attribute__((naked)) void _syscall_entry(void) { diff --git a/arch/x86_64/untyped_retype_page.c b/arch/x86_64/untyped_retype_page.c index 216d88d..32afe2c 100644 --- a/arch/x86_64/untyped_retype_page.c +++ b/arch/x86_64/untyped_retype_page.c @@ -36,16 +36,3 @@ int untyped_retype_page(objdir_entry_t *untyped_entry, void **dest) #endif return r; } - -int -untyped_retype_kernel_stack(objdir_entry_t *untyped_entry, objdir_entry_t *dest_entry) -{ - int r = s_untyped_retype(untyped_entry, KERNEL_STACK_SIZE, 1, (void**)(&dest_entry->data)); - if(r != 0) return r; - - dest_entry->type = KO_KERNEL_STACK; - #ifdef DBG_MEM - klogf("Untyped block %p retyped to kernel stack at %p\n", untyped_entry->data, dest_entry->data); - #endif - return r; -} diff --git a/arch/x86_64/usermode.c b/arch/x86_64/usermode.c index 9ce5ed3..66a641c 100644 --- a/arch/x86_64/usermode.c +++ b/arch/x86_64/usermode.c @@ -1,12 +1,10 @@ #include "arch/x86_64/object.h" #include "object.h" -#include "memory.h" #include "bootargs.h" #include "device/initrd.h" #include "object.h" #include "panic.h" #include "string.h" -#include "print.h" #include "device/processor.h" #include "arch/x86_64/page.h" @@ -28,23 +26,6 @@ s_new_mapping(objdir_t *untyped_dir) return 0; } -static uintptr_t -s_new_kstack(objdir_t *untyped_dir, objdir_entry_t *dest_entry) -{ - objdir_entry_t *untyped_entry = NULL; - for(int i = 1; i < OBJECT_DIRECTORY_MAX_ENTRIES; i++) { - untyped_entry = &untyped_dir->entries[i]; - if(untyped_entry->type != KO_MEMORY_UNTYPED) continue; - - int err = untyped_retype_kernel_stack(untyped_entry, dest_entry); - if(err != 0) continue; - - uintptr_t ptr = dest_entry->data; - return (uintptr_t)vmem_phys_tovirt(ptr); - } - return 0; -} - static pmle_t* s_ensure_mapping_layer(pmle_t *pml, objdir_t *untyped_dir, uintptr_t addr, uint8_t layer) { @@ -60,13 +41,14 @@ s_ensure_mapping_layer(pmle_t *pml, objdir_t *untyped_dir, uintptr_t addr, uint8 .p = 1, .rw = 1, .us = 1, + .osflg = (layer - 1) & 3, .paddr = table_phys >> 12 }; __asm__ volatile("invlpg (%0)":: "r"(table_phys)); return vmem_phys_tovirt(table_phys); } -static void +static uintptr_t s_map_page(pmle_t *pml4, objdir_t *untyped_dir, uintptr_t addr) { pmle_t *pml3 = s_ensure_mapping_layer(pml4, untyped_dir, addr, 4); @@ -82,9 +64,11 @@ s_map_page(pmle_t *pml4, objdir_t *untyped_dir, uintptr_t addr) .p = 1, .rw = 1, .us = 1, + .osflg = 0, .paddr = pptr >> 12 }; __asm__ volatile("invlpg (%0)":: "r"(addr)); + return pptr; } __attribute__((noreturn)) @@ -114,11 +98,9 @@ init_load(void) } size_t tcb_diri = _initDirectory.self.data++; - size_t kstack_diri = _initDirectory.self.data++; size_t message_diri = _initDirectory.self.data++; _initData.tcb_object = tcb_diri; - _initData.kernel_stack_object = kstack_diri; _initData.message_object = message_diri; _initDirectory.entries[tcb_diri] = (objdir_entry_t) { @@ -130,7 +112,7 @@ init_load(void) objdir_t *untyped_dir = (objdir_t*)_initDirectory.entries[untyped_diri].data; size_t pml4_diri = _initData.pm_object; - pmle_t *pml4 = vmem_phys_tovirt(_initDirectory.entries[pml4_diri].data); + pmle_t *pml4 = vmem_phys_tovirt(_initDirectory.entries[pml4_diri].data & ~3ULL); //Reserve and map pages for init binary size_t init_size = initrd_file_size(init_header); @@ -150,11 +132,7 @@ init_load(void) uintptr_t sp = stack_base + 0xFF0; //Create a kernel stack for the init TCB - uintptr_t ksp_base = (uintptr_t)s_new_kstack(untyped_dir, &_initDirectory.entries[kstack_diri]); - _initDirectory.entries[kstack_diri] = (objdir_entry_t) { - .type = KO_KERNEL_STACK, - .data = ksp_base - }; + uintptr_t ksp_base = (uintptr_t)s_init_tcb.kstack; s_init_tcb.ksp = ksp_base + 0xFF0; processor_t *proc = (processor_t*)processor_current(); @@ -164,10 +142,10 @@ init_load(void) uintptr_t message_base = init_base + (init_pages << 12); message_base += ((~(message_base & 0xFFF)) & 0xFFF) + 1; - s_map_page(pml4, untyped_dir, message_base); + uintptr_t message_phys = s_map_page(pml4, untyped_dir, message_base); _initDirectory.entries[message_diri] = (objdir_entry_t) { .type = KO_MESSAGE, - .data = message_base + .data = (uintptr_t)vmem_phys_tovirt(message_phys) }; _initData.message_object_address = message_base; @@ -1,13 +1,18 @@ PROCESSORS_MAX=8 +KERNEL_STACKBYTES = 4096 + ENABLE_UART = y ENABLE_PORTIO_UART = y ENABLE_INITRD = y +ENABLE_SSE=y +ENABLE_AVX=n -DBG_MEM = y +DBG_MEM=y +DBG_SYSCALL=n +DBG_LOCK=n CFLAGS = \ -ffreestanding \ - -mno-sse \ -nostdlib \ -fno-pie \ -fno-pic \ @@ -15,6 +20,7 @@ CFLAGS = \ -D__$(TARGET_MACHINE)__ \ -D__$(TARGET_BOOTLOADER)__ \ -DPROCESSORS_MAX=$(PROCESSORS_MAX) \ + -DKERNEL_STACKBYTES=$(KERNEL_STACKBYTES) \ -Iinclude \ -I. @@ -29,12 +35,24 @@ ifeq "$(TARGET_MACHINE)" "x86_64" -mfsgsbase endif +ifeq "$(ENABLE_SSE)" "y" +CFLAGS += -DENABLE_SSE +else +CFLAGS += -mno-sse +endif + +ifeq "$(ENABLE_AVX)" "y" +CFLAGS += -DENABLE_AVX +endif + ifeq "$(ENABLE_UART)" "y" CFLAGS += -DENABLE_UART endif + ifeq "$(ENABLE_PORTIO_UART)" "y" CFLAGS += -DENABLE_PORTIO_UART endif + ifeq "$(ENABLE_INITRD)" "y" CFLAGS += -DENABLE_INITRD endif @@ -42,3 +60,11 @@ endif ifeq "$(DBG_MEM)" "y" CFLAGS += -DDBG_MEM endif + +ifeq "$(DBG_SYSCALL)" "y" +CFLAGS += -DDBG_SYSCALL +endif + +ifeq "$(DBG_LOCK)" "y" +CFLAGS += -DDBG_LOCK +endif diff --git a/device/initrd.c b/device/initrd.c index 36eefc6..1a04338 100644 --- a/device/initrd.c +++ b/device/initrd.c @@ -68,7 +68,7 @@ tar_parse(tar_block_t *block) .data = (uintptr_t)block }; - klogf("Load file '%s' at %p size %x\n", block->header.name, block + 1, file_size); + klogf("Load file '%s' at %p sie %x\n", block->header.name, block + 1, file_size); block = &block[(file_size / 512) + 1]; if(file_size % 512) block++; @@ -93,7 +93,7 @@ initrd_setup(void) .data = (uintptr_t)&s_initrd_dir }; //Add initrd dir to init object - ((init_data_t*)_initDirectory.entries[1].data)->initrd_dir = initrd_diri; + _initData.initrd_dir = initrd_diri; } int diff --git a/device/uart.c b/device/uart.c index 6728ab1..5c65207 100644 --- a/device/uart.c +++ b/device/uart.c @@ -1,10 +1,11 @@ #include "device/uart.h" #include "device/portio_uart.h" +#include "object.h" void -uart_write(objdir_t *dir, uint64_t entryi, const char *s, size_t w) +uart_write(objdir_t *dir, path_byte_t *path, const char *s, size_t w) { - objdir_entry_t *entry = objdir_seek(dir, entryi); + objdir_entry_t *entry = objdir_seek(dir, path, 1); if(entry == NULL || entry->type != KO_DEV_UART) return; #ifdef ENABLE_PORTIO_UART diff --git a/include/arch/x86_64/object.h b/include/arch/x86_64/object.h index 8d5af33..6512049 100644 --- a/include/arch/x86_64/object.h +++ b/include/arch/x86_64/object.h @@ -3,15 +3,18 @@ #include <stdint.h> +#ifndef KERNEL_STACKBYTES +#define KERNEL_STACKBYTES 4096 +#endif + typedef struct jove_InitData { uint8_t log_object; - uint8_t untyped_data_dir; - uint8_t processor_dir; + uint16_t untyped_data_dir; + uint16_t processor_dir; uint8_t pm_object; //Page mapping object. - uint8_t initrd_dir; //Init ramdisk files directory. + uint16_t initrd_dir; //Init ramdisk files directory. uint8_t tcb_object; - uint8_t kernel_stack_object; uint8_t message_object; uintptr_t message_object_address; } init_data_t; @@ -21,6 +24,7 @@ typedef struct jove_ThreadControlBlock void *stack; uintptr_t sp, ksp; void *pml4; + uint8_t kstack[KERNEL_STACKBYTES]; } tcb_t; #endif diff --git a/include/arch/x86_64/page.h b/include/arch/x86_64/page.h index 99bc691..4460720 100644 --- a/include/arch/x86_64/page.h +++ b/include/arch/x86_64/page.h @@ -4,6 +4,11 @@ #include <stdint.h> #include "include/object.h" +#define PAGE_PRESENT (1ULL << 0) +#define PAGE_RW (1ULL << 1) +#define PAGE_US (1ULL << 2) +#define PAGE_XD (1ULL << 63) + typedef union jove_PageMapLevelEntry { struct { @@ -16,7 +21,7 @@ typedef union jove_PageMapLevelEntry uint8_t d : 1; /* Dirty */ uint8_t ps_pat : 1; uint8_t g : 1; /* Global */ - uint8_t _r0 : 2; + uint8_t osflg : 2; uint8_t r : 1; uint64_t paddr : 35; uint8_t _r1; @@ -35,6 +40,7 @@ uintptr_t vmem_ident_tophys(void *vptr); void *vmem_phys_tovirt(uintptr_t pptr); void *pmle_get_page(pmle_t entry); +uint8_t pmle_level(pmle_t entry); int untyped_retype_page(objdir_entry_t *untyped_entry, void **dest_ptr); diff --git a/include/arch/x86_64/syscall.h b/include/arch/x86_64/syscall.h new file mode 100644 index 0000000..2d5060e --- /dev/null +++ b/include/arch/x86_64/syscall.h @@ -0,0 +1,18 @@ +#ifndef _JOVE_ARCH_x86_64_SYSCALL_H +#define _JOVE_ARCH_x86_64_SYSCALL_H 1 + +/**@ENUM mapping invokes*/ +enum +{ + /*[target path][u8 funcid]*/ + INVOKE_MAPPING_RELEASE = 0, + /*[target path][u8 funcid][u16 pmli][dest path]*/ + INVOKE_MAPPING_GET, + /*[target path][u8 funcid][u16 pmli][untyped path][u64 flags]*/ + INVOKE_MAPPING_MAP, + /*[target path][u8 funcid][u16 pmli][mapped path]*/ + INVOKE_MAPPING_UNMAP +}; + + +#endif diff --git a/include/device/uart.h b/include/device/uart.h index 3d481a2..9e5c3d3 100644 --- a/include/device/uart.h +++ b/include/device/uart.h @@ -1,11 +1,10 @@ #ifndef _JOVE_DEVICE_UART_H #define _JOVE_DEVICE_UART_H 1 -#include <stdint.h> #include <stddef.h> #include "object.h" -void uart_write(objdir_t *dir, uint64_t entryi, const char *s, size_t w); +void uart_write(objdir_t *dir, path_byte_t *path, const char *s, size_t w); #endif diff --git a/include/error.h b/include/error.h index 8aa087c..40a39e2 100644 --- a/include/error.h +++ b/include/error.h @@ -5,4 +5,21 @@ #define E_BADOBJ 1 #define E_ARGUMENT 2 +enum +{ + KE_OK = 0, + KE_BADOBJ, + KE_BADFUNC, + KE_BADTYPE, + KE_BADMSG, + KE_BADCALL, + KE_FULL, + KE_TOOSMALL, + KE_OOB, + KE_DNE, + KE_ALIGN, + KE_BADSIZE, + KE_OCCUPIED +}; + #endif diff --git a/include/lock.h b/include/lock.h new file mode 100644 index 0000000..412aabf --- /dev/null +++ b/include/lock.h @@ -0,0 +1,20 @@ +#ifndef _JOVE_LOCK_H +#define _JOVE_LOCK_H 1 + +void _mtx_acquire(unsigned char *mtx); +void _mtx_release(unsigned char *mtx); + +#ifdef DBG_LOCK +#include "print.h" +#define mtx_acquire(mtx) \ + klogf("Lock %p\n", mtx); \ + _mtx_acquire(mtx) +#define mtx_release(mtx) \ + klogf("Release %p\n", mtx); \ + _mtx_release(mtx) +#else +#define mtx_acquire(mtx) _mtx_acquire(mtx) +#define mtx_release(mtx) _mtx_release(mtx) +#endif + +#endif diff --git a/include/memory.h b/include/memory.h index e29c41b..7e668ae 100644 --- a/include/memory.h +++ b/include/memory.h @@ -14,4 +14,7 @@ void vmem_setup(void); int untyped_retype_kernel_stack(objdir_entry_t *untyped_entry, objdir_entry_t *dest_entry); +void *ko_entry_data(objdir_entry_t *entry); +uintptr_t ko_data_toentry(uintptr_t vptr); + #endif diff --git a/include/object.h b/include/object.h index 0a71b5f..190b082 100644 --- a/include/object.h +++ b/include/object.h @@ -14,11 +14,9 @@ enum KO_OBJECT_DIRECTORY, KO_INIT_DATA, KO_MEMORY_UNTYPED, - KO_MEMORY_MAPPED_PAGE, //4KiB Fixed Width - KO_MEMORY_MAPPING_PAGE, //4Kib Fixed Width + KO_MEMORY_MAPPING, //4KiB aligned fixed width KO_INITRD_FILE, KO_TCB, - KO_KERNEL_STACK, KO_MESSAGE, /* Device objects*/ KO_DEV_INVALID = 0x100, @@ -26,7 +24,10 @@ enum KO_DEV_UART }; -typedef uintmax_t obj_path_t; +#define KO_MESSAGE_BYTES 4096 +#define KO_MESSAGE_ALIGN 0x1000 + +typedef uint8_t path_byte_t; typedef uint16_t obj_type_t; typedef struct jove_ObjectDirectoryEntry @@ -34,10 +35,9 @@ typedef struct jove_ObjectDirectoryEntry obj_type_t type; union { struct { - char lock : 1; - char u0 : 7; - char u1; -}; + unsigned char lock; + char u0; + }; unsigned short flg; }; uintmax_t data; @@ -45,9 +45,6 @@ typedef struct jove_ObjectDirectoryEntry #define OBJECT_DIRECTORY_MAX_ENTRIES 256 -//The first entry always represents itself, which allows the kernel to ignore -//some checks. -//The data variable also contains the next free index for this directory. typedef struct jove_ObjectDirectory { union { @@ -56,6 +53,7 @@ typedef struct jove_ObjectDirectory }; } objdir_t; -objdir_entry_t *objdir_seek(objdir_t *dir, uintmax_t index); +objdir_entry_t *objdir_seek(objdir_t *dir, uint8_t *path, unsigned long pathw); +unsigned long objdir_pathw(objdir_t *dir, uint8_t *path); #endif diff --git a/include/print.h b/include/print.h index f4c942c..988333f 100644 --- a/include/print.h +++ b/include/print.h @@ -14,4 +14,6 @@ int kvprintf(const char *fmt, va_list ap); int kvsprintf(char *s, const char *fmt, va_list ap); int kvsnprintf(char *s, int size, const char *fmt, va_list ap); +void kprint_objpath(unsigned char *path, int len); + #endif diff --git a/include/syscall.h b/include/syscall.h index c9c26d8..e70ba82 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -1,9 +1,7 @@ #ifndef _JOVE_SYSCALL_H #define _JOVE_SYSCALL_H 1 -#include <stdint.h> #include <stddef.h> -#include "object.h" enum { @@ -12,35 +10,35 @@ enum SYSCALL_SEND, SYSCALL_RECV, - SYSCALL_DEBUG_PUTC, - SYSCALL_DEBUG_IDENTIFY + SYSCALL_DEBUG_PUTC }; -typedef uint16_t invokeid_t; - -struct syscallInvokeHeader -{ - obj_path_t target_path; - invokeid_t func_id; -}; +/* Generic payload of SYSCALL_INVOKE: + * [ n bytes ][ uint8_t ][ payload ] + * target entry funcid + * */ +/**@ENUM objdir invokes*/ enum { + /*[target path][u8 funcid][u8 ret]*/ INVOKE_OBJDIR_NMEMB = 0, - INVOKE_OBJDIR_GETMEMB -}; - -struct syscallInvoke_objdir_nmemb -{ - struct syscallInvokeHeader header; - size_t value; + /*[target path][u8 funcid][u8 memb][u16 ret]*/ + INVOKE_OBJDIR_GETMEMB, + /*[target path][u8 funcid][u8 ret]*/ + INVOKE_OBJDIR_LASTFREE }; - -struct syscallInvoke_objdir_getmemb +/**@ENUM untyped invokes*/ +enum { - struct syscallInvokeHeader header; - uint8_t member; - obj_type_t value; + /*[target path][u8 funcid][size_t ret]*/ + INVOKE_UNTYPED_SIZE = 0, + /*[target path][u8 funcid][dest path][dest bytes]*/ + INVOKE_UNTYPED_SPLIT, + /*[first path][u8 funcid][second path]*/ + INVOKE_UNTYPED_MERGE, + /*[target path][u8 funcid][size_t ret]*/ + INVOKE_UNTYPED_ALIGNMENT }; #endif diff --git a/lib/objdir.c b/lib/objdir.c index 665da4c..e264e5d 100644 --- a/lib/objdir.c +++ b/lib/objdir.c @@ -1,15 +1,35 @@ #include "object.h" +#include <stddef.h> -objdir_entry_t* -objdir_seek(objdir_t *dir, uintmax_t index) +static objdir_entry_t* +s_objdir_seek_rec(objdir_t *lastdir, objdir_t *dir, uint8_t *path, size_t pathw) { - uint8_t tli = index & 0xFF; - if(tli == 0) return &dir->self; + uint8_t tli = *path; + if(tli == 0 || pathw == 0) { + if(lastdir == NULL) return &dir->self; + return &lastdir->entries[path[-1]]; + } objdir_entry_t *entry = &dir->entries[tli]; - if(entry->type == KO_OBJECT_DIRECTORY) { - if(tli == index) return entry; - return objdir_seek((objdir_t*)entry->data, index >> 8); - } + if(entry->type == KO_OBJECT_DIRECTORY) + return s_objdir_seek_rec(dir, (objdir_t*)entry->data, ++path, pathw - 1); return entry; } + +objdir_entry_t* +objdir_seek(objdir_t *dir, uint8_t *path, size_t pathw) +{ + return s_objdir_seek_rec(NULL, dir, path, pathw); +} + +unsigned long +objdir_pathw(objdir_t *dir, uint8_t *path) +{ + size_t w = 0; + for(; path[w]; w++) { + uint8_t ei = path[w]; + if(dir->entries[ei].type != KO_OBJECT_DIRECTORY) return w + 1; + dir = (objdir_t*)(dir->entries[ei].data); + } + return w + 1; +} diff --git a/lib/print.c b/lib/print.c index 45c7671..a53ab4f 100644 --- a/lib/print.c +++ b/lib/print.c @@ -44,7 +44,7 @@ int kvprintf(const char *fmt, va_list ap) kvsnprintf(buffer, size, fmt, ap_dup); #ifdef ENABLE_UART - uart_write(&_initDirectory, _initData.log_object, buffer, size - 1); + uart_write(&_initDirectory, &_initData.log_object, buffer, size - 1); #endif return size; } diff --git a/lib/printpath.c b/lib/printpath.c new file mode 100644 index 0000000..5235572 --- /dev/null +++ b/lib/printpath.c @@ -0,0 +1,9 @@ +#include "print.h" +#include "object.h" + +void +kprint_objpath(path_byte_t *path, int len) +{ + kprintf("%x", *path); + for(int i = 1; i < len; i++) kprintf(":%x", path[i]); +} diff --git a/syscall/handler.c b/syscall/handler.c index efab179..6ac71da 100644 --- a/syscall/handler.c +++ b/syscall/handler.c @@ -3,64 +3,74 @@ #include "handles.h" #include "device/processor.h" #include "print.h" +#include "error.h" +#include "lock.h" +#include "memory.h" #include <stdint.h> #include <stddef.h> +extern int _syscall_handler_arch(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at); + +static inline int +s_invoke_release( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at, + int (*invoke)(objdir_t*, objdir_entry_t*, uint8_t*, size_t)) +{ + int e = invoke(root_dir, target, payload, payload_at); + return e; +} + static int -s_syscall_handle_invoke(objdir_t *root_dir, void *payload) +s_syscall_handle_invoke(objdir_t *root_dir, uint8_t *payload) { - struct syscallInvokeHeader *invokeHeader = payload; - uintmax_t target_path = invokeHeader->target_path; - objdir_entry_t *target_entry = objdir_seek(root_dir, target_path); - - klogf("target entry %x:%p func %i\n", target_path, target_entry->data, invokeHeader->func_id); + size_t payload_at = 0; + size_t target_pathw; + objdir_entry_t *target_entry; + SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, target_pathw, target_entry); - if(target_entry == NULL) return -1; switch(target_entry->type) { case KO_NONE: - return -1; + return -KE_BADOBJ; case KO_OBJECT_DIRECTORY: - return syscall_handle_invoke_objdir(root_dir, (objdir_t*)target_entry->data, payload); + return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_objdir); + case KO_MEMORY_UNTYPED: + return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_untyped); + case KO_MEMORY_MAPPING: + return s_invoke_release(root_dir, target_entry, payload, payload_at, syscall_handle_invoke_mapping); default: - klogf("Missing implementation of invoke for type %i\n", target_entry->type); - return -1; + return _syscall_handler_arch(root_dir, target_entry, payload, payload_at); } } int _syscall_handler(uintmax_t argsi, int calli) { - objdir_t *objdir = ((processor_t*)processor_current())->odir; - objdir_entry_t *payload_entry = objdir_seek(objdir, argsi); - if(payload_entry == NULL) { - klogf("Missing object for syscall %i (%x)\n", calli, argsi); - return -1; - } + objdir_t *root_dir = ((processor_t*)processor_current())->odir; + objdir_entry_t *payload_entry = objdir_seek(root_dir, (uint8_t*)&argsi, sizeof(uintmax_t)); + if(payload_entry->type != KO_MESSAGE) { klogf("Tried to invoke syscall %i with invalid object %x\n", calli, argsi); - return -1; + return -KE_BADMSG; } - - uintmax_t *payload = (void*)payload_entry->data; + mtx_acquire(&payload_entry->lock); + uint8_t *payload = ko_entry_data(payload_entry); switch(calli) { - case SYSCALL_INVOKE: return s_syscall_handle_invoke(objdir, payload); + case SYSCALL_INVOKE: { + int e = s_syscall_handle_invoke(root_dir, payload); + mtx_release(&payload_entry->lock); + return e; + } case SYSCALL_DEBUG_PUTC: kprintf("%c", (char)payload[0]); + mtx_release(&payload_entry->lock); return 0; - case SYSCALL_DEBUG_IDENTIFY: - { - objdir_entry_t *target_entry = objdir_seek(objdir, payload[0]); - if(payload_entry == NULL) { - payload[0] = KO_NONE; - } else { - payload[0] = target_entry->type; - } - return 0; - } default: klogf("Invalid syscall %i caught! Failing.\n", calli); - return -1; + mtx_release(&payload_entry->lock); + return -KE_BADCALL; } - return -1; } diff --git a/syscall/handles.h b/syscall/handles.h index f9fd79c..5b6e395 100644 --- a/syscall/handles.h +++ b/syscall/handles.h @@ -2,7 +2,26 @@ #define _JOVE_SYSCALL_HANDLES_H 1 #include "object.h" +#include <stddef.h> -int syscall_handle_invoke_objdir(objdir_t *root_dir, objdir_t *target_dir, void *payload); +#define SYSCALL_PAYLOAD_TAKEL(p, at, val, type) \ + if(sizeof(type) + at >= KO_MESSAGE_BYTES) return -KE_BADMSG; \ + val = *((type*)(&p[at])); \ + at += sizeof(type) + +#define SYSCALL_PAYLOAD_TAKEP(p, at, val, type) \ + if(sizeof(type) + at >= KO_MESSAGE_BYTES) return -KE_BADMSG; \ + val = ((type*)(&p[at])); \ + at += sizeof(type) + +#define SYSCALL_PAYLOAD_TAKEOBJ(p, at, w, o) \ + SYSCALL_PAYLOAD_TAKEL(p, at, w, size_t); \ + if(w + payload_at >= KO_MESSAGE_BYTES) return -KE_BADMSG; \ + o = objdir_seek(root_dir, &p[at], w); \ + at += w + +int syscall_handle_invoke_objdir(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at); +int syscall_handle_invoke_untyped(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at); +int syscall_handle_invoke_mapping(objdir_t *root_dir, objdir_entry_t *target, uint8_t *payload, size_t payload_at); #endif diff --git a/syscall/invoke-untyped.c b/syscall/invoke-untyped.c new file mode 100644 index 0000000..6b9199f --- /dev/null +++ b/syscall/invoke-untyped.c @@ -0,0 +1,96 @@ +#include "handles.h" +#include "syscall.h" +#include "error.h" +#include "memory.h" +#include "print.h" + +static int +s_handle_invoke_untyped_size( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at + ) +{ + size_t *dest; + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, size_t); + + size_t *untyped = ko_entry_data(target); +#ifdef DBG_SYSCALL + klogf("root_dir %p target %p data %p\n", root_dir, target, untyped); +#endif + *dest = *untyped; + return 0; +} + +static int +s_handle_invoke_untyped_alignment( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at + ) +{ + size_t *dest; + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, size_t); +#ifdef DBG_SYSCALL + klogf("root_dir %p target %p data %p\n", root_dir, target, target->data); +#endif + + *dest = target->data & 0xFFF; + return 0; +} + +static int +s_handle_invoke_untyped_split( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at + ) +{ + size_t dest_pathw; + size_t dest_bytes; + objdir_entry_t *dest_entry; + + SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, dest_pathw, dest_entry); + if(dest_entry->type != KO_NONE) return -KE_BADOBJ; + + size_t *untyped = (size_t*)target->data; + size_t untyped_size = *untyped; + + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, dest_bytes, size_t); + if(untyped_size - sizeof(size_t) <= dest_bytes) return -KE_TOOSMALL; + + size_t *split = (size_t*)(((uintptr_t)untyped) + untyped_size - dest_bytes); + *untyped -= dest_bytes; + *split = dest_bytes; + + *dest_entry = (objdir_entry_t) { + .type = KO_MEMORY_UNTYPED, + .data = (uintptr_t)split + }; + return 0; +} + +static int (*s_invoke_handles[])(objdir_t*, objdir_entry_t*, uint8_t*, size_t) = { + [INVOKE_UNTYPED_SIZE] = s_handle_invoke_untyped_size, + [INVOKE_UNTYPED_SPLIT] = s_handle_invoke_untyped_split, + + [INVOKE_UNTYPED_ALIGNMENT] = s_handle_invoke_untyped_alignment +}; +static size_t s_invoke_handles_count = sizeof(s_invoke_handles) / sizeof(void*); + +int +syscall_handle_invoke_untyped( + objdir_t *root_dir, + objdir_entry_t *target, + uint8_t *payload, + size_t payload_at) +{ + uint8_t funcid; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, funcid, uint8_t); + + if(funcid >= s_invoke_handles_count) return -KE_BADFUNC; + return s_invoke_handles[funcid](root_dir, target, payload, payload_at); +} diff --git a/syscall/invoke_objdir.c b/syscall/invoke_objdir.c index 4698f34..9cd3f32 100644 --- a/syscall/invoke_objdir.c +++ b/syscall/invoke_objdir.c @@ -1,34 +1,98 @@ #include "handles.h" #include "syscall.h" +#include "error.h" +#include "lock.h" +#include "print.h" static int -s_handle_invoke_objdir_nmemb(objdir_t *root_dir, objdir_t *target_dir, void *payload) +s_handle_invoke_objdir_nmemb( + objdir_t *root_dir, + objdir_t *target_dir, + uint8_t *payload, + size_t payload_at + ) { - struct syscallInvoke_objdir_nmemb *payloadStruct = payload; - payloadStruct->value = target_dir->self.data; - return 0; + uint8_t *dest; + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, uint8_t); + + *dest = target_dir->self.data; + +#ifdef DBG_SYSCALL + klogf("objdir_nmemb %p[%i]\n", dest, *dest); +#endif + return KE_OK; +} + +static int +s_handle_invoke_objdir_getmemb( + objdir_t *root_dir, + objdir_t *target_dir, + uint8_t *payload, + size_t payload_at + ) +{ + path_byte_t member; + obj_type_t *dest; + + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, member, uint8_t); + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, obj_type_t); + + *dest = target_dir->entries[member].type; + +#ifdef DBG_SYSCALL + klogf("objdir_getmemb %i ret %i\n", member, *dest); +#endif + return KE_OK; } static int -s_handle_invoke_objdir_getmemb(objdir_t *root_dir, objdir_t *target_dir, void *payload) +s_handle_invoke_objdir_lastfree( + objdir_t *root_dir, + objdir_t *target_dir, + uint8_t *payload, + size_t payload_at + ) { - struct syscallInvoke_objdir_getmemb *payloadStruct = payload; - payloadStruct->value = target_dir->entries[payloadStruct->member].type; - return 0; + path_byte_t *dest; + SYSCALL_PAYLOAD_TAKEP(payload, payload_at, dest, path_byte_t); + + for(int i = 0; i < 256; i++) { + if(target_dir->entries[i].type == KO_NONE) { + *dest = (path_byte_t)i; + return KE_OK; + } + } + return -KE_FULL; } -static int (*s_invoke_handles[])(objdir_t*, objdir_t*, void*) = { +static int (*s_invoke_handles[])(objdir_t*, objdir_t*, uint8_t*, size_t) = { [INVOKE_OBJDIR_NMEMB] = s_handle_invoke_objdir_nmemb, - [INVOKE_OBJDIR_GETMEMB] = s_handle_invoke_objdir_getmemb + [INVOKE_OBJDIR_GETMEMB] = s_handle_invoke_objdir_getmemb, + [INVOKE_OBJDIR_LASTFREE] = s_handle_invoke_objdir_lastfree }; static size_t s_invoke_handles_count = sizeof(s_invoke_handles) / sizeof(void*); int -syscall_handle_invoke_objdir(objdir_t *root_dir, objdir_t *target_dir, void *payload) +syscall_handle_invoke_objdir( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) { - struct syscallInvokeHeader *invokeHeader = payload; - size_t funcid = invokeHeader->func_id; + uint8_t funcid; + SYSCALL_PAYLOAD_TAKEL(payload, payload_at, funcid, uint8_t); + + if(funcid >= s_invoke_handles_count) return -KE_BADFUNC; + objdir_t *target_dir = (objdir_t*)target_entry->data; + + if((void*)target_entry == root_dir) target_dir = root_dir; +#ifdef DBG_SYSCALL + klogf("Call %i root_dir %p target %p\n", funcid, root_dir, target_entry); +#endif - if(funcid >= s_invoke_handles_count) return -1; - return s_invoke_handles[funcid](root_dir, target_dir, payload); + mtx_acquire(&target_entry->lock); + int e = s_invoke_handles[funcid](root_dir, target_dir, payload, payload_at); + mtx_release(&target_entry->lock); + return e; } |