diff options
author | Jon Santmyer <jon@jonsantmyer.com> | 2025-08-19 15:03:42 -0400 |
---|---|---|
committer | Jon Santmyer <jon@jonsantmyer.com> | 2025-08-19 15:03:42 -0400 |
commit | 772717dc22e04b4d168d0f77bee6b6357118768c (patch) | |
tree | 9da95703c3376091904e295930104b51c280008d /arch/x86_64/syscall | |
parent | 7ee9347560768641096df68c545ac085a20233e4 (diff) | |
download | jove-kernel-772717dc22e04b4d168d0f77bee6b6357118768c.tar.gz jove-kernel-772717dc22e04b4d168d0f77bee6b6357118768c.tar.bz2 jove-kernel-772717dc22e04b4d168d0f77bee6b6357118768c.zip |
refactor KO_MEMORY_MAPPING invokemain
Diffstat (limited to 'arch/x86_64/syscall')
-rw-r--r-- | arch/x86_64/syscall/invoke-mapping.c | 146 | ||||
-rw-r--r-- | arch/x86_64/syscall/syscall.c | 55 | ||||
-rw-r--r-- | arch/x86_64/syscall/wrappers.h | 14 |
3 files changed, 215 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..be401d6 --- /dev/null +++ b/arch/x86_64/syscall/invoke-mapping.c @@ -0,0 +1,146 @@ +#include "arch/x86_64/syscall/wrappers.h" +#include "arch/x86_64/syscall.h" +#include "arch/x86_64/page.h" +#include <stddef.h> +#include "error.h" +#include "lock.h" +#include "string.h" +#include "memory.h" +#include "print.h" + +static int +s_handle_invoke_mapping_exists( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + pmle_t *target_pml; + uint8_t target_depth; + SYSCALL_PAYLOAD_TAKEPML(payload, payload_at, pml4, target_depth, target_pml); + if(target_pml == NULL || !target_pml->p) return KE_DNE; + +#ifdef DBG_SYSCALL + klogf("pml d%i %p from %p exists\n", target_depth, target_pml, pml4); +#endif + 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 + ) +{ + pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + pmle_t *target_pml; + uint8_t target_depth; + SYSCALL_PAYLOAD_TAKEPML(payload, payload_at, pml4, target_depth, target_pml); + if(target_pml == NULL) return KE_DNE; + + 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; + } + + uintptr_t untyped_phys = untyped_entry->data; + size_t *untyped = ko_entry_data(untyped_entry); + size_t untyped_size = *untyped; + if(untyped_size != 0x1000) { + mtx_release(&untyped_entry->lock); + return KE_BADSIZE; + } + + target_pml->value = untyped_phys | PAGE_RW | PAGE_US | PAGE_PRESENT; + __asm__ volatile("invlpg (%0)":: "r"(untyped): "memory"); + + if(target_depth != 3) { + memset(untyped, 0, 0x1000); + } + untyped_entry->type = KO_NONE; +#ifdef DBG_SYSCALL + klogf("map %p[%i] to %p[%i]\n", untyped_phys, target_depth, target_pml, ((uintptr_t)target_pml & 0xFFF) / 8); +#endif + + mtx_release(&untyped_entry->lock); + return 0; +} + +static int +s_handle_invoke_mapping_unmap( + objdir_t *root_dir, + objdir_entry_t *target_entry, + uint8_t *payload, + size_t payload_at + ) +{ + pmle_t *pml4 = (pmle_t*)vmem_phys_tovirt(target_entry->data); + pmle_t *target_pml; + uint8_t target_depth; + SYSCALL_PAYLOAD_TAKEPML(payload, payload_at, pml4, target_depth, target_pml); + if(target_pml == NULL || !target_pml->p) return KE_DNE; + + if(target_depth != 3) { + for(pmli_t i = 0; i < 512; i++) { + if(target_pml[i].p) return KE_FULL; + } + } + + target_pml->p = false; + + objdir_entry_t *dest_entry; + size_t dest_pathw; + SYSCALL_PAYLOAD_TAKEOBJ(payload, payload_at, dest_pathw, dest_entry); + + if(dest_entry->type != KO_NONE) return KE_FULL; + uintptr_t pmle_addr = target_pml->paddr << 12; + size_t *untyped = vmem_phys_tovirt(pmle_addr); + __asm__ volatile("invlpg (%0)":: "r"(untyped): "memory"); + + *untyped = 0x1000; + dest_entry->type = KO_MEMORY_UNTYPED; + dest_entry->data = pmle_addr; + +#ifdef DBG_SYSCALL + klogf("unmap %p[%i] to untyped %p\n", target_pml, 3 - target_depth, pmle_addr); +#endif + return 0; +} + +static int (*s_invoke_handles[])(objdir_t*, objdir_entry_t*, uint8_t*, size_t) = { + [INVOKE_MAPPING_EXISTS] = s_handle_invoke_mapping_exists, + [INVOKE_MAPPING_MAP] = s_handle_invoke_mapping_map, + [INVOKE_MAPPING_UNMAP] = s_handle_invoke_mapping_unmap +}; + +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; + int r = s_invoke_handles[funcid](root_dir, target, payload, payload_at); +#ifdef DBG_SYSCALL + klogf("Call returns %i\n", r); +#endif + return r; +} diff --git a/arch/x86_64/syscall/syscall.c b/arch/x86_64/syscall/syscall.c new file mode 100644 index 0000000..5582336 --- /dev/null +++ b/arch/x86_64/syscall/syscall.c @@ -0,0 +1,55 @@ +#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) +{ + __asm__ volatile(" \ + pushq %%r11; \ + pushq %%rcx; \ + swapgs; \ + movq %%gs:%c[tcb], %%rax; \ + movq %%rsp, %c[sp](%%rax); \ + movq %c[ksp](%%rax), %%rsp; \ + pushq %c[sp](%%rax); \ + callq _syscall_handler; \ + swapgs; \ + popq %%rsp; \ + popq %%rcx; \ + popq %%r11; \ + sysretq;" + :: + [tcb] "i"(offsetof(processor_t, tcb)), + [sp] "i"(offsetof(tcb_t, sp)), + [ksp] "i"(offsetof(tcb_t, ksp))); +} diff --git a/arch/x86_64/syscall/wrappers.h b/arch/x86_64/syscall/wrappers.h new file mode 100644 index 0000000..a6fdf88 --- /dev/null +++ b/arch/x86_64/syscall/wrappers.h @@ -0,0 +1,14 @@ +#ifndef _JOVE_ARCH_x86_64_SYSCALL_WRAPPERS_H +#define _JOVE_ARCH_x86_64_SYSCALL_WRAPPERS_H 1 + +#include "arch/x86_64/page-mapping.h" +#include "syscall/handles.h" + +#define SYSCALL_PAYLOAD_TAKEPML(payload, at, pml4, depth, pml) \ + SYSCALL_PAYLOAD_TAKEL(payload, at, depth, uint8_t); \ + if(((depth + 1) * sizeof(uint16_t)) + at >= KO_MESSAGE_BYTES) return KE_BADMSG; \ + if(depth == 0 && *(uint16_t*)&payload[at] > 255) return KE_OOB; \ + pml = page_mapping_traverse(pml4, depth, (uint16_t*)&payload[at]); \ + at += (depth + 1) * sizeof(uint16_t) + +#endif |