diff options
Diffstat (limited to 'src/common/host_memory.cpp')
| -rw-r--r-- | src/common/host_memory.cpp | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index dd0780a283..75a9da80e9 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -178,6 +178,14 @@ public: Release(); } + void* Allocate(size_t size) { + auto* ptr = VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (ptr == nullptr) { + LOG_CRITICAL(HW_Memory, "Failed to allocate fallback buffer with size {:#x}, error {}", size, GetLastError()); + } + return ptr; + } + void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms) { std::unique_lock lock{placeholder_mutex}; if (!IsNiechePlaceholder(virtual_offset, length)) { @@ -398,6 +406,10 @@ private: // For managarm: see https://github.com/managarm/managarm/issues/1370 #else // ^^^ Windows ^^^ vvv POSIX vvv +#ifndef MAP_NOCORE +#define MAP_NOCORE 0 +#endif + #ifdef ARCHITECTURE_arm64 static void* ChooseVirtualBase(size_t virtual_size) { @@ -422,7 +434,7 @@ static void* ChooseVirtualBase(size_t virtual_size) { // Note: we may be able to take advantage of MAP_FIXED_NOREPLACE here. void* map_pointer = mmap(reinterpret_cast<void*>(hint_address), virtual_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_NOCORE, -1, 0); // If we successfully mapped, we're done. if (reinterpret_cast<uintptr_t>(map_pointer) == hint_address) { @@ -442,11 +454,11 @@ static void* ChooseVirtualBase(size_t virtual_size) { static void* ChooseVirtualBase(size_t virtual_size) { #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__managarm__) || defined(__AIX__) - void* virtual_base = mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER, -1, 0); + void* virtual_base = mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_ALIGNED_SUPER | MAP_NOCORE, -1, 0); if (virtual_base != MAP_FAILED) return virtual_base; #endif - return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + return mmap(nullptr, virtual_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_NOCORE, -1, 0); } #endif @@ -540,13 +552,13 @@ public: } if (use_anon) { LOG_WARNING(Common_Memory, "Using private mappings instead of shared ones"); - backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); + backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NOCORE, -1, 0)); if (fd > 0) { fd = -1; close(fd); } } else { - backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); + backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOCORE, fd, 0)); } if (backing_base == MAP_FAILED) { LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno)); @@ -570,6 +582,14 @@ public: Release(); } + void* Allocate(size_t size) { + auto* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (ptr == MAP_FAILED) { + LOG_CRITICAL(HW_Memory, "Failed to allocate fallback buffer with size {:#x}, {}", size, strerror(errno)); + } + return ptr; + } + void Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms) { // Intersect the range with our address space. AdjustMap(&virtual_offset, &length); @@ -690,12 +710,10 @@ HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_) { #if defined(__OPENORBIS__) || defined(__managarm__) LOG_WARNING(HW_Memory, "Platform doesn't support fastmem"); - fallback_buffer.emplace(backing_size); - backing_base = fallback_buffer->data(); + backing_base = static_cast<u8*>(mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); virtual_base = nullptr; #else // Try to allocate a fastmem arena. - // The implementation will fail with std::bad_alloc on errors. impl = std::make_unique<HostMemory::Impl>(AlignUp(backing_size, PageAlignment), AlignUp(virtual_size, PageAlignment) + HugePageSize); if (impl->Init()) { backing_base = impl->backing_base; @@ -706,16 +724,26 @@ HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_) virtual_base_offset = virtual_base - impl->virtual_base; } } else { - impl.reset(); LOG_WARNING(HW_Memory, "Platform can support fastmem, but can't create it"); - fallback_buffer.emplace(backing_size); - backing_base = fallback_buffer->data(); + fallback_buffer = true; + backing_base = static_cast<u8*>(impl->Allocate(backing_size)); virtual_base = nullptr; + impl.reset(); } #endif } -HostMemory::~HostMemory() = default; +HostMemory::~HostMemory() { +#ifdef _WIN32 + if (fallback_buffer) { + VirtualFree(backing_base, backing_size, MEM_RELEASE); + } +#else + if (fallback_buffer) { + munmap(backing_base, backing_size); + } +#endif +} HostMemory::HostMemory(HostMemory&&) noexcept = default; |
