From b4d55ee1f3cac5419c5a7d2f9e7904d82874b75e Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 20 May 2026 19:29:21 +0000 Subject: [PATCH] Use managarm special fastmem fallback --- src/common/host_memory.cpp | 68 ++++++++++++++++++++++++++++++-------- src/common/host_memory.h | 7 ++++ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 04f3a65778..c405ce4053 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -32,6 +32,8 @@ #include #elif defined(__FreeBSD__) #include +#elif defined(__OPENORBIS__) +#include #endif // FreeBSD @@ -391,6 +393,9 @@ private: ankerl::unordered_dense::map placeholder_host_pointers; ///< Placeholder backing offset }; +#elif defined(__OPENORBIS__) || defined(__managarm__) +// None of the luxuries of POSIX, all of the suffering +// For managarm: see https://github.com/managarm/managarm/issues/1370 #else // ^^^ Windows ^^^ vvv POSIX vvv #ifdef ARCHITECTURE_arm64 @@ -507,7 +512,7 @@ public: fd = shm_open_anon(O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); #elif defined(__FreeBSD__) fd = shm_open(SHM_ANON, O_RDWR, 0600); -#elif defined(__APPLE__) +#elif defined(__APPLE__) || defined(__managarm__) // macOS doesn't have memfd_create, use anonymous temporary file char template_path[] = "/tmp/eden_mem_XXXXXX"; fd = mkstemp(template_path); @@ -669,17 +674,47 @@ private: #endif // ^^^ POSIX ^^^ -HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_) : backing_size(backing_size_), virtual_size(virtual_size_) { - // Try to allocate a fastmem arena. - // The implementation will fail with std::bad_alloc on errors. - impl = std::make_unique(AlignUp(backing_size, PageAlignment), AlignUp(virtual_size, PageAlignment) + HugePageSize); - backing_base = impl->backing_base; - virtual_base = impl->virtual_base; - if (virtual_base) { - // Ensure the virtual base is aligned to the L2 block size. - virtual_base = reinterpret_cast(Common::AlignUp(uintptr_t(virtual_base), HugePageSize)); - virtual_base_offset = virtual_base - impl->virtual_base; +HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_) + : backing_size(backing_size_) + , virtual_size(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(); + virtual_base = nullptr; +#else + bool has_memfd = true; // all platforms support it +#ifdef _WIN32 + // EXCEPT WINDOWS who may not (Windows 8.1, 7, Vista, etc) + DynamicLibrary kernelbase_dll("KernelBase"); + has_memfd = kernelbase_dll.IsOpen(); + if (has_memfd) { + PFN_CreateFileMapping2 p{}; + GetFuncAddress(kernelbase_dll, "CreateFileMapping2", p); + has_memfd = p != nullptr; } +#endif + if (has_memfd) { + // Try to allocate a fastmem arena. + // The implementation will fail with std::bad_alloc on errors. + impl = std::make_unique(AlignUp(backing_size, PageAlignment), AlignUp(virtual_size, PageAlignment) + HugePageSize); + backing_base = impl->backing_base; + virtual_base = impl->virtual_base; + if (virtual_base) { + // Ensure the virtual base is aligned to the L2 block size. + virtual_base = reinterpret_cast(Common::AlignUp(uintptr_t(virtual_base), HugePageSize)); + virtual_base_offset = virtual_base - impl->virtual_base; + } + } else { + LOG_WARNING(HW_Memory, "Platform doesn't support fastmem"); +#ifdef _WIN32 + fallback_buffer.emplace(backing_size); + backing_base = fallback_buffer->data(); + virtual_base = nullptr; +#endif + } +#endif } HostMemory::~HostMemory() = default; @@ -688,8 +723,8 @@ HostMemory::HostMemory(HostMemory&&) noexcept = default; HostMemory& HostMemory::operator=(HostMemory&&) noexcept = default; -void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length, - MemoryPermission perms, bool separate_heap) { +void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perms, bool separate_heap) { +#if !(defined(__OPENORBIS__) || defined(__managarm__)) ASSERT(virtual_offset % PageAlignment == 0); ASSERT(host_offset % PageAlignment == 0); ASSERT(length % PageAlignment == 0); @@ -699,9 +734,11 @@ void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length, return; } impl->Map(virtual_offset + virtual_base_offset, host_offset, length, perms); +#endif } void HostMemory::Unmap(size_t virtual_offset, size_t length, bool separate_heap) { +#if !(defined(__OPENORBIS__) || defined(__managarm__)) ASSERT(virtual_offset % PageAlignment == 0); ASSERT(length % PageAlignment == 0); ASSERT(virtual_offset + length <= virtual_size); @@ -709,9 +746,11 @@ void HostMemory::Unmap(size_t virtual_offset, size_t length, bool separate_heap) return; } impl->Unmap(virtual_offset + virtual_base_offset, length); +#endif } void HostMemory::Protect(size_t virtual_offset, size_t length, MemoryPermission perm) { +#if !(defined(__OPENORBIS__) || defined(__managarm__)) ASSERT(virtual_offset % PageAlignment == 0); ASSERT(length % PageAlignment == 0); ASSERT(virtual_offset + length <= virtual_size); @@ -722,6 +761,7 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, MemoryPermission const bool write = True(perm & MemoryPermission::Write); const bool execute = True(perm & MemoryPermission::Execute); impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute); +#endif } void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) { @@ -729,10 +769,12 @@ void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 f } void HostMemory::EnableDirectMappedAddress() { +#if !(defined(__OPENORBIS__) || defined(__managarm__)) if (impl) { impl->EnableDirectMappedAddress(); virtual_size += reinterpret_cast(virtual_base); } +#endif } } // namespace Common diff --git a/src/common/host_memory.h b/src/common/host_memory.h index 8dd30aa9de..577be22b19 100644 --- a/src/common/host_memory.h +++ b/src/common/host_memory.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include "common/common_funcs.h" #include "common/common_types.h" #include "common/virtual_buffer.h" @@ -76,12 +77,18 @@ private: size_t backing_size{}; size_t virtual_size{}; +#if !(defined(__OPENORBIS__) || defined(__managarm__)) // Low level handler for the platform dependent memory routines class Impl; std::unique_ptr impl; +#endif u8* backing_base{}; u8* virtual_base{}; size_t virtual_base_offset{}; +// Windows requires it for kernels whom lack proper support for some functions! +#if defined(__OPENORBIS__) || defined(__managarm__) || defined(_WIN32) + std::optional> fallback_buffer; +#endif }; } // namespace Common