diff options
Diffstat (limited to 'arch/x86_64/sys')
| -rw-r--r-- | arch/x86_64/sys/init.c | 40 | ||||
| -rw-r--r-- | arch/x86_64/sys/serial.c | 41 | ||||
| -rw-r--r-- | arch/x86_64/sys/syscall.c | 40 | ||||
| -rw-r--r-- | arch/x86_64/sys/syscall.h | 23 |
4 files changed, 118 insertions, 26 deletions
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 |
