From 7a83b74d3e372b3062025002c651707af1d404d4 Mon Sep 17 00:00:00 2001 From: "Daniel R." <47796739+polybiusproxy@users.noreply.github.com> Date: Wed, 10 Jul 2024 19:22:11 +0200 Subject: [PATCH] Fix `sceKernelReserveVirtualRange`. --- .../libraries/kernel/memory_management.cpp | 4 +- src/core/memory.cpp | 50 ++++++++++++++++--- src/core/memory.h | 3 ++ 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/core/libraries/kernel/memory_management.cpp b/src/core/libraries/kernel/memory_management.cpp index 61a6ae734..92fde9600 100644 --- a/src/core/libraries/kernel/memory_management.cpp +++ b/src/core/libraries/kernel/memory_management.cpp @@ -107,9 +107,9 @@ s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u } auto* memory = Core::Memory::Instance(); + const VAddr in_addr = reinterpret_cast(*addr); const auto map_flags = static_cast(flags); - memory->MapMemory(addr, 0, len, Core::MemoryProt::NoAccess, map_flags, Core::VMAType::Direct, - "", false, -1, alignment); + memory->Reserve(addr, in_addr, len, map_flags, alignment); return SCE_OK; } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 7eb9a0fa7..a1af228b2 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -83,6 +83,25 @@ void MemoryManager::Free(PAddr phys_addr, size_t size) { MergeAdjacent(dmem_map, dmem_area); } +int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, MemoryMapFlags flags, + u64 alignment) { + std::scoped_lock lk{mutex}; + + virtual_addr = (virtual_addr == 0) ? impl.VirtualBase() : virtual_addr; + + VAddr mapped_addr = alignment > 0 ? Common::AlignUp(virtual_addr, alignment) : virtual_addr; + + // Add virtual memory area + auto& new_vma = AddMapping(mapped_addr, size); + new_vma.disallow_merge = True(flags & MemoryMapFlags::NoCoalesce); + new_vma.prot = MemoryProt::NoAccess; + new_vma.name = ""; + new_vma.type = VMAType::Reserved; + + *out_addr = std::bit_cast(mapped_addr); + return ORBIS_OK; +} + int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, VMAType type, std::string_view name, bool is_exec, PAddr phys_addr, u64 alignment) { @@ -146,18 +165,35 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, uintptr_t fd, size_t offset) { - virtual_addr = impl.VirtualBase(); + if (virtual_addr == 0) { + virtual_addr = impl.VirtualBase(); + } else { + LOG_INFO(Kernel_Vmm, "Virtual addr {:#x} with size {:#x}", virtual_addr, size); + } + + VAddr mapped_addr = 0; const size_t size_aligned = Common::AlignUp(size, 16_KB); // Find first free area to map the file. - auto it = FindVMA(virtual_addr); - while (it->second.type != VMAType::Free || it->second.size < size_aligned) { - it++; + if (False(flags & MemoryMapFlags::Fixed)) { + auto it = FindVMA(virtual_addr); + while (it->second.type != VMAType::Free || it->second.size < size_aligned) { + it++; + } + ASSERT(it != vma_map.end()); + + mapped_addr = it->second.base; + } + + if (True(flags & MemoryMapFlags::Fixed)) { + const auto& vma = FindVMA(virtual_addr)->second; + const size_t remaining_size = vma.base + vma.size - virtual_addr; + ASSERT_MSG((vma.type == VMAType::Free || vma.type == VMAType::Reserved) && remaining_size >= size); + + mapped_addr = virtual_addr; } - ASSERT(it != vma_map.end()); // Map the file. - const VAddr mapped_addr = it->second.base; impl.MapFile(mapped_addr, size, offset, fd); // Add virtual memory area @@ -302,7 +338,7 @@ VirtualMemoryArea& MemoryManager::AddMapping(VAddr virtual_addr, size_t size) { ASSERT_MSG(vma_handle != vma_map.end(), "Virtual address not in vm_map"); const VirtualMemoryArea& vma = vma_handle->second; - ASSERT_MSG(vma.type == VMAType::Free && vma.base <= virtual_addr, + ASSERT_MSG((vma.type == VMAType::Free || vma.type == VMAType::Reserved) && vma.base <= virtual_addr, "Adding a mapping to already mapped region"); const VAddr start_in_vma = virtual_addr - vma.base; diff --git a/src/core/memory.h b/src/core/memory.h index 220fa43ff..d4f1047ba 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -137,6 +137,9 @@ public: void Free(PAddr phys_addr, size_t size); + int Reserve(void** out_addr, VAddr virtual_addr, size_t size, MemoryMapFlags flags, + u64 alignment = 0); + int MapMemory(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, VMAType type, std::string_view name = "", bool is_exec = false, PAddr phys_addr = -1, u64 alignment = 0);