#include "Log.h" #include "arch/MMU.h" #include "memory/MemoryManager.h" #include "sys/Syscall.h" #include "thread/Scheduler.h" #include #include constexpr uintptr_t USERSPACE_HEAP_BASE = 0x3000000; Result sys_mmap(Registers*, SyscallArgs args) { void* addr = (void*)args[0]; usize len = (usize)args[1]; int prot = (int)args[2]; int flags = (int)args[3]; if (len == 0) return err(EINVAL); if (flags < 0) return err(EINVAL); // We support only anonymous mappings for now. if ((flags & MAP_ANONYMOUS) != MAP_ANONYMOUS) { kwarnln("mmap: FIXME: attempt to mmap file instead of anonymous memory"); return err(ENOTSUP); } if (flags & MAP_SHARED) { kwarnln("mmap: FIXME: attempt to mmap shared memory"); return err(ENOTSUP); } len = align_up(len); Thread* current = Scheduler::current(); u64 address; if (!addr) address = TRY(current->vm_allocator->alloc_region(get_blocks_from_size(len, ARCH_PAGE_SIZE))); else { // FIXME: We should be more flexible if MAP_FIXED was not specified. if (!TRY(current->vm_allocator->test_and_alloc_region((u64)addr, get_blocks_from_size(len, ARCH_PAGE_SIZE)))) return err(ENOMEM); address = (u64)addr; } int mmu_flags = MMU::User | MMU::NoExecute; if (prot & PROT_WRITE) mmu_flags |= MMU::ReadWrite; if (prot & PROT_EXEC) mmu_flags &= ~MMU::NoExecute; if (prot == PROT_NONE) mmu_flags = MMU::NoExecute; #ifdef MMAP_DEBUG kdbgln("mmap: mapping memory at %#lx, size=%zu", address, len); #endif // FIXME: This leaks VM if it fails. return MemoryManager::alloc_at_zeroed(address, get_blocks_from_size(len, ARCH_PAGE_SIZE), mmu_flags); } Result sys_munmap(Registers*, SyscallArgs args) { u64 address = (u64)args[0]; usize size = (usize)args[1]; if (size == 0) return err(EINVAL); if (!is_aligned(size)) return err(EINVAL); Thread* current = Scheduler::current(); bool ok = TRY(current->vm_allocator->free_region(address, get_blocks_from_size(size, ARCH_PAGE_SIZE))); // POSIX says munmap should silently do nothing if the memory was not already mapped. if (!ok) return 0; #ifdef MMAP_DEBUG kdbgln("munmap: unmapping memory at %#lx, size=%zu", address, size); #endif TRY(MemoryManager::unmap_owned(address, get_blocks_from_size(size, ARCH_PAGE_SIZE))); return { 0 }; }