summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--arch/x86_64/lock.s19
-rw-r--r--arch/x86_64/memory.c16
-rw-r--r--arch/x86_64/page_directory.c11
-rw-r--r--arch/x86_64/processor.c12
-rw-r--r--arch/x86_64/sse.s46
-rw-r--r--arch/x86_64/syscall-invoke-mapping.c124
-rw-r--r--arch/x86_64/syscall.c32
-rw-r--r--arch/x86_64/untyped_retype_page.c13
-rw-r--r--arch/x86_64/usermode.c38
-rw-r--r--config.mk30
-rw-r--r--device/initrd.c4
-rw-r--r--device/uart.c5
-rw-r--r--include/arch/x86_64/object.h12
-rw-r--r--include/arch/x86_64/page.h8
-rw-r--r--include/arch/x86_64/syscall.h18
-rw-r--r--include/device/uart.h3
-rw-r--r--include/error.h17
-rw-r--r--include/lock.h20
-rw-r--r--include/memory.h3
-rw-r--r--include/object.h22
-rw-r--r--include/print.h2
-rw-r--r--include/syscall.h44
-rw-r--r--lib/objdir.c36
-rw-r--r--lib/print.c2
-rw-r--r--lib/printpath.c9
-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
30 files changed, 683 insertions, 154 deletions
diff --git a/Makefile b/Makefile
index 1d26c59..a2ec118 100644
--- a/Makefile
+++ b/Makefile
@@ -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;
diff --git a/config.mk b/config.mk
index 4b940b5..0d26458 100644
--- a/config.mk
+++ b/config.mk
@@ -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;
}