diff --git a/src/xenia/base/memory.h b/src/xenia/base/memory.h index 4b8a99237..94c998c92 100644 --- a/src/xenia/base/memory.h +++ b/src/xenia/base/memory.h @@ -50,6 +50,7 @@ enum class DeallocationType { // Allocates a block of memory at the given page-aligned base address. // Fails if the memory is not available. +// Specify nullptr for base_address to leave it up to the system. void* AllocFixed(void* base_address, size_t length, AllocationType allocation_type, PageAccess access); diff --git a/src/xenia/base/memory_posix.cc b/src/xenia/base/memory_posix.cc index d6b0dd062..1af6c74d8 100644 --- a/src/xenia/base/memory_posix.cc +++ b/src/xenia/base/memory_posix.cc @@ -17,19 +17,41 @@ namespace memory { size_t page_size() { return getpagesize(); } size_t allocation_granularity() { return page_size(); } +uint32_t ToPosixProtectFlags(PageAccess access) { + switch (access) { + case PageAccess::kNoAccess: + return PROT_NONE; + case PageAccess::kReadOnly: + return PROT_READ; + case PageAccess::kReadWrite: + return PROT_READ | PROT_WRITE; + case PageAccess::kExecuteReadWrite: + return PROT_READ | PROT_WRITE | PROT_EXEC; + default: + assert_unhandled_case(access); + return PROT_NONE; + } +} + void* AllocFixed(void* base_address, size_t length, AllocationType allocation_type, PageAccess access) { - return nullptr; + // mmap does not support reserve / commit, so ignore allocation_type. + uint32_t prot = ToPosixProtectFlags(access); + return mmap(base_address, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } bool DeallocFixed(void* base_address, size_t length, DeallocationType deallocation_type) { - return false; + return munmap(base_address, length) == 0; } bool Protect(void* base_address, size_t length, PageAccess access, PageAccess* out_old_access) { - return false; + // Linux does not have a syscall to query memory permissions. + assert_null(out_old_access); + + uint32_t prot = ToPosixProtectFlags(access); + return mprotect(base_address, length, prot) == 0; } bool QueryProtect(void* base_address, size_t& length, PageAccess& access_out) {