Merge pull request #2797 from yuriks/cached-vma-free-crash

Memory: Fix crash when unmapping a VMA covering cached surfaces
This commit is contained in:
bunnei 2017-07-08 14:07:47 -04:00 committed by GitHub
commit 6d4bac8522
1 changed files with 20 additions and 5 deletions

View File

@ -139,7 +139,12 @@ void UnmapRegion(VAddr base, u32 size) {
static u8* GetPointerFromVMA(VAddr vaddr) { static u8* GetPointerFromVMA(VAddr vaddr) {
u8* direct_pointer = nullptr; u8* direct_pointer = nullptr;
auto& vma = Kernel::g_current_process->vm_manager.FindVMA(vaddr)->second; auto& vm_manager = Kernel::g_current_process->vm_manager;
auto it = vm_manager.FindVMA(vaddr);
ASSERT(it != vm_manager.vma_map.end());
auto& vma = it->second;
switch (vma.type) { switch (vma.type) {
case Kernel::VMAType::AllocatedMemoryBlock: case Kernel::VMAType::AllocatedMemoryBlock:
direct_pointer = vma.backing_block->data() + vma.offset; direct_pointer = vma.backing_block->data() + vma.offset;
@ -147,6 +152,8 @@ static u8* GetPointerFromVMA(VAddr vaddr) {
case Kernel::VMAType::BackingMemory: case Kernel::VMAType::BackingMemory:
direct_pointer = vma.backing_memory; direct_pointer = vma.backing_memory;
break; break;
case Kernel::VMAType::Free:
return nullptr;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -341,11 +348,19 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
if (res_count == 0) { if (res_count == 0) {
PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
switch (page_type) { switch (page_type) {
case PageType::RasterizerCachedMemory: case PageType::RasterizerCachedMemory: {
page_type = PageType::Memory; u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
current_page_table->pointers[vaddr >> PAGE_BITS] = if (pointer == nullptr) {
GetPointerFromVMA(vaddr & ~PAGE_MASK); // It's possible that this function has called been 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; break;
}
case PageType::RasterizerCachedSpecial: case PageType::RasterizerCachedSpecial:
page_type = PageType::Special; page_type = PageType::Special;
break; break;