From f823c1d5991657a3d91f97c345e1f01a1162fca7 Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 23 Apr 2018 10:57:12 -0500 Subject: GPU: Make the GPU virtual memory manager use 16 page bits and 10 page table bits. Also removed some dead code and added memory map consistency asserts. --- src/video_core/memory_manager.cpp | 53 +++++++++++++++------------------------ 1 file changed, 20 insertions(+), 33 deletions(-) (limited to 'src/video_core/memory_manager.cpp') diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 2789a4ca1..2e1edee03 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/alignment.h" #include "common/assert.h" #include "video_core/memory_manager.h" @@ -11,7 +12,8 @@ PAddr MemoryManager::AllocateSpace(u64 size, u64 align) { boost::optional paddr = FindFreeBlock(size, align); ASSERT(paddr); - for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { + for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { + ASSERT(PageSlot(*paddr + offset) == static_cast(PageStatus::Unmapped)); PageSlot(*paddr + offset) = static_cast(PageStatus::Allocated); } @@ -19,13 +21,8 @@ PAddr MemoryManager::AllocateSpace(u64 size, u64 align) { } PAddr MemoryManager::AllocateSpace(PAddr paddr, u64 size, u64 align) { - for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { - if (IsPageMapped(paddr + offset)) { - return AllocateSpace(size, align); - } - } - - for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { + for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { + ASSERT(PageSlot(paddr + offset) == static_cast(PageStatus::Unmapped)); PageSlot(paddr + offset) = static_cast(PageStatus::Allocated); } @@ -33,12 +30,11 @@ PAddr MemoryManager::AllocateSpace(PAddr paddr, u64 size, u64 align) { } PAddr MemoryManager::MapBufferEx(VAddr vaddr, u64 size) { - vaddr &= ~Memory::PAGE_MASK; - - boost::optional paddr = FindFreeBlock(size); + boost::optional paddr = FindFreeBlock(size, PAGE_SIZE); ASSERT(paddr); - for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { + for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { + ASSERT(PageSlot(*paddr + offset) == static_cast(PageStatus::Unmapped)); PageSlot(*paddr + offset) = vaddr + offset; } @@ -46,16 +42,10 @@ PAddr MemoryManager::MapBufferEx(VAddr vaddr, u64 size) { } PAddr MemoryManager::MapBufferEx(VAddr vaddr, PAddr paddr, u64 size) { - vaddr &= ~Memory::PAGE_MASK; - paddr &= ~Memory::PAGE_MASK; + ASSERT((paddr & PAGE_MASK) == 0); - for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { - if (PageSlot(paddr + offset) != static_cast(PageStatus::Allocated)) { - return MapBufferEx(vaddr, size); - } - } - - for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { + for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { + ASSERT(PageSlot(paddr + offset) == static_cast(PageStatus::Allocated)); PageSlot(paddr + offset) = vaddr + offset; } @@ -63,23 +53,20 @@ PAddr MemoryManager::MapBufferEx(VAddr vaddr, PAddr paddr, u64 size) { } boost::optional MemoryManager::FindFreeBlock(u64 size, u64 align) { - PAddr paddr{}; - u64 free_space{}; - align = (align + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; + PAddr paddr = 0; + u64 free_space = 0; + align = (align + PAGE_MASK) & ~PAGE_MASK; while (paddr + free_space < MAX_ADDRESS) { if (!IsPageMapped(paddr + free_space)) { - free_space += Memory::PAGE_SIZE; + free_space += PAGE_SIZE; if (free_space >= size) { return paddr; } } else { - paddr += free_space + Memory::PAGE_SIZE; + paddr += free_space + PAGE_SIZE; free_space = 0; - const u64 remainder{paddr % align}; - if (!remainder) { - paddr = (paddr - remainder) + align; - } + paddr = Common::AlignUp(paddr, align); } } @@ -89,7 +76,7 @@ boost::optional MemoryManager::FindFreeBlock(u64 size, u64 align) { VAddr MemoryManager::PhysicalToVirtualAddress(PAddr paddr) { VAddr base_addr = PageSlot(paddr); ASSERT(base_addr != static_cast(PageStatus::Unmapped)); - return base_addr + (paddr & Memory::PAGE_MASK); + return base_addr + (paddr & PAGE_MASK); } bool MemoryManager::IsPageMapped(PAddr paddr) { @@ -97,14 +84,14 @@ bool MemoryManager::IsPageMapped(PAddr paddr) { } VAddr& MemoryManager::PageSlot(PAddr paddr) { - auto& block = page_table[(paddr >> (Memory::PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK]; + auto& block = page_table[(paddr >> (PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK]; if (!block) { block = std::make_unique(); for (unsigned index = 0; index < PAGE_BLOCK_SIZE; index++) { (*block)[index] = static_cast(PageStatus::Unmapped); } } - return (*block)[(paddr >> Memory::PAGE_BITS) & PAGE_BLOCK_MASK]; + return (*block)[(paddr >> PAGE_BITS) & PAGE_BLOCK_MASK]; } } // namespace Tegra -- cgit v1.2.3 From 9e11a76e926a7190880063d8fc8c3d97003b9938 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 21 Apr 2018 11:16:21 -0400 Subject: memory_manager: Use GPUVAdddr, not PAddr, for GPU addresses. --- src/video_core/memory_manager.cpp | 72 +++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'src/video_core/memory_manager.cpp') diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 2e1edee03..3f21071c0 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -8,90 +8,90 @@ namespace Tegra { -PAddr MemoryManager::AllocateSpace(u64 size, u64 align) { - boost::optional paddr = FindFreeBlock(size, align); - ASSERT(paddr); +GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) { + boost::optional gpu_addr = FindFreeBlock(size, align); + ASSERT(gpu_addr); for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { - ASSERT(PageSlot(*paddr + offset) == static_cast(PageStatus::Unmapped)); - PageSlot(*paddr + offset) = static_cast(PageStatus::Allocated); + ASSERT(PageSlot(*gpu_addr + offset) == static_cast(PageStatus::Unmapped)); + PageSlot(*gpu_addr + offset) = static_cast(PageStatus::Allocated); } - return *paddr; + return *gpu_addr; } -PAddr MemoryManager::AllocateSpace(PAddr paddr, u64 size, u64 align) { +GPUVAddr MemoryManager::AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align) { for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { - ASSERT(PageSlot(paddr + offset) == static_cast(PageStatus::Unmapped)); - PageSlot(paddr + offset) = static_cast(PageStatus::Allocated); + ASSERT(PageSlot(gpu_addr + offset) == static_cast(PageStatus::Unmapped)); + PageSlot(gpu_addr + offset) = static_cast(PageStatus::Allocated); } - return paddr; + return gpu_addr; } -PAddr MemoryManager::MapBufferEx(VAddr vaddr, u64 size) { - boost::optional paddr = FindFreeBlock(size, PAGE_SIZE); - ASSERT(paddr); +GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) { + boost::optional gpu_addr = FindFreeBlock(size, PAGE_SIZE); + ASSERT(gpu_addr); for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { - ASSERT(PageSlot(*paddr + offset) == static_cast(PageStatus::Unmapped)); - PageSlot(*paddr + offset) = vaddr + offset; + ASSERT(PageSlot(*gpu_addr + offset) == static_cast(PageStatus::Unmapped)); + PageSlot(*gpu_addr + offset) = cpu_addr + offset; } - return *paddr; + return *gpu_addr; } -PAddr MemoryManager::MapBufferEx(VAddr vaddr, PAddr paddr, u64 size) { - ASSERT((paddr & PAGE_MASK) == 0); +GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size) { + ASSERT((gpu_addr & PAGE_MASK) == 0); for (u64 offset = 0; offset < size; offset += PAGE_SIZE) { - ASSERT(PageSlot(paddr + offset) == static_cast(PageStatus::Allocated)); - PageSlot(paddr + offset) = vaddr + offset; + ASSERT(PageSlot(gpu_addr + offset) == static_cast(PageStatus::Allocated)); + PageSlot(gpu_addr + offset) = cpu_addr + offset; } - return paddr; + return gpu_addr; } -boost::optional MemoryManager::FindFreeBlock(u64 size, u64 align) { - PAddr paddr = 0; +boost::optional MemoryManager::FindFreeBlock(u64 size, u64 align) { + GPUVAddr gpu_addr = 0; u64 free_space = 0; align = (align + PAGE_MASK) & ~PAGE_MASK; - while (paddr + free_space < MAX_ADDRESS) { - if (!IsPageMapped(paddr + free_space)) { + while (gpu_addr + free_space < MAX_ADDRESS) { + if (!IsPageMapped(gpu_addr + free_space)) { free_space += PAGE_SIZE; if (free_space >= size) { - return paddr; + return gpu_addr; } } else { - paddr += free_space + PAGE_SIZE; + gpu_addr += free_space + PAGE_SIZE; free_space = 0; - paddr = Common::AlignUp(paddr, align); + gpu_addr = Common::AlignUp(gpu_addr, align); } } return {}; } -VAddr MemoryManager::PhysicalToVirtualAddress(PAddr paddr) { - VAddr base_addr = PageSlot(paddr); +VAddr MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) { + VAddr base_addr = PageSlot(gpu_addr); ASSERT(base_addr != static_cast(PageStatus::Unmapped)); - return base_addr + (paddr & PAGE_MASK); + return base_addr + (gpu_addr & PAGE_MASK); } -bool MemoryManager::IsPageMapped(PAddr paddr) { - return PageSlot(paddr) != static_cast(PageStatus::Unmapped); +bool MemoryManager::IsPageMapped(GPUVAddr gpu_addr) { + return PageSlot(gpu_addr) != static_cast(PageStatus::Unmapped); } -VAddr& MemoryManager::PageSlot(PAddr paddr) { - auto& block = page_table[(paddr >> (PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK]; +VAddr& MemoryManager::PageSlot(GPUVAddr gpu_addr) { + auto& block = page_table[(gpu_addr >> (PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK]; if (!block) { block = std::make_unique(); for (unsigned index = 0; index < PAGE_BLOCK_SIZE; index++) { (*block)[index] = static_cast(PageStatus::Unmapped); } } - return (*block)[(paddr >> PAGE_BITS) & PAGE_BLOCK_MASK]; + return (*block)[(gpu_addr >> PAGE_BITS) & PAGE_BLOCK_MASK]; } } // namespace Tegra -- cgit v1.2.3 From 239ac8abe228b9080741ba7d50d9e13cc4a1ceae Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 21 Apr 2018 12:31:30 -0400 Subject: memory_manager: Make GpuToCpuAddress return an optional. --- src/video_core/memory_manager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/video_core/memory_manager.cpp') diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 3f21071c0..9bbbb7e65 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -73,9 +73,14 @@ boost::optional MemoryManager::FindFreeBlock(u64 size, u64 align) { return {}; } -VAddr MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) { +boost::optional MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) { VAddr base_addr = PageSlot(gpu_addr); ASSERT(base_addr != static_cast(PageStatus::Unmapped)); + + if (base_addr == static_cast(PageStatus::Allocated)) { + return {}; + } + return base_addr + (gpu_addr & PAGE_MASK); } -- cgit v1.2.3 From 10c6d891190e407cf4fbcf6eb8ce2506ddf388ec Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 21 Apr 2018 14:40:51 -0400 Subject: memory_manager: Add implement CpuToGpuAddress. --- src/video_core/memory_manager.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/video_core/memory_manager.cpp') diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 9bbbb7e65..25984439d 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -38,6 +38,9 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) { PageSlot(*gpu_addr + offset) = cpu_addr + offset; } + MappedRegion region{cpu_addr, *gpu_addr, size}; + mapped_regions.push_back(region); + return *gpu_addr; } @@ -49,6 +52,9 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size) PageSlot(gpu_addr + offset) = cpu_addr + offset; } + MappedRegion region{cpu_addr, gpu_addr, size}; + mapped_regions.push_back(region); + return gpu_addr; } @@ -84,6 +90,17 @@ boost::optional MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) { return base_addr + (gpu_addr & PAGE_MASK); } +std::vector MemoryManager::CpuToGpuAddress(VAddr cpu_addr) const { + std::vector results; + for (const auto& region : mapped_regions) { + if (cpu_addr >= region.cpu_addr && cpu_addr < (region.cpu_addr + region.size)) { + u64 offset = cpu_addr - region.cpu_addr; + results.push_back(region.gpu_addr + offset); + } + } + return results; +} + bool MemoryManager::IsPageMapped(GPUVAddr gpu_addr) { return PageSlot(gpu_addr) != static_cast(PageStatus::Unmapped); } -- cgit v1.2.3