summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile8
-rw-r--r--arch/x86_64/hal/obj.h2
-rw-r--r--arch/x86_64/hal/process.c37
-rw-r--r--arch/x86_64/hal/process.h14
-rw-r--r--arch/x86_64/hal/smp.c8
-rw-r--r--arch/x86_64/hal/smp.h2
-rw-r--r--arch/x86_64/lib/elf.h2
-rw-r--r--arch/x86_64/sys/init.c40
-rw-r--r--arch/x86_64/sys/serial.c41
-rw-r--r--arch/x86_64/sys/syscall.c40
-rw-r--r--arch/x86_64/sys/syscall.h23
-rw-r--r--compile_commands.json77
-rw-r--r--hal/obj.h3
-rw-r--r--hal/process.h29
-rw-r--r--hal/smp.h6
-rw-r--r--init.h1
-rw-r--r--lib/printf.c15
-rw-r--r--sys/message.c15
-rw-r--r--sys/message.h13
-rw-r--r--sys/syscall.c111
-rw-r--r--sys/syscall.h43
22 files changed, 481 insertions, 50 deletions
diff --git a/.gitignore b/.gitignore
index 71d7146..6872380 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
*.elf
*.o
*.d
+.cache
diff --git a/Makefile b/Makefile
index c53a551..cd8e128 100644
--- a/Makefile
+++ b/Makefile
@@ -20,9 +20,17 @@ OBJFILES += $(patsubst %.s,%.o,$(SFILES))
DEPFILES := $(patsubst %.c,%.d,$(CFILES))
BIN := jove.elf
+INCDIR := $(OUT)/usr/include/kernel
all: $(BIN)
+headers:
+ mkdir -p $(INCDIR)
+ -$(foreach dir,$(CDIRS),$$(mkdir -p $(INCDIR)/$(dir) $(INCDIR)/arch/$(dir)/))
+ -cp *.h $(INCDIR)/
+ -$(foreach dir,$(CDIRS),$$(cp $(dir)/*.h $(INCDIR)/$(dir)/))
+ -$(foreach dir,$(CDIRS),$$(cp arch/$(TARGET_MACHINE)/$(dir)/*.h $(INCDIR)/arch/$(dir)/))
+
.PHONY: clean
clean:
-rm $(OBJFILES)
diff --git a/arch/x86_64/hal/obj.h b/arch/x86_64/hal/obj.h
index f7d7711..78d7383 100644
--- a/arch/x86_64/hal/obj.h
+++ b/arch/x86_64/hal/obj.h
@@ -7,7 +7,7 @@
enum
{
- JOVE_OBJ_SERIAL_COM = 0x81,
+ JOVE_OBJ_SERIAL_COM = 0x80,
};
/*Represents a locked kernel object pointer inside of a object directory.*/
diff --git a/arch/x86_64/hal/process.c b/arch/x86_64/hal/process.c
index 5c91238..872be5a 100644
--- a/arch/x86_64/hal/process.c
+++ b/arch/x86_64/hal/process.c
@@ -1,6 +1,8 @@
#include "process.h"
#include "arch/x86_64/hal/obj.h"
#include "hal/obj.h"
+#include "hal/process.h"
+#include "hal/smp.h"
#include "init.h"
#include "smp.h"
#include "paging.h"
@@ -9,22 +11,53 @@
PAGEALIGN char s_init_pcb_bytes[0x1000] = { 0 };
static pcb_t *s_init_pcb = (pcb_t*)&s_init_pcb_bytes;
+jove_owned_obj_t*
+process_current(void)
+{
+ return obj_take(((processor_t*)processor_current())->pcb_obj);
+}
+
+pcb_t*
+pcb_from_obj(jove_owned_obj_t *obj)
+{
+ if(obj_gettype(obj) != JOVE_OBJ_PROCESS) {
+ reterr(EBADOBJ);
+ }
+ return obj_deref(obj);
+}
+
+pid_t
+pcb_pid(pcb_t *pcb)
+{
+ return pcb->pid;
+}
+
+jove_owned_obj_t*
+pcb_rootdir(pcb_t *pcb)
+{
+ return obj_take(pcb->rootdir);
+}
+
void
processing_setup(void (*process_main))
{
uintptr_t ksp = ((uintptr_t)&s_init_pcb_bytes) + 0xFF0;
+
+ s_init_pcb->pid = 1;
s_init_pcb->ksp = (void*)ksp;
s_init_pcb->pml4 = paging_get_pml4();
+ s_init_pcb->rootdir = _rootdir_obj;
processor_t *proc = processor_current();
- proc->pcb = s_init_pcb;
proc->tss.rsp[0] = (uintptr_t)s_init_pcb->ksp;
{
jove_owned_obj_t *process_obj = objdir_getlocal(_rootdir_obj, ROOTDIR_PCB_I);
obj_settype(process_obj, JOVE_OBJ_PROCESS);
obj_setvalue(process_obj, (uintptr_t)s_init_pcb);
- obj_release(process_obj);
+
+ proc->pcb_obj = obj_release(process_obj);
+ proc->pcb = s_init_pcb;
}
__asm__ volatile("\
diff --git a/arch/x86_64/hal/process.h b/arch/x86_64/hal/process.h
index 0c0fb5b..65b2318 100644
--- a/arch/x86_64/hal/process.h
+++ b/arch/x86_64/hal/process.h
@@ -1,22 +1,12 @@
#ifndef _JOVE_x86_64_HAL_PROCESS_H
#define _JOVE_x86_64_HAL_PROCESS_H 1
-#include "hal/obj.h"
+#include "hal/process.h"
#include "arch/x86_64/x86_64.h"
-enum pcb_state
-{
- PCB_DEAD, PCB_READY, PCB_RUNNING, PCB_BLOCKED
-};
-
-struct pcb_mailbox
-{
- jove_obj_t *obj;
- uintmax_t pcbid;
-};
-
typedef struct process_control_block
{
+ pid_t pid;
jove_obj_t *rootdir;
uintptr_t pml4;
diff --git a/arch/x86_64/hal/smp.c b/arch/x86_64/hal/smp.c
index e0945c1..85ba4ec 100644
--- a/arch/x86_64/hal/smp.c
+++ b/arch/x86_64/hal/smp.c
@@ -1,4 +1,5 @@
#include "smp.h"
+#include "hal/process.h"
#include "init.h"
#include "hal/obj.h"
#include "config.h"
@@ -55,12 +56,7 @@ smp_init_bsp(void)
}
}
-void *processor_current(void)
+processor_t *processor_current(void)
{
return (processor_t*)msr_get_gs_base();
}
-
-jove_obj_t *processor_objdir(void *processor)
-{
- return ((processor_t*)processor)->pcb->rootdir;
-}
diff --git a/arch/x86_64/hal/smp.h b/arch/x86_64/hal/smp.h
index 68e420f..5813dd3 100644
--- a/arch/x86_64/hal/smp.h
+++ b/arch/x86_64/hal/smp.h
@@ -3,6 +3,7 @@
#include "gdt.h"
#include "process.h"
+#include "hal/obj.h"
#include "hal/smp.h"
typedef struct processor
@@ -10,6 +11,7 @@ typedef struct processor
struct gdt_entry gdt[GDT_TSS_HI+1];
struct tss tss;
+ jove_obj_t *pcb_obj;
pcb_t *pcb;
} processor_t;
diff --git a/arch/x86_64/lib/elf.h b/arch/x86_64/lib/elf.h
index fae2255..bd3e9cf 100644
--- a/arch/x86_64/lib/elf.h
+++ b/arch/x86_64/lib/elf.h
@@ -32,6 +32,8 @@ struct elf_header
uint16_t e_shstrndx;
};
+#define PT_LOAD 1
+
struct elf_phdr
{
uint32_t p_type;
diff --git a/arch/x86_64/sys/init.c b/arch/x86_64/sys/init.c
index 26eefde..cecca32 100644
--- a/arch/x86_64/sys/init.c
+++ b/arch/x86_64/sys/init.c
@@ -1,6 +1,7 @@
#include "init.h"
#include "arch/x86_64/hal/msr.h"
#include "config.h"
+#include "hal/process.h"
#include "jove.h"
#include "hal/obj.h"
#include "lib/string.h"
@@ -98,15 +99,16 @@ init_setup(void)
jove_owned_obj_t *init_pagedir = objdir_getlocal(_rootdir_obj, ROOTDIR_PAGEDIR_I);
page_t *pml4 = obj_deref(init_pagedir);
+ size_t last_base = 0;
//Load the init ELF
- for(size_t i = 0; i < init_ehdr->e_shnum; i++) {
- struct elf_shdr *shdr = init_data + init_ehdr->e_shoff + i * init_ehdr->e_shentsize;
- if(shdr->sh_type != SHT_PROGBITS && shdr->sh_type != SHT_NOBITS) continue;
- if((shdr->sh_flags & SHF_ALLOC) == 0) continue;
+ for(size_t i = 0; i < init_ehdr->e_phnum; i++) {
+ struct elf_phdr *phdr = init_data + init_ehdr->e_phoff + i * init_ehdr->e_phentsize;
+ if(phdr->p_type != PT_LOAD) continue;
+ kprintf("init: phdr %i flags %b\n", i, phdr->p_flags);
- uintptr_t base = shdr->sh_addr;
- size_t limit = shdr->sh_size;
+ uintptr_t base = phdr->p_vaddr;
+ size_t limit = phdr->p_memsz;
uintptr_t page_base = base & ~0xFFFULL;
size_t pml3i = (page_base >> PMLI_SHL(3)) & 0x1FF;
@@ -125,15 +127,15 @@ init_setup(void)
if(pml0i > INIT_PROGRAM_PAGES_MAX) {
kpanic("init: Program exceeds maximum program pages in the same hugepage frame!\n");
}
+ if(last_base < base + limit) last_base = base + limit;
uintptr_t pml0_pptr = init_program_pml0_pptr + (pml0i << 12);
s_init_program_pml1[pml0i].value = pml0_pptr | PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE;
}
//Copy data from section if SHT_PROGBITS
- if(shdr->sh_type == SHT_PROGBITS) {
- memcpy((void*)shdr->sh_addr, init_data + shdr->sh_offset, shdr->sh_size);
- }
+ kprintf("init: load %p : %p\n", base, limit);
+ memcpy((void*)phdr->p_vaddr, init_data + phdr->p_offset, phdr->p_memsz);
}
//Map the stack
@@ -147,19 +149,37 @@ init_setup(void)
s_init_stack_pml1[pml0i].value = page_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER | PAGE_XD;
}
+ //Map the syscall message.
+ last_base = (last_base + 0xFFF) & ~0xFFF;
+ size_t last_page = (last_base >> 12) & 0x1FF;
+ uintptr_t message_pptr = init_program_pml0_pptr + (last_page << 12);
+ s_init_program_pml1[last_page].value = message_pptr | PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER | PAGE_XD;
+
+ jove_owned_obj_t *message_obj = objdir_getlocal(_rootdir_obj, ROOTDIR_MESSAGE_I);
+ obj_settype(message_obj, JOVE_OBJ_MESSAGE);
+ obj_setvalue(message_obj, (message_pptr & ~0xFFF) | 1);
+ obj_release(message_obj);
+
obj_release(init_pagedir);
//Enable syscalls
extern void _syscall_entry(void);
msr_set_lstar(_syscall_entry);
+ //Setup KSP for syscalls
+ jove_owned_obj_t *pcb_obj = process_current();
+ pcb_t *pcb = obj_deref(pcb_obj);
+
+ obj_release(pcb_obj);
+
uintptr_t usp = 0x00007FFFFFFFFFF8;
uintptr_t uip = init_ehdr->e_entry;
__asm__ volatile("movq %0, %%rsp; \
movq %1, %%rcx; \
+ movq %2, %%rdi; \
movq $0x202, %%r11; \
swapgs; \
sysretq"::
- "r"(usp), "r"(uip): "memory");
+ "r"(usp), "r"(uip), "m"(last_base): "memory");
}
diff --git a/arch/x86_64/sys/serial.c b/arch/x86_64/sys/serial.c
new file mode 100644
index 0000000..48a14c7
--- /dev/null
+++ b/arch/x86_64/sys/serial.c
@@ -0,0 +1,41 @@
+#include "jove.h"
+#include "lib/printf.h"
+#include "syscall.h"
+#include "arch/x86_64/hal/serial_com.h"
+
+static int
+s_syscall_serial_write(
+ jove_owned_obj_t *serial_com,
+ size_t payload_bytes,
+ void *payload_data)
+{
+ if(payload_bytes < sizeof(struct syscall_serial_write)) {
+ kprintf("syscall_serial_write: message is too small for this syscall!\n");
+ return EOOB;
+ }
+ struct syscall_serial_write *payload = payload_data;
+ if(payload_bytes < sizeof(struct syscall_serial_write) + payload->len) {
+ kprintf("syscall_serial_write: message is to small for payload!\n");
+ return EOOB;
+ }
+ return serial_com_write(serial_com, payload->data, payload->len);
+}
+
+int
+_syscall_handle_serial(
+ jove_owned_obj_t *pcb_obj,
+ jove_owned_obj_t *objdir,
+ jove_owned_obj_t *message_obj,
+ jove_owned_obj_t *target_obj,
+ struct syscall_header *header,
+ size_t bytes_left,
+ void *payload_data)
+{
+ switch(header->callid) {
+ case 0:
+ return s_syscall_serial_write(target_obj, bytes_left, payload_data);
+ default:
+ kprintf("syscall_serial: serial com object does not support syscall %i\n", header->callid);
+ return EOOB;
+ }
+}
diff --git a/arch/x86_64/sys/syscall.c b/arch/x86_64/sys/syscall.c
index 4e95225..b2d3e7f 100644
--- a/arch/x86_64/sys/syscall.c
+++ b/arch/x86_64/sys/syscall.c
@@ -1,24 +1,33 @@
+#include "arch/x86_64/hal/obj.h"
#include "arch/x86_64/hal/process.h"
#include "arch/x86_64/hal/smp.h"
-#include "hal/smp.h"
-#include "jove.h"
+#include "lib/printf.h"
+
+#include "syscall.h"
+
+syscall_handle_t s_arch_handles[128] = {
+ [JOVE_OBJ_SERIAL_COM-0x80] = _syscall_handle_serial
+};
int
-syscall_handler_arch(uint64_t message_path_raw, uint64_t message_pathlen)
+syscall_handle_arch(
+ jove_owned_obj_t *pcb_obj,
+ jove_owned_obj_t *objdir,
+ jove_owned_obj_t *message_obj,
+ jove_owned_obj_t *target_obj,
+ struct syscall_header *header,
+ size_t bytes_left,
+ void *payload)
{
- uint16_t *message_path = (uint16_t*)&message_path_raw;
- if(message_pathlen > 4) {
- return EBADPATH;
- }
- processor_t *proc = processor_current();
- jove_owned_obj_t *objdir = obj_take(proc->pcb->rootdir);
- jove_owned_obj_t *message_obj = objdir_getobj(objdir, message_path, message_pathlen);
- if(message_obj == 0) {
- obj_release(objdir);
- return errno;
+ uint8_t target_type = obj_gettype(target_obj) - 0x80;
+ syscall_handle_t call_handle = s_arch_handles[target_type];
+ if(call_handle == NULL) {
+ kprintf("syscall: Process %i tried to call syscall on object %P which doesn't support syscalls!\n",
+ pcb_pid(obj_deref(pcb_obj)), header->path, header->pathlen);
+ return EBADOBJ;
}
- return 0;
+ return call_handle(pcb_obj, objdir, message_obj, target_obj, header, bytes_left, payload);
}
__attribute__((naked))
@@ -38,7 +47,7 @@ void _syscall_entry(void)
pushq %%r13; \
pushq %%r14; \
pushq %%r15; \
- callq syscall_handler_arch; \
+ callq syscall_handler; \
swapgs; \
popq %%r15; \
popq %%r14; \
@@ -53,7 +62,6 @@ void _syscall_entry(void)
xorq %%r8, %%r8; \
xorq %%r9, %%r9; \
xorq %%r10, %%r10; \
- popq %%rcx; \
popq %%r11; \
popq %%rsp; \
sysretq;"
diff --git a/arch/x86_64/sys/syscall.h b/arch/x86_64/sys/syscall.h
new file mode 100644
index 0000000..1368897
--- /dev/null
+++ b/arch/x86_64/sys/syscall.h
@@ -0,0 +1,23 @@
+#ifndef _JOVE_ARCH_SYS_SYSCALL_H
+#define _JOVE_ARCH_SYS_SYSCALL_H 1
+
+#include "sys/syscall.h"
+
+int
+_syscall_handle_serial(
+ jove_owned_obj_t *pcb_obj,
+ jove_owned_obj_t *objdir,
+ jove_owned_obj_t *message_obj,
+ jove_owned_obj_t *target_obj,
+ struct syscall_header *header,
+ size_t bytes_left,
+ void *payload);
+struct syscall_serial_write
+{
+ size_t len;
+ char data[];
+};
+
+#define SYSCALL_SERIAL_COM_WRITE 0
+
+#endif
diff --git a/compile_commands.json b/compile_commands.json
new file mode 100644
index 0000000..2592007
--- /dev/null
+++ b/compile_commands.json
@@ -0,0 +1,77 @@
+[
+ {
+ "file": "arch/x86_64/sys/init.c",
+ "arguments": [
+ "x86_64-elf-gcc",
+ "-ffreestanding",
+ "-fno-pie",
+ "-fno-pic",
+ "-g",
+ "-MD",
+ "-D__x86_64__",
+ "-D__limine__",
+ "-Iinclude",
+ "-I.",
+ "-m64",
+ "-mno-red-zone",
+ "-mcmodel=kernel",
+ "-mfsgsbase",
+ "-c",
+ "arch/x86_64/sys/init.c",
+ "-o",
+ "arch/x86_64/sys/init.o"
+ ],
+ "directory": "/home/jon/prg/jove/kernel",
+ "output": "arch/x86_64/sys/init.o"
+ },
+ {
+ "file": "arch/x86_64/sys/syscall.c",
+ "arguments": [
+ "x86_64-elf-gcc",
+ "-ffreestanding",
+ "-fno-pie",
+ "-fno-pic",
+ "-g",
+ "-MD",
+ "-D__x86_64__",
+ "-D__limine__",
+ "-Iinclude",
+ "-I.",
+ "-m64",
+ "-mno-red-zone",
+ "-mcmodel=kernel",
+ "-mfsgsbase",
+ "-c",
+ "arch/x86_64/sys/syscall.c",
+ "-o",
+ "arch/x86_64/sys/syscall.o"
+ ],
+ "directory": "/home/jon/prg/jove/kernel",
+ "output": "arch/x86_64/sys/syscall.o"
+ },
+ {
+ "file": "arch/x86_64/boot/limine/framebuffer.c",
+ "arguments": [
+ "x86_64-elf-gcc",
+ "-ffreestanding",
+ "-fno-pie",
+ "-fno-pic",
+ "-g",
+ "-MD",
+ "-D__x86_64__",
+ "-D__limine__",
+ "-Iinclude",
+ "-I.",
+ "-m64",
+ "-mno-red-zone",
+ "-mcmodel=kernel",
+ "-mfsgsbase",
+ "-c",
+ "arch/x86_64/boot/limine/framebuffer.c",
+ "-o",
+ "arch/x86_64/boot/limine/framebuffer.o"
+ ],
+ "directory": "/home/jon/prg/jove/kernel",
+ "output": "arch/x86_64/boot/limine/framebuffer.o"
+ }
+] \ No newline at end of file
diff --git a/hal/obj.h b/hal/obj.h
index c988795..93825fd 100644
--- a/hal/obj.h
+++ b/hal/obj.h
@@ -14,7 +14,8 @@ enum
JOVE_OBJ_PAGEFRAME,
JOVE_OBJ_INITRD_FILE,
JOVE_OBJ_FRAMEBUFFER,
- JOVE_OBJ_VIRTTERM
+ JOVE_OBJ_VIRTTERM,
+ JOVE_OBJ_MESSAGE
};
#ifdef __x86_64__
diff --git a/hal/process.h b/hal/process.h
new file mode 100644
index 0000000..63c800f
--- /dev/null
+++ b/hal/process.h
@@ -0,0 +1,29 @@
+#ifndef _JOVE_HAL_PROCESS_H
+#define _JOVE_HAL_PROCESS_H 1
+
+#include "hal/obj.h"
+
+typedef uintmax_t pid_t;
+
+enum pcb_state
+{
+ PCB_DEAD, PCB_READY, PCB_RUNNING, PCB_BLOCKED
+};
+
+struct pcb_mailbox
+{
+ jove_obj_t *obj;
+ pid_t pid;
+};
+
+typedef struct process_control_block pcb_t;
+
+jove_owned_obj_t *process_current(void);
+
+/*Returns the process ID of the passed PCB. */
+pid_t pcb_pid(pcb_t *pcb);
+
+/*Returns the root kernel object directory of this PCB. */
+jove_owned_obj_t *pcb_rootdir(pcb_t *pcb);
+
+#endif
diff --git a/hal/smp.h b/hal/smp.h
index 3718f46..ba4f7d2 100644
--- a/hal/smp.h
+++ b/hal/smp.h
@@ -3,8 +3,10 @@
#include "obj.h"
-void *processor_current(void);
+typedef struct processor processor_t;
-jove_obj_t *processor_objdir(void *processor);
+processor_t *processor_current(void);
+
+jove_owned_obj_t *processor_objdir(processor_t *processor);
#endif
diff --git a/init.h b/init.h
index 8447b26..ce2612a 100644
--- a/init.h
+++ b/init.h
@@ -8,6 +8,7 @@ extern void *_rootdir_obj;
#define ROOTDIR_UNTYPED_I 0x02
#define ROOTDIR_PCB_I 0x03
#define ROOTDIR_INITRD_I 0x04
+#define ROOTDIR_MESSAGE_I 0x05
#define ROOTDIR_SERIAL_COM_I 0x80
#define ROOTDIR_FRAMEBUFFER_I 0x81
diff --git a/lib/printf.c b/lib/printf.c
index 4c26fe4..4e64d7b 100644
--- a/lib/printf.c
+++ b/lib/printf.c
@@ -100,6 +100,10 @@ vsnprintf(
case 'i':
goto int_conversion;
break;
+ /*custom formatters for jove.*/
+ case 'P':
+ goto path_conversion;
+ break;
}
string_conversion:
{
@@ -132,6 +136,17 @@ int_conversion:
}
stri += advance;
} continue;
+path_conversion:
+ {
+ uint16_t *obj_path = va_arg(ap, uint16_t*);
+ size_t obj_pathlen = va_arg(ap, size_t);
+ for(size_t i = 0; i < obj_pathlen; i++) {
+ uint16_t subdir = obj_path[i];
+ int advance = convert_as_int(str, size, stri, 3, subdir, 10, 1);
+ stri += advance;
+ SPRINTF_PUTC(str, size, stri, '/');
+ }
+ } continue;
}
if(str && stri < size) str[stri] = 0;
return stri;
diff --git a/sys/message.c b/sys/message.c
new file mode 100644
index 0000000..7c871ce
--- /dev/null
+++ b/sys/message.c
@@ -0,0 +1,15 @@
+#include "message.h"
+#include "hal/obj.h"
+
+void *
+message_data(jove_owned_obj_t *obj)
+{
+ uintptr_t objptr = (uintptr_t)obj_deref(obj);
+ return (void*)(objptr & ~0xFFF);
+}
+
+size_t
+message_len(jove_owned_obj_t *obj)
+{
+ return (obj_getvalue(obj) & 0xFFF) << 12;
+}
diff --git a/sys/message.h b/sys/message.h
new file mode 100644
index 0000000..2ae6e03
--- /dev/null
+++ b/sys/message.h
@@ -0,0 +1,13 @@
+#ifndef _JOVE_SYS_MESSAGE_H
+#define _JOVE_SYS_MESSAGE_H 1
+
+#include "hal/obj.h"
+
+#define MESSAGE_MAX_PAGES (1<<12)
+#define MESSAGE_MAX_BYTES (MESSAGE_MAX_PAGES * 0x1000)
+#define MESSAGE_ALIGN 0x1000
+
+void *message_data(jove_owned_obj_t *obj);
+size_t message_len(jove_owned_obj_t *obj);
+
+#endif
diff --git a/sys/syscall.c b/sys/syscall.c
new file mode 100644
index 0000000..1eadf50
--- /dev/null
+++ b/sys/syscall.c
@@ -0,0 +1,111 @@
+#include "sys/syscall.h"
+#include "arch/x86_64/hal/obj.h"
+#include "hal/smp.h"
+#include "hal/process.h"
+#include "jove.h"
+#include "lib/printf.h"
+#include "sys/message.h"
+
+int
+_syscall_handle_generic(
+ jove_owned_obj_t *pcb_obj,
+ jove_owned_obj_t *objdir,
+ jove_owned_obj_t *message_obj,
+ jove_owned_obj_t *target_obj,
+ struct syscall_header *header,
+ size_t bytes_left,
+ void *payload)
+{
+ pcb_t *pcb = obj_deref(pcb_obj);
+ kprintf("syscall: Process %i encountered stub syscall on object %P\n", pcb_pid(pcb), header->path, header->pathlen);
+ return EBADOBJ;
+}
+
+static const syscall_handle_t s_syscall_handles[128] = {
+ [JOVE_OBJ_NONE] = NULL,
+ [JOVE_OBJ_UNTYPED] = _syscall_handle_generic,
+ [JOVE_OBJ_OBJDIR] = _syscall_handle_generic,
+ [JOVE_OBJ_PAGEDIR] = _syscall_handle_generic,
+ [JOVE_OBJ_PROCESSOR] = _syscall_handle_generic,
+ [JOVE_OBJ_PROCESS] = _syscall_handle_generic,
+ [JOVE_OBJ_PAGEFRAME] = _syscall_handle_generic,
+ [JOVE_OBJ_INITRD_FILE] = _syscall_handle_generic,
+ [JOVE_OBJ_FRAMEBUFFER] = _syscall_handle_generic,
+ [JOVE_OBJ_VIRTTERM] = _syscall_handle_generic,
+ [JOVE_OBJ_MESSAGE] = _syscall_handle_generic,
+};
+
+int
+syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen)
+{
+ uint16_t *message_path = (uint16_t*)&message_path_raw;
+ if(message_pathlen > sizeof(uintmax_t) >> 1) {
+ return EBADPATH;
+ }
+
+ jove_owned_obj_t *pcb_obj = process_current();
+ pcb_t *pcb = obj_deref(pcb_obj);
+
+ jove_owned_obj_t *objdir = pcb_rootdir(pcb);
+ kprintf("Syscall: %p : %P \n", objdir, message_path, message_pathlen);
+
+ jove_owned_obj_t *message_obj = objdir_getobj(objdir, message_path, message_pathlen);
+ if(message_obj == 0) {
+ obj_release(objdir);
+ obj_release(pcb_obj);
+ return errno;
+ }
+
+#define SYSCALL_MIDWAY_CLEANUP \
+ obj_release(message_obj); \
+ obj_release(objdir); \
+ obj_release(pcb_obj)
+
+ if(obj_gettype(message_obj) != JOVE_OBJ_MESSAGE) {
+ kprintf("syscall: Process %i tried to call syscall with invalid object: %P\n", pcb_pid(pcb), message_path, message_pathlen);
+ SYSCALL_MIDWAY_CLEANUP;
+ return EBADOBJ;
+ }
+
+ size_t messagelen = message_len(message_obj);
+ void *messagedata = message_data(message_obj);
+ struct syscall_header *header = messagedata;
+
+ size_t header_bytes = sizeof(struct syscall_header) + header->pathlen * 2;
+ int bytes_left = messagelen - header_bytes;
+ kprintf("syscall: Payload %p len %i\n", messagedata, header->pathlen);
+ if(bytes_left < 0) {
+ //Target path exceeds message length.
+ kprintf("syscall: Process %i tried to call syscall with OOB target path.\n", pcb_pid(pcb));
+ SYSCALL_MIDWAY_CLEANUP;
+ return EBADPATH;
+ }
+ jove_owned_obj_t *target = objdir_getobj(objdir, header->path, header->pathlen);
+ if(target == 0) {
+ //Could not find payload target in pcb rootdir.
+ kprintf("syscall: Process %i tried to call syscall with bad target path %P\n",
+ pcb_pid(pcb), header->path, header->pathlen);
+ SYSCALL_MIDWAY_CLEANUP;
+ return errno;
+ }
+ int sysret = 0;
+
+ uint8_t target_type = obj_gettype(target);
+ if(target_type > 0x7F) {
+ sysret = syscall_handle_arch(pcb_obj, objdir, message_obj, target,
+ header, bytes_left, messagedata + header_bytes);
+ }else{
+ syscall_handle_t call_handle = s_syscall_handles[obj_gettype(target)];
+ if(call_handle == NULL) {
+ kprintf("syscall: Process %i tried to call syscall on object %P which doesn't support syscalls!\n",
+ pcb_pid(pcb), header->path, header->pathlen);
+ sysret = EBADOBJ;
+ }else
+ sysret = call_handle(pcb_obj, objdir, message_obj, target,
+ header, bytes_left, message_data + header_bytes);
+ }
+
+ obj_release(target);
+ SYSCALL_MIDWAY_CLEANUP;
+ return sysret;
+}
diff --git a/sys/syscall.h b/sys/syscall.h
new file mode 100644
index 0000000..efd3f64
--- /dev/null
+++ b/sys/syscall.h
@@ -0,0 +1,43 @@
+#ifndef _JOVE_SYS_SYSCALL_H
+#define _JOVE_SYS_SYSCALL_H 1
+
+#include "hal/obj.h"
+#include <stdint.h>
+
+struct syscall_header
+{
+ uint16_t callid;
+ uint16_t pathlen;
+ uint16_t path[];
+};
+
+typedef int (*syscall_handle_t)(
+ jove_owned_obj_t*, //PCB object
+ jove_owned_obj_t*, //Objdir object
+ jove_owned_obj_t*, //Message object
+ jove_owned_obj_t*, //Target object
+ struct syscall_header*, //Syscall header
+ size_t, //How many bytes are left in the message
+ void*); //The bytes left in the message.
+
+int
+_syscall_handle_generic(
+ jove_owned_obj_t *pcb_obj,
+ jove_owned_obj_t *objdir,
+ jove_owned_obj_t *message_obj,
+ jove_owned_obj_t *target_obj,
+ struct syscall_header *header,
+ size_t bytes_left,
+ void *payload);
+
+int
+syscall_handle_arch(
+ jove_owned_obj_t *pcb_obj,
+ jove_owned_obj_t *objdir,
+ jove_owned_obj_t *message_obj,
+ jove_owned_obj_t *target_obj,
+ struct syscall_header *header,
+ size_t bytes_left,
+ void *payload);
+
+#endif