Memory: Add function to flush a virtual range from the rasterizer cache

This is slightly more ergonomic to use, correctly handles virtual
regions which are disjoint in physical addressing space, and checks only
regions which can be cached by the rasterizer.
This commit is contained in:
Yuri Kunde Schlesner 2017-06-21 22:48:00 -07:00
parent 75be7907c1
commit 1423b3b10e
4 changed files with 72 additions and 47 deletions

View file

@ -83,19 +83,13 @@ static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE,
(base + size) * PAGE_SIZE);
u32 end = base + size;
RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE,
FlushMode::FlushAndInvalidate);
u32 end = base + size;
while (base != end) {
ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %08X", base);
// Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
// null here
if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory ||
current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) {
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS),
PAGE_SIZE);
}
current_page_table->attributes[base] = type;
current_page_table->pointers[base] = memory;
current_page_table->cached_res_count[base] = 0;
@ -189,7 +183,7 @@ T Read(const VAddr vaddr) {
ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
break;
case PageType::RasterizerCachedMemory: {
RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
T value;
std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T));
@ -198,8 +192,7 @@ T Read(const VAddr vaddr) {
case PageType::Special:
return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
case PageType::RasterizerCachedSpecial: {
RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
}
default:
@ -229,8 +222,7 @@ void Write(const VAddr vaddr, const T data) {
ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
break;
case PageType::RasterizerCachedMemory: {
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T));
break;
}
@ -238,8 +230,7 @@ void Write(const VAddr vaddr, const T data) {
WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
break;
case PageType::RasterizerCachedSpecial: {
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
break;
}
@ -369,11 +360,48 @@ void RasterizerFlushRegion(PAddr start, u32 size) {
}
void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) {
// Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
// null here
if (VideoCore::g_renderer != nullptr) {
VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(start, size);
}
}
void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
// Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
// null here
if (VideoCore::g_renderer != nullptr) {
VAddr end = start + size;
auto CheckRegion = [&](VAddr region_start, VAddr region_end) {
if (start >= region_end || end <= region_start) {
// No overlap with region
return;
}
VAddr overlap_start = std::max(start, region_start);
VAddr overlap_end = std::min(end, region_end);
PAddr physical_start = TryVirtualToPhysicalAddress(overlap_start).value();
u32 overlap_size = overlap_end - overlap_start;
auto* rasterizer = VideoCore::g_renderer->Rasterizer();
switch (mode) {
case FlushMode::Flush:
rasterizer->FlushRegion(physical_start, overlap_size);
break;
case FlushMode::FlushAndInvalidate:
rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size);
break;
}
};
CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END);
CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END);
CheckRegion(VRAM_VADDR, VRAM_VADDR_END);
}
}
u8 Read8(const VAddr addr) {
return Read<u8>(addr);
}
@ -420,16 +448,13 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
break;
}
case PageType::RasterizerCachedMemory: {
RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount);
break;
}
case PageType::RasterizerCachedSpecial: {
DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount);
break;
}
@ -490,18 +515,13 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
break;
}
case PageType::RasterizerCachedMemory: {
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
copy_amount);
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
break;
}
case PageType::RasterizerCachedSpecial: {
DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
copy_amount);
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
break;
}
@ -547,18 +567,13 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
break;
}
case PageType::RasterizerCachedMemory: {
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
copy_amount);
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
break;
}
case PageType::RasterizerCachedSpecial: {
DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
copy_amount);
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
break;
}
@ -603,15 +618,13 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
break;
}
case PageType::RasterizerCachedMemory: {
RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount);
break;
}
case PageType::RasterizerCachedSpecial: {
DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
std::vector<u8> buffer(copy_amount);
GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size());