From 2654a679b3d1a6fb3c36ca00b44dce713b9a98b4 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sun, 4 Nov 2018 12:15:55 -0500 Subject: [PATCH] Memory: replace PhysicalToVirtualAddress with a more dedicated function There is no external use of PhysicalToVirtualAddress any more, so it there is no need to have a generic function that handles all physical regions. Also, the previous APT change makes it possible that linear heap has some regions mapped to old and new VAddr regions at the same time, so we need to check both region and mark cached for the mapped one. RasterizerMarkRegionCached would skip the unmapped one in its loop --- src/core/memory.cpp | 122 ++++++++++++++++++++------------------------ src/core/memory.h | 5 -- 2 files changed, 54 insertions(+), 73 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 697345ea7..af37ff471 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -318,6 +318,22 @@ u8* GetPhysicalPointer(PAddr address) { return target_pointer; } +/// For a rasterizer-accessible PAddr, gets a list of all possible VAddr +static std::vector PhysicalToVirtualAddressForRasterizer(PAddr addr) { + if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { + return {addr - VRAM_PADDR + VRAM_VADDR}; + } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { + return {addr - FCRAM_PADDR + LINEAR_HEAP_VADDR, addr - FCRAM_PADDR + NEW_LINEAR_HEAP_VADDR}; + } else { + // While the physical <-> virtual mapping is 1:1 for the regions supported by the cache, + // some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond + // the end address of VRAM, causing the Virtual->Physical translation to fail when flushing + // parts of the texture. + LOG_ERROR(HW_Memory, "Trying to use invalid physical address for rasterizer: {:08X}", addr); + return {}; + } +} + void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { if (start == 0) { return; @@ -327,57 +343,46 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { PAddr paddr = start; for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) { - std::optional maybe_vaddr = PhysicalToVirtualAddress(paddr); - // While the physical <-> virtual mapping is 1:1 for the regions supported by the cache, - // some games (like Pokemon Super Mystery Dungeon) will try to use textures that go beyond - // the end address of VRAM, causing the Virtual->Physical translation to fail when flushing - // parts of the texture. - if (!maybe_vaddr) { - LOG_ERROR(HW_Memory, - "Trying to flush a cached region to an invalid physical address {:08X}", - paddr); - continue; - } - VAddr vaddr = *maybe_vaddr; + for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) { + PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; - PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; - - if (cached) { - // Switch page type to cached if now cached - switch (page_type) { - case PageType::Unmapped: - // It is not necessary for a process to have this region mapped into its address - // space, for example, a system module need not have a VRAM mapping. - break; - case PageType::Memory: - page_type = PageType::RasterizerCachedMemory; - current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; - break; - default: - UNREACHABLE(); - } - } else { - // Switch page type to uncached if now uncached - switch (page_type) { - case PageType::Unmapped: - // It is not necessary for a process to have this region mapped into its address - // space, for example, a system module need not have a VRAM mapping. - break; - case PageType::RasterizerCachedMemory: { - u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); - if (pointer == nullptr) { - // It's possible that this function has been called while updating the pagetable - // after unmapping a VMA. In that case the underlying VMA will no longer exist, - // and we should just leave the pagetable entry blank. - page_type = PageType::Unmapped; - } else { - page_type = PageType::Memory; - current_page_table->pointers[vaddr >> PAGE_BITS] = pointer; + if (cached) { + // Switch page type to cached if now cached + switch (page_type) { + case PageType::Unmapped: + // It is not necessary for a process to have this region mapped into its address + // space, for example, a system module need not have a VRAM mapping. + break; + case PageType::Memory: + page_type = PageType::RasterizerCachedMemory; + current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; + break; + default: + UNREACHABLE(); + } + } else { + // Switch page type to uncached if now uncached + switch (page_type) { + case PageType::Unmapped: + // It is not necessary for a process to have this region mapped into its address + // space, for example, a system module need not have a VRAM mapping. + break; + case PageType::RasterizerCachedMemory: { + u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); + if (pointer == nullptr) { + // It's possible that this function has been called while updating the + // pagetable after unmapping a VMA. In that case the underlying VMA will no + // longer exist, and we should just leave the pagetable entry blank. + page_type = PageType::Unmapped; + } else { + page_type = PageType::Memory; + current_page_table->pointers[vaddr >> PAGE_BITS] = pointer; + } + break; + } + default: + UNREACHABLE(); } - break; - } - default: - UNREACHABLE(); } } } @@ -820,25 +825,6 @@ PAddr VirtualToPhysicalAddress(const VAddr addr) { return *paddr; } -std::optional PhysicalToVirtualAddress(const PAddr addr) { - if (addr == 0) { - return 0; - } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { - return addr - VRAM_PADDR + VRAM_VADDR; - } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { - return addr - FCRAM_PADDR + - Core::System::GetInstance().Kernel().GetCurrentProcess()->GetLinearHeapAreaAddress(); - } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) { - return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; - } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { - return addr - IO_AREA_PADDR + IO_AREA_VADDR; - } else if (addr >= N3DS_EXTRA_RAM_PADDR && addr < N3DS_EXTRA_RAM_PADDR_END) { - return addr - N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_VADDR; - } - - return {}; -} - u32 GetFCRAMOffset(u8* pointer) { ASSERT(pointer >= fcram.data() && pointer < fcram.data() + fcram.size()); return pointer - fcram.data(); diff --git a/src/core/memory.h b/src/core/memory.h index bad47375a..a1e4383df 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -228,11 +228,6 @@ std::optional TryVirtualToPhysicalAddress(VAddr addr); */ PAddr VirtualToPhysicalAddress(VAddr addr); -/** - * Undoes a mapping performed by VirtualToPhysicalAddress(). - */ -std::optional PhysicalToVirtualAddress(PAddr paddr); - /** * Gets a pointer to the memory region beginning at the specified physical address. */