mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-10-30 19:23:39 +01:00
core: Do not expand host mmap range during POSIX AddressSpace::Unmap (#5189)
Calling mmap(MAP_FIXED) over an expanded coalesced range and mutating *size causes issues: - Calling mmap over already-free PROT_NONE memory adds redundant kernel overhead and risks Mach VM submap collisions on macOS. - Mutating *size passes inflated ranges to callers like the GPU rasterizer. Unmap strictly the requested [virtual_addr, virtual_addr + *size) range on the host, preserve *size, and remove unused m_free_regions from the POSIX implementation.
This commit is contained in:
1 parent
e9f2c54c20
commit
437dc7eb8f
2 files changed
+9
-35
No files matched your search
@@ -732,13 +732,6 @@ struct AddressSpace::Impl {
|
||||
LOG_INFO(Kernel_Vmm, "User virtual memory region: {} - {}", fmt::ptr(user_base),
|
||||
fmt::ptr(user_base + user_size - 1));
|
||||
|
||||
const VAddr system_managed_addr = reinterpret_cast<VAddr>(system_managed_base);
|
||||
const VAddr system_reserved_addr = reinterpret_cast<VAddr>(system_reserved_base);
|
||||
const VAddr user_addr = reinterpret_cast<VAddr>(user_base);
|
||||
m_free_regions.insert({system_managed_addr, system_managed_addr + system_managed_size});
|
||||
m_free_regions.insert({system_reserved_addr, system_reserved_addr + system_reserved_size});
|
||||
m_free_regions.insert({user_addr, user_addr + user_size});
|
||||
|
||||
#ifdef __APPLE__
|
||||
const auto shm_path = fmt::format("/BackingDmem{}", getpid());
|
||||
backing_fd = shm_open(shm_path.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
@@ -781,7 +774,6 @@ struct AddressSpace::Impl {
|
||||
|
||||
void* Map(VAddr virtual_addr, PAddr phys_addr, u64 size, PosixPageProtection prot,
|
||||
int fd = -1) {
|
||||
m_free_regions.subtract({virtual_addr, virtual_addr + size});
|
||||
#ifdef __APPLE__
|
||||
if ((prot & PROT_EXEC) != 0) {
|
||||
ASSERT_MSG(fd == -1, "Requested execute permissions for file mapping");
|
||||
@@ -798,30 +790,16 @@ struct AddressSpace::Impl {
|
||||
}
|
||||
|
||||
VAddr Unmap(VAddr virtual_addr, u64* size) {
|
||||
// Check to see if we are adjacent to any regions.
|
||||
VAddr start_address = virtual_addr;
|
||||
VAddr end_address = start_address + *size;
|
||||
ASSERT_MSG(size != nullptr && *size > 0, "Invalid unmap size");
|
||||
|
||||
// If we are, join with them, ensuring we stay in bounds.
|
||||
auto it = m_free_regions.find({start_address - 1, end_address});
|
||||
if (it != m_free_regions.end()) {
|
||||
start_address = std::min(start_address, it->lower());
|
||||
}
|
||||
it = m_free_regions.find({start_address, end_address + 1});
|
||||
if (it != m_free_regions.end()) {
|
||||
end_address = std::max(end_address, it->upper());
|
||||
}
|
||||
|
||||
// Free the relevant region.
|
||||
m_free_regions.insert({start_address, end_address});
|
||||
|
||||
// Return the adjusted pointers.
|
||||
void* ret = mmap(reinterpret_cast<void*>(start_address), end_address - start_address,
|
||||
PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
int map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
|
||||
#if !defined(__FreeBSD__)
|
||||
map_flags |= MAP_NORESERVE;
|
||||
#endif
|
||||
void* ret = mmap(reinterpret_cast<void*>(virtual_addr), *size, PROT_NONE, map_flags, -1, 0);
|
||||
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
|
||||
|
||||
*size = end_address - start_address;
|
||||
return reinterpret_cast<VAddr>(ret);
|
||||
return virtual_addr;
|
||||
}
|
||||
|
||||
void Protect(VAddr virtual_addr, u64 size, bool read, bool write, bool execute) {
|
||||
@@ -849,7 +827,6 @@ struct AddressSpace::Impl {
|
||||
u64 system_reserved_size{};
|
||||
u8* user_base{};
|
||||
u64 user_size{};
|
||||
boost::icl::interval_set<VAddr> m_free_regions;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -91,10 +91,7 @@ public:
|
||||
/// Memory maps a specified file descriptor.
|
||||
void* MapFile(VAddr virtual_addr, u64 size, u64 offset, u32 prot, uintptr_t fd);
|
||||
|
||||
/// Unmaps specified virtual memory area.
|
||||
/// Due to coalescing unmapped areas (implemented to save on VMAs), the real replaced area
|
||||
/// might be different to what has been passed to Unmap. Therefore, a new address is returned
|
||||
/// and size is updated to properly represent the mmapped area.
|
||||
/// Unmaps specified virtual memory area and marks it free in the address space.
|
||||
VAddr Unmap(VAddr virtual_addr, u64* size);
|
||||
|
||||
/// Protects requested region.
|
||||
|
||||
Reference in new issue
Block a user