Kernel.Vmm: Fix bug with VMA physical area tracking (#3998)
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-sdl-gcc (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions

* Fix bug with "phys_addr_to_search" logic

By improperly updating the variable, some games would mark the same dmem area as mapped in different parts of the vma, and the dmem map wouldn't properly reflect the state of the vma's phys areas.

* Clang

* Oops
This commit is contained in:
Stephen Miller 2026-02-07 00:38:44 -06:00 committed by GitHub
parent b88ec484ba
commit f911ed23a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -593,7 +593,10 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo
// Tracy memory tracking breaks from merging memory areas. Disabled for now.
// TRACK_ALLOC(out_addr, size_to_map, "VMEM");
// Merge this handle with adjacent areas
handle = MergeAdjacent(fmem_map, new_fmem_handle);
// Get the next flexible area.
current_addr += size_to_map;
remaining_size -= size_to_map;
flexible_usage += size_to_map;
@ -602,13 +605,13 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo
ASSERT_MSG(remaining_size == 0, "Failed to map physical memory");
} else if (type == VMAType::Direct) {
// Map the physical memory for this direct memory mapping.
auto phys_addr_to_search = phys_addr;
auto current_phys_addr = phys_addr;
u64 remaining_size = size;
auto dmem_area = FindDmemArea(phys_addr);
while (dmem_area != dmem_map.end() && remaining_size > 0) {
// Carve a new dmem area in place of this one with the appropriate type.
// Ensure the carved area only covers the current dmem area.
const auto start_phys_addr = std::max<PAddr>(phys_addr, dmem_area->second.base);
const auto start_phys_addr = std::max<PAddr>(current_phys_addr, dmem_area->second.base);
const auto offset_in_dma = start_phys_addr - dmem_area->second.base;
const auto size_in_dma =
std::min<u64>(dmem_area->second.size - offset_in_dma, remaining_size);
@ -617,17 +620,17 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo
new_dmem_area.dma_type = PhysicalMemoryType::Mapped;
// Add the dmem area to this vma, merge it with any similar tracked areas.
new_vma.phys_areas[phys_addr_to_search - phys_addr] = dmem_handle->second;
MergeAdjacent(new_vma.phys_areas,
new_vma.phys_areas.find(phys_addr_to_search - phys_addr));
const u64 offset_in_vma = current_phys_addr - phys_addr;
new_vma.phys_areas[offset_in_vma] = dmem_handle->second;
MergeAdjacent(new_vma.phys_areas, new_vma.phys_areas.find(offset_in_vma));
// Merge the new dmem_area with dmem_map
MergeAdjacent(dmem_map, dmem_handle);
// Get the next relevant dmem area.
phys_addr_to_search = phys_addr + size_in_dma;
current_phys_addr += size_in_dma;
remaining_size -= size_in_dma;
dmem_area = FindDmemArea(phys_addr_to_search);
dmem_area = FindDmemArea(current_phys_addr);
}
ASSERT_MSG(remaining_size == 0, "Failed to map physical memory");
}