summaryrefslogtreecommitdiff
path: root/src/core/memory.cpp
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2017-06-21 22:48:00 -0700
committerGravatar Yuri Kunde Schlesner2017-06-21 22:57:12 -0700
commitd5531357487a144cf962ce08a912417fd5e61570 (patch)
tree22a4991545b092b5a46cc448c0359d3bfcaf253e /src/core/memory.cpp
parentMemory: Add TryVirtualToPhysicalAddress, returning a boost::optional (diff)
downloadyuzu-d5531357487a144cf962ce08a912417fd5e61570.tar.gz
yuzu-d5531357487a144cf962ce08a912417fd5e61570.tar.xz
yuzu-d5531357487a144cf962ce08a912417fd5e61570.zip
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.
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r--src/core/memory.cpp91
1 files changed, 52 insertions, 39 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 42ca69e00..38fe9e231 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -83,19 +83,13 @@ static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
83 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, 83 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE,
84 (base + size) * PAGE_SIZE); 84 (base + size) * PAGE_SIZE);
85 85
86 u32 end = base + size; 86 RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE,
87 FlushMode::FlushAndInvalidate);
87 88
89 u32 end = base + size;
88 while (base != end) { 90 while (base != end) {
89 ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %08X", base); 91 ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %08X", base);
90 92
91 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
92 // null here
93 if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory ||
94 current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) {
95 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS),
96 PAGE_SIZE);
97 }
98
99 current_page_table->attributes[base] = type; 93 current_page_table->attributes[base] = type;
100 current_page_table->pointers[base] = memory; 94 current_page_table->pointers[base] = memory;
101 current_page_table->cached_res_count[base] = 0; 95 current_page_table->cached_res_count[base] = 0;
@@ -189,7 +183,7 @@ T Read(const VAddr vaddr) {
189 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 183 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
190 break; 184 break;
191 case PageType::RasterizerCachedMemory: { 185 case PageType::RasterizerCachedMemory: {
192 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 186 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
193 187
194 T value; 188 T value;
195 std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T)); 189 std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T));
@@ -198,8 +192,7 @@ T Read(const VAddr vaddr) {
198 case PageType::Special: 192 case PageType::Special:
199 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 193 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
200 case PageType::RasterizerCachedSpecial: { 194 case PageType::RasterizerCachedSpecial: {
201 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 195 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
202
203 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 196 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
204 } 197 }
205 default: 198 default:
@@ -229,8 +222,7 @@ void Write(const VAddr vaddr, const T data) {
229 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 222 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
230 break; 223 break;
231 case PageType::RasterizerCachedMemory: { 224 case PageType::RasterizerCachedMemory: {
232 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 225 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
233
234 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); 226 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T));
235 break; 227 break;
236 } 228 }
@@ -238,8 +230,7 @@ void Write(const VAddr vaddr, const T data) {
238 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 230 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
239 break; 231 break;
240 case PageType::RasterizerCachedSpecial: { 232 case PageType::RasterizerCachedSpecial: {
241 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 233 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
242
243 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 234 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
244 break; 235 break;
245 } 236 }
@@ -369,11 +360,48 @@ void RasterizerFlushRegion(PAddr start, u32 size) {
369} 360}
370 361
371void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) { 362void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) {
363 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
364 // null here
372 if (VideoCore::g_renderer != nullptr) { 365 if (VideoCore::g_renderer != nullptr) {
373 VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(start, size); 366 VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(start, size);
374 } 367 }
375} 368}
376 369
370void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
371 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
372 // null here
373 if (VideoCore::g_renderer != nullptr) {
374 VAddr end = start + size;
375
376 auto CheckRegion = [&](VAddr region_start, VAddr region_end) {
377 if (start >= region_end || end <= region_start) {
378 // No overlap with region
379 return;
380 }
381
382 VAddr overlap_start = std::max(start, region_start);
383 VAddr overlap_end = std::min(end, region_end);
384
385 PAddr physical_start = TryVirtualToPhysicalAddress(overlap_start).value();
386 u32 overlap_size = overlap_end - overlap_start;
387
388 auto* rasterizer = VideoCore::g_renderer->Rasterizer();
389 switch (mode) {
390 case FlushMode::Flush:
391 rasterizer->FlushRegion(physical_start, overlap_size);
392 break;
393 case FlushMode::FlushAndInvalidate:
394 rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size);
395 break;
396 }
397 };
398
399 CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END);
400 CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END);
401 CheckRegion(VRAM_VADDR, VRAM_VADDR_END);
402 }
403}
404
377u8 Read8(const VAddr addr) { 405u8 Read8(const VAddr addr) {
378 return Read<u8>(addr); 406 return Read<u8>(addr);
379} 407}
@@ -420,16 +448,13 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
420 break; 448 break;
421 } 449 }
422 case PageType::RasterizerCachedMemory: { 450 case PageType::RasterizerCachedMemory: {
423 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 451 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
424
425 std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); 452 std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount);
426 break; 453 break;
427 } 454 }
428 case PageType::RasterizerCachedSpecial: { 455 case PageType::RasterizerCachedSpecial: {
429 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 456 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
430 457 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
431 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
432
433 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); 458 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount);
434 break; 459 break;
435 } 460 }
@@ -490,18 +515,13 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
490 break; 515 break;
491 } 516 }
492 case PageType::RasterizerCachedMemory: { 517 case PageType::RasterizerCachedMemory: {
493 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), 518 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
494 copy_amount);
495
496 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); 519 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
497 break; 520 break;
498 } 521 }
499 case PageType::RasterizerCachedSpecial: { 522 case PageType::RasterizerCachedSpecial: {
500 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 523 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
501 524 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
502 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
503 copy_amount);
504
505 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); 525 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
506 break; 526 break;
507 } 527 }
@@ -547,18 +567,13 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
547 break; 567 break;
548 } 568 }
549 case PageType::RasterizerCachedMemory: { 569 case PageType::RasterizerCachedMemory: {
550 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), 570 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
551 copy_amount);
552
553 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); 571 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
554 break; 572 break;
555 } 573 }
556 case PageType::RasterizerCachedSpecial: { 574 case PageType::RasterizerCachedSpecial: {
557 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 575 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
558 576 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
559 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
560 copy_amount);
561
562 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); 577 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
563 break; 578 break;
564 } 579 }
@@ -603,15 +618,13 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
603 break; 618 break;
604 } 619 }
605 case PageType::RasterizerCachedMemory: { 620 case PageType::RasterizerCachedMemory: {
606 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 621 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
607
608 WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount); 622 WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount);
609 break; 623 break;
610 } 624 }
611 case PageType::RasterizerCachedSpecial: { 625 case PageType::RasterizerCachedSpecial: {
612 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 626 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
613 627 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
614 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
615 628
616 std::vector<u8> buffer(copy_amount); 629 std::vector<u8> buffer(copy_amount);
617 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); 630 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size());