citra-emu
/
citra-canary
Archived
1
0
Fork 0

Memory: replace GetPointerFromVMA with GetPointerForRasterizerCache

All usage of GetPointerFromVMA is to recover the pointer that is nulled by changing page type to RasterizerCachedMemory. Our rasterizer cache only works on linear heap and vram, so we can recover the pointer directly by address computation, instead of going through VMA table. Also removed a sanity check pointer!=nullptr in RasterizerMarkRegionCached(RasterizerCachedMemory=>Memory), as now the pointer is never null. The sanity check was added in f2a5a77 (#2797), which was originally necessary during VMA unmapping process, because the function is invloked by VMA after unmapping the page, which in turn invokes back to query the memory, forming a circular dependency. Now the dependency is resolved so the check is not necessary
This commit is contained in:
Weiyi Wang 2018-11-17 14:17:20 -05:00
parent 2b768da531
commit 36cf104a02
1 changed files with 26 additions and 47 deletions

View File

@ -79,37 +79,22 @@ void UnmapRegion(PageTable& page_table, VAddr base, u32 size) {
} }
/** /**
* Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) * Gets the pointer for virtual memory where the page is marked as RasterizerCachedMemory.
* using a VMA from the current process * This is used to access the memory where the page pointer is nullptr due to rasterizer cache.
* Since the cache only happens on linear heap or VRAM, we know the exact physical address and
* pointer of such virtual address
*/ */
static u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) { static u8* GetPointerForRasterizerCache(VAddr addr) {
u8* direct_pointer = nullptr; if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
return fcram.data() + (addr - LINEAR_HEAP_VADDR);
auto& vm_manager = process.vm_manager;
auto it = vm_manager.FindVMA(vaddr);
ASSERT(it != vm_manager.vma_map.end());
auto& vma = it->second;
switch (vma.type) {
case Kernel::VMAType::BackingMemory:
direct_pointer = vma.backing_memory;
break;
case Kernel::VMAType::Free:
return nullptr;
default:
UNREACHABLE();
} }
if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) {
return direct_pointer + (vaddr - vma.base); return fcram.data() + (addr - NEW_LINEAR_HEAP_VADDR);
} }
if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
/** return vram.data() + (addr - VRAM_VADDR);
* Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) }
* using a VMA from the current process. UNREACHABLE();
*/
static u8* GetPointerFromVMA(VAddr vaddr) {
return GetPointerFromVMA(*Core::System::GetInstance().Kernel().GetCurrentProcess(), vaddr);
} }
/** /**
@ -159,7 +144,7 @@ T Read(const VAddr vaddr) {
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush); RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
T value; T value;
std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T)); std::memcpy(&value, GetPointerForRasterizerCache(vaddr), sizeof(T));
return value; return value;
} }
case PageType::Special: case PageType::Special:
@ -195,7 +180,7 @@ void Write(const VAddr vaddr, const T data) {
break; break;
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate); RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate);
std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); std::memcpy(GetPointerForRasterizerCache(vaddr), &data, sizeof(T));
break; break;
} }
case PageType::Special: case PageType::Special:
@ -242,7 +227,7 @@ u8* GetPointer(const VAddr vaddr) {
} }
if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) {
return GetPointerFromVMA(vaddr); return GetPointerForRasterizerCache(vaddr);
} }
LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x}", vaddr); LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x}", vaddr);
@ -364,16 +349,9 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) {
// space, for example, a system module need not have a VRAM mapping. // space, for example, a system module need not have a VRAM mapping.
break; break;
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); page_type = PageType::Memory;
if (pointer == nullptr) { current_page_table->pointers[vaddr >> PAGE_BITS] =
// It's possible that this function has been called while updating the GetPointerForRasterizerCache(vaddr & ~PAGE_MASK);
// 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; break;
} }
default: default:
@ -501,7 +479,7 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
FlushMode::Flush); FlushMode::Flush);
std::memcpy(dest_buffer, GetPointerFromVMA(process, current_vaddr), copy_amount); std::memcpy(dest_buffer, GetPointerForRasterizerCache(current_vaddr), copy_amount);
break; break;
} }
default: default:
@ -570,7 +548,7 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
FlushMode::Invalidate); FlushMode::Invalidate);
std::memcpy(GetPointerFromVMA(process, current_vaddr), src_buffer, copy_amount); std::memcpy(GetPointerForRasterizerCache(current_vaddr), src_buffer, copy_amount);
break; break;
} }
default: default:
@ -624,7 +602,7 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std:
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
FlushMode::Invalidate); FlushMode::Invalidate);
std::memset(GetPointerFromVMA(process, current_vaddr), 0, copy_amount); std::memset(GetPointerForRasterizerCache(current_vaddr), 0, copy_amount);
break; break;
} }
default: default:
@ -677,7 +655,8 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
FlushMode::Flush); FlushMode::Flush);
WriteBlock(process, dest_addr, GetPointerFromVMA(process, current_vaddr), copy_amount); WriteBlock(process, dest_addr, GetPointerForRasterizerCache(current_vaddr),
copy_amount);
break; break;
} }
default: default:
@ -732,7 +711,7 @@ void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_p
case PageType::RasterizerCachedMemory: { case PageType::RasterizerCachedMemory: {
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
FlushMode::Flush); FlushMode::Flush);
WriteBlock(dest_process, dest_addr, GetPointerFromVMA(src_process, current_vaddr), WriteBlock(dest_process, dest_addr, GetPointerForRasterizerCache(current_vaddr),
copy_amount); copy_amount);
break; break;
} }