From dc8425a9864bed472ad6efef85c148622533d290 Mon Sep 17 00:00:00 2001 From: Steveice10 <1269164+Steveice10@users.noreply.github.com> Date: Sun, 26 Nov 2023 12:07:10 -0800 Subject: [PATCH] kernel: Fix memory mapping issue introduced in https://github.com/citra-emu/citra/pull/6680 (#7208) --- src/core/hle/kernel/process.cpp | 11 +++++------ src/core/hle/kernel/shared_memory.cpp | 5 +---- src/core/hle/kernel/vm_manager.cpp | 12 +++++------- src/core/hle/kernel/vm_manager.h | 3 ++- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 1027c0e12..9256d9421 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -300,14 +300,15 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { // Free heaps block by block CASCADE_RESULT(auto backing_blocks, vm_manager.GetBackingBlocksForRange(target, size)); - for (const auto& backing_block : backing_blocks) { - memory_region->Free(backing_block.lower(), backing_block.upper() - backing_block.lower()); + for (const auto& [backing_memory, block_size] : backing_blocks) { + const auto backing_offset = kernel.memory.GetFCRAMOffset(backing_memory.GetPtr()); + memory_region->Free(backing_offset, block_size); + holding_memory -= MemoryRegionInfo::Interval(backing_offset, backing_offset + block_size); } ResultCode result = vm_manager.UnmapRange(target, size); ASSERT(result.IsSuccess()); - holding_memory -= backing_blocks; memory_used -= size; resource_limit->current_commit -= size; @@ -504,9 +505,7 @@ ResultCode Process::Map(VAddr target, VAddr source, u32 size, VMAPermission perm CASCADE_RESULT(auto backing_blocks, vm_manager.GetBackingBlocksForRange(source, size)); VAddr interval_target = target; - for (const auto& backing_block : backing_blocks) { - auto backing_memory = kernel.memory.GetFCRAMRef(backing_block.lower()); - auto block_size = backing_block.upper() - backing_block.lower(); + for (const auto& [backing_memory, block_size] : backing_blocks) { auto target_vma = vm_manager.MapBackingMemory(interval_target, backing_memory, block_size, target_state); ASSERT(target_vma.Succeeded()); diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index a28590ad5..b86fd2ae5 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -70,10 +70,7 @@ ResultVal> KernelSystem::CreateSharedMemory( auto backing_blocks = vm_manager.GetBackingBlocksForRange(address, size); ASSERT(backing_blocks.Succeeded()); // should success after verifying memory state above - for (const auto& interval : backing_blocks.Unwrap()) { - shared_memory->backing_blocks.emplace_back(memory.GetFCRAMRef(interval.lower()), - interval.upper() - interval.lower()); - } + shared_memory->backing_blocks = std::move(backing_blocks).Unwrap(); } shared_memory->base_address = address; diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index f187b92bf..f2c798750 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -391,9 +391,9 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { plgldr->OnMemoryChanged(process, Core::System::GetInstance().Kernel()); } -ResultVal VMManager::GetBackingBlocksForRange(VAddr address, - u32 size) { - MemoryRegionInfo::IntervalSet backing_blocks; +ResultVal>> VMManager::GetBackingBlocksForRange(VAddr address, + u32 size) { + std::vector> backing_blocks; VAddr interval_target = address; while (interval_target != address + size) { auto vma = FindVMA(interval_target); @@ -404,10 +404,8 @@ ResultVal VMManager::GetBackingBlocksForRange(VAd VAddr interval_end = std::min(address + size, vma->second.base + vma->second.size); u32 interval_size = interval_end - interval_target; - auto backing_memory = memory.GetFCRAMOffset(vma->second.backing_memory + - (interval_target - vma->second.base)); - backing_blocks += - MemoryRegionInfo::Interval(backing_memory, backing_memory + interval_size); + auto backing_memory = vma->second.backing_memory + (interval_target - vma->second.base); + backing_blocks.push_back({backing_memory, interval_size}); interval_target += interval_size; } diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index d520eeccb..615d5d1ce 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -206,7 +206,8 @@ public: void LogLayout(Common::Log::Level log_level) const; /// Gets a list of backing memory blocks for the specified range - ResultVal GetBackingBlocksForRange(VAddr address, u32 size); + ResultVal>> GetBackingBlocksForRange(VAddr address, + u32 size); /// Each VMManager has its own page table, which is set as the main one when the owning process /// is scheduled.