diff --git a/src/arch/x86_64/include/arch/mmu.h b/src/arch/x86_64/include/arch/mmu.h index 0e0ba80d..a4d387a7 100644 --- a/src/arch/x86_64/include/arch/mmu.h +++ b/src/arch/x86_64/include/arch/mmu.h @@ -14,6 +14,11 @@ #define ARCH_MMU_MAP_PAGESIZE (uint64_t)(1 << 7) #define ARCH_MMU_MAP_ACCESSED (uint64_t)(1 << 5) +#define ARCH_MMU_ERROR_WRITE 2 +#define ARCH_MMU_ERROR_PRESENT 1 +#define ARCH_MMU_ERROR_USER 4 +#define ARCH_MMU_ERROR_INSTFETCH 16 + typedef uint64_t* arch_mmu_tableptr; int arch_mmu_map(arch_mmu_tableptr, void*, void*, size_t); diff --git a/src/arch/x86_64/isr.c b/src/arch/x86_64/isr.c index db9cbe26..b5a8544d 100644 --- a/src/arch/x86_64/isr.c +++ b/src/arch/x86_64/isr.c @@ -16,7 +16,7 @@ void isr_except(arch_regs *reg){ void isr_pagefault(arch_regs *reg){ - if(!vmm_dealwithrequest(reg->cr2)) + if(!vmm_dealwithrequest(reg->cr2, reg->error, reg->cs == 0x3b)) _panic("Page fault!", reg); } diff --git a/src/arch/x86_64/syscall.asm b/src/arch/x86_64/syscall.asm index 9d18b207..4eec5bfd 100644 --- a/src/arch/x86_64/syscall.asm +++ b/src/arch/x86_64/syscall.asm @@ -4,13 +4,15 @@ section .rodata extern syscall_libc_log extern syscall_mmap extern syscall_arch_ctl -func_count equ 3 +extern syscall_gettid +func_count equ 4 func_table: dq syscall_libc_log dq syscall_mmap dq syscall_arch_ctl + dq syscall_gettid section .text global asm_syscall_entry diff --git a/src/include/kernel/syscalls.h b/src/include/kernel/syscalls.h index b40b9841..6346d411 100644 --- a/src/include/kernel/syscalls.h +++ b/src/include/kernel/syscalls.h @@ -11,5 +11,6 @@ typedef struct { syscallret syscall_libc_log(char* str); syscallret syscall_mmap(void* hint, size_t len, int prot, int flags, int fd, off_t offset); +syscallret syscall_gettid(); #endif diff --git a/src/include/kernel/vmm.h b/src/include/kernel/vmm.h index 5426caa4..b2b9c3bb 100644 --- a/src/include/kernel/vmm.h +++ b/src/include/kernel/vmm.h @@ -55,7 +55,7 @@ typedef struct { void vmm_init(); -bool vmm_dealwithrequest(void* addr); +bool vmm_dealwithrequest(void* addr, long error, bool user); bool vmm_setused(void* addr, size_t pagec, size_t mmuflags); bool vmm_unmap(void* addr, size_t pagec); bool vmm_map(void* paddr, void* vaddr, size_t pagec, size_t mmuflags); diff --git a/src/sys/mm/vmm.c b/src/sys/mm/vmm.c index 707e61ff..c84a1955 100644 --- a/src/sys/mm/vmm.c +++ b/src/sys/mm/vmm.c @@ -395,14 +395,16 @@ void* vmm_allocfrom(void* addr, size_t mmuflags, size_t pagec){ spinlock_acquire(lock); - addr = findfirstfreearea(findmappingfromaddr(*start, addr), pagec); + vmm_mapping* map = findmappingfromaddr(*start, addr); + + addr = findfirstfreearea(map, pagec); if(!addr) goto _done; if(!setmap(start, addr, pagec, mmuflags, VMM_TYPE_ANON, 0, 0)) addr = NULL; - + _done: spinlock_release(lock); @@ -514,8 +516,11 @@ bool vmm_allocnowat(void* addr, size_t mmuflags, size_t size){ // called by the page fault handler -bool vmm_dealwithrequest(void* addr){ +bool vmm_dealwithrequest(void* addr, long error, bool user){ + if(user && addr > USER_SPACE_END) + return false; + int* lock; vmm_mapping** start = NULL; @@ -533,10 +538,27 @@ bool vmm_dealwithrequest(void* addr){ status = false; goto done; } - + if(map->type == VMM_TYPE_FILE) _panic("File mappings are not supported (yet)", 0); + size_t goodmmuflags = 1; + + if(error & ARCH_MMU_ERROR_WRITE) + goodmmuflags |= ARCH_MMU_MAP_WRITE; + + if(error & ARCH_MMU_ERROR_USER) + goodmmuflags |= ARCH_MMU_MAP_USER; + + if(error & ARCH_MMU_ERROR_INSTFETCH == 0) + goodmmuflags |= ARCH_MMU_MAP_NOEXEC; + + + if(goodmmuflags != (map->mmuflags & goodmmuflags)) + return false; + + + // allocate a page addr = (size_t)addr & ~(0xFFF); diff --git a/src/sys/sched/elf.c b/src/sys/sched/elf.c index 6b064506..a82b19a2 100644 --- a/src/sys/sched/elf.c +++ b/src/sys/sched/elf.c @@ -304,7 +304,7 @@ int elf_load(thread_t* thread, vnode_t* node, char** argv, char** env){ // also load the executable memory image if we're using an interpreter if(interp){ - for(size_t currentph = 0; currentph < header.ph_count; ++currentph){ + for(size_t currentph = 0; currentph < progheader.ph_count; ++currentph){ // read ph diff --git a/src/sys/syscalls/gettid.c b/src/sys/syscalls/gettid.c new file mode 100644 index 00000000..3d33f658 --- /dev/null +++ b/src/sys/syscalls/gettid.c @@ -0,0 +1,9 @@ +#include +#include + +syscallret syscall_gettid(){ + syscallret retv; + retv.errno = 0; + retv.ret = arch_getcls()->thread->tid; + return retv; +} diff --git a/src/sys/syscalls/mmap.c b/src/sys/syscalls/mmap.c index 34e1206b..510b3095 100644 --- a/src/sys/syscalls/mmap.c +++ b/src/sys/syscalls/mmap.c @@ -45,6 +45,7 @@ #define MFD_ALLOW_SEALING 2U syscallret syscall_mmap(void* hint, size_t len, int prot, int flags, int fd, off_t offset){ + syscallret retv; retv.ret = -1; @@ -79,10 +80,10 @@ syscallret syscall_mmap(void* hint, size_t len, int prot, int flags, int fd, off void* ret = NULL; if(hint) - ret = vmm_allocnowat(hint, mmuflags, plen) ? hint : NULL; // TODO demand page + ret = vmm_allocnowat(hint, mmuflags, len) ? hint : NULL; // TODO demand page if(!ret && !(flags & MAP_FIXED)) - ret = vmm_allocfrom(USER_ALLOC_START, mmuflags, len); + ret = vmm_allocfrom(USER_ALLOC_START, mmuflags, plen); if(!ret){ retv.errno = ENOMEM;