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 /arch/x86_64/syscall-invoke-mapping.c | |
parent | b905869a35f062a4e5072f10bec3a2ba3db0e365 (diff) | |
download | jove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.tar.gz jove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.tar.bz2 jove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.zip |
working usermode objdir iteration
Diffstat (limited to 'arch/x86_64/syscall-invoke-mapping.c')
-rw-r--r-- | arch/x86_64/syscall-invoke-mapping.c | 124 |
1 files changed, 124 insertions, 0 deletions
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); +} |