summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/syscall
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2025-08-19 15:03:42 -0400
committerJon Santmyer <jon@jonsantmyer.com>2025-08-19 15:03:42 -0400
commit772717dc22e04b4d168d0f77bee6b6357118768c (patch)
tree9da95703c3376091904e295930104b51c280008d /arch/x86_64/syscall
parent7ee9347560768641096df68c545ac085a20233e4 (diff)
downloadjove-kernel-main.tar.gz
jove-kernel-main.tar.bz2
jove-kernel-main.zip
refactor KO_MEMORY_MAPPING invokemain
Diffstat (limited to 'arch/x86_64/syscall')
-rw-r--r--arch/x86_64/syscall/invoke-mapping.c146
-rw-r--r--arch/x86_64/syscall/syscall.c55
-rw-r--r--arch/x86_64/syscall/wrappers.h14
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