File shadPS4-PR1822.patch of Package shadPS4
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index f90d4e6a..343946ca 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -389,12 +389,8 @@ s32 MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) {
return UnmapMemoryImpl(virtual_addr, size);
}
-s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) {
- const auto it = FindVMA(virtual_addr);
- const auto& vma_base = it->second;
- ASSERT_MSG(vma_base.Contains(virtual_addr, size),
- "Existing mapping does not contain requested unmap range");
-
+size_t MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma_base,
+ size_t size) {
const auto type = vma_base.type;
if (type == VMAType::Free) {
return ORBIS_OK;
@@ -405,16 +401,17 @@ s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) {
const auto phys_base = vma_base.phys_base;
const bool is_exec = vma_base.is_exec;
const auto start_in_vma = virtual_addr - vma_base_addr;
+ const auto adjusted_size =
+ vma_base_size - start_in_vma < size ? vma_base_size - start_in_vma : size;
const bool has_backing = type == VMAType::Direct || type == VMAType::File;
if (type == VMAType::Direct || type == VMAType::Pooled) {
- rasterizer->UnmapMemory(virtual_addr, size);
- }
+ rasterizer->UnmapMemory(virtual_addr, adjusted_size);
if (type == VMAType::Flexible) {
- flexible_usage -= size;
+ flexible_usage -= adjusted_size;
}
// Mark region as free and attempt to coalesce it with neighbours.
- const auto new_it = CarveVMA(virtual_addr, size);
+ const auto new_it = CarveVMA(virtual_addr, adjusted_size);
auto& vma = new_it->second;
vma.type = VMAType::Free;
vma.prot = MemoryProt::NoAccess;
@@ -426,11 +423,25 @@ s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) {
if (type != VMAType::Reserved && type != VMAType::PoolReserved) {
// Unmap the memory region.
- impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + size, phys_base,
- is_exec, has_backing, readonly_file);
+ impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + adjusted_size, phys_base,
+ is_exec, has_backing, readonly_file);
TRACK_FREE(virtual_addr, "VMEM");
}
+ return adjusted_size;
+}
+
+s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) {
+ auto unmapped_bytes = 0;
+ do {
+ auto it = FindVMA(virtual_addr + unmapped_bytes);
+ auto& vma_base = it->second;
+ auto unmapped =
+ UnmapBytesFromEntry(virtual_addr + unmapped_bytes, vma_base, size - unmapped_bytes);
+ ASSERT_MSG(unmapped > 0, "Failed to unmap memory, progress is impossible");
+ unmapped_bytes += unmapped;
+ } while (unmapped_bytes < size);
+
return ORBIS_OK;
}
@@ -651,6 +662,12 @@ MemoryManager::VMAHandle MemoryManager::CarveVMA(VAddr virtual_addr, size_t size
const VAddr start_in_vma = virtual_addr - vma.base;
const VAddr end_in_vma = start_in_vma + size;
+
+ if (start_in_vma == 0 && size == vma.size) {
+ // if requsting the whole VMA, return it
+ return vma_handle;
+ }
+
ASSERT_MSG(end_in_vma <= vma.size, "Mapping cannot fit inside free region");
if (end_in_vma != vma.size) {
diff --git a/src/core/memory.h b/src/core/memory.h
index 615ecc3e..b8f7e7db 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -252,6 +252,8 @@ private:
DMemHandle Split(DMemHandle dmem_handle, size_t offset_in_area);
+ size_t UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma_base, size_t size);
+
s32 UnmapMemoryImpl(VAddr virtual_addr, size_t size);
private: