summaryrefslogtreecommitdiffstats
path: root/syscall
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2025-08-10 15:40:19 -0400
committerJon Santmyer <jon@jonsantmyer.com>2025-08-10 15:40:19 -0400
commitc4f8ef91f18d854a4ede7a94e95b2eab898d6963 (patch)
treec2772c4f380a684b6fa347f03b13f9476bf9500c /syscall
parentb905869a35f062a4e5072f10bec3a2ba3db0e365 (diff)
downloadjove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.tar.gz
jove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.tar.bz2
jove-kernel-c4f8ef91f18d854a4ede7a94e95b2eab898d6963.zip
working usermode objdir iteration
Diffstat (limited to 'syscall')
-rw-r--r--syscall/handler.c76
-rw-r--r--syscall/handles.h21
-rw-r--r--syscall/invoke-untyped.c96
-rw-r--r--syscall/invoke_objdir.c94
4 files changed, 238 insertions, 49 deletions
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;
}