summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Weiyi Wang2017-07-22 10:15:52 +0300
committerGravatar GitHub2017-07-22 10:15:52 +0300
commit045d0b5bbdf790952ddfedcfc8816c0afc7a2300 (patch)
treefba1a440adf7d7ecd59edaf48e215e70b7c6cf9e /src
parentMerge pull request #2833 from j-selby/single-header-json (diff)
parentMemory: Add function to flush a virtual range from the rasterizer cache (diff)
downloadyuzu-045d0b5bbdf790952ddfedcfc8816c0afc7a2300.tar.gz
yuzu-045d0b5bbdf790952ddfedcfc8816c0afc7a2300.tar.xz
yuzu-045d0b5bbdf790952ddfedcfc8816c0afc7a2300.zip
Merge pull request #2799 from yuriks/virtual-cached-range-flush
Add address conversion functions returning optional, Add function to flush virtual region from rasterizer cache
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/shared_memory.cpp2
-rw-r--r--src/core/hle/service/apt/apt.cpp2
-rw-r--r--src/core/hle/service/gsp_gpu.cpp11
-rw-r--r--src/core/hle/service/y2r_u.cpp4
-rw-r--r--src/core/memory.cpp128
-rw-r--r--src/core/memory.h34
6 files changed, 113 insertions, 68 deletions
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 922e5ab58..a7b66142f 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -149,7 +149,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
149 149
150 if (base_address == 0 && target_address == 0) { 150 if (base_address == 0 && target_address == 0) {
151 // Calculate the address at which to map the memory block. 151 // Calculate the address at which to map the memory block.
152 target_address = Memory::PhysicalToVirtualAddress(linear_heap_phys_address); 152 target_address = Memory::PhysicalToVirtualAddress(linear_heap_phys_address).value();
153 } 153 }
154 154
155 // Map the memory block into the target process 155 // Map the memory block into the target process
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index df4b5cc3f..5c44b43bb 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -85,7 +85,7 @@ void GetSharedFont(Service::Interface* self) {
85 // The shared font has to be relocated to the new address before being passed to the 85 // The shared font has to be relocated to the new address before being passed to the
86 // application. 86 // application.
87 VAddr target_address = 87 VAddr target_address =
88 Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address); 88 Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address).value();
89 if (!shared_font_relocated) { 89 if (!shared_font_relocated) {
90 BCFNT::RelocateSharedFont(shared_font_mem, target_address); 90 BCFNT::RelocateSharedFont(shared_font_mem, target_address);
91 shared_font_relocated = true; 91 shared_font_relocated = true;
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index bc964ec60..88684b82d 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -475,12 +475,11 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
475 475
476 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever 476 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever
477 // possible/likely 477 // possible/likely
478 Memory::RasterizerFlushRegion( 478 Memory::RasterizerFlushVirtualRegion(command.dma_request.source_address,
479 Memory::VirtualToPhysicalAddress(command.dma_request.source_address), 479 command.dma_request.size, Memory::FlushMode::Flush);
480 command.dma_request.size); 480 Memory::RasterizerFlushVirtualRegion(command.dma_request.dest_address,
481 Memory::RasterizerFlushAndInvalidateRegion( 481 command.dma_request.size,
482 Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), 482 Memory::FlushMode::FlushAndInvalidate);
483 command.dma_request.size);
484 483
485 // TODO(Subv): These memory accesses should not go through the application's memory mapping. 484 // TODO(Subv): These memory accesses should not go through the application's memory mapping.
486 // They should go through the GSP module's memory mapping. 485 // They should go through the GSP module's memory mapping.
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index e73971d5f..57172ddd6 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -587,8 +587,8 @@ static void StartConversion(Interface* self) {
587 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( 587 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
588 u32 total_output_size = 588 u32 total_output_size =
589 conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); 589 conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap);
590 Memory::RasterizerFlushAndInvalidateRegion( 590 Memory::RasterizerFlushVirtualRegion(conversion.dst.address, total_output_size,
591 Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size); 591 Memory::FlushMode::FlushAndInvalidate);
592 592
593 HW::Y2R::PerformConversion(conversion); 593 HW::Y2R::PerformConversion(conversion);
594 594
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 9024f4922..65649d9d7 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;
@@ -196,7 +190,7 @@ T Read(const VAddr vaddr) {
196 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 190 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
197 break; 191 break;
198 case PageType::RasterizerCachedMemory: { 192 case PageType::RasterizerCachedMemory: {
199 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 193 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
200 194
201 T value; 195 T value;
202 std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T)); 196 std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T));
@@ -205,8 +199,7 @@ T Read(const VAddr vaddr) {
205 case PageType::Special: 199 case PageType::Special:
206 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 200 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
207 case PageType::RasterizerCachedSpecial: { 201 case PageType::RasterizerCachedSpecial: {
208 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 202 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
209
210 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 203 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
211 } 204 }
212 default: 205 default:
@@ -236,8 +229,7 @@ void Write(const VAddr vaddr, const T data) {
236 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 229 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
237 break; 230 break;
238 case PageType::RasterizerCachedMemory: { 231 case PageType::RasterizerCachedMemory: {
239 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 232 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
240
241 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); 233 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T));
242 break; 234 break;
243 } 235 }
@@ -245,8 +237,7 @@ void Write(const VAddr vaddr, const T data) {
245 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 237 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
246 break; 238 break;
247 case PageType::RasterizerCachedSpecial: { 239 case PageType::RasterizerCachedSpecial: {
248 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 240 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::FlushAndInvalidate);
249
250 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 241 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
251 break; 242 break;
252 } 243 }
@@ -275,7 +266,8 @@ bool IsValidVirtualAddress(const VAddr vaddr) {
275} 266}
276 267
277bool IsValidPhysicalAddress(const PAddr paddr) { 268bool IsValidPhysicalAddress(const PAddr paddr) {
278 return IsValidVirtualAddress(PhysicalToVirtualAddress(paddr)); 269 boost::optional<VAddr> vaddr = PhysicalToVirtualAddress(paddr);
270 return vaddr && IsValidVirtualAddress(*vaddr);
279} 271}
280 272
281u8* GetPointer(const VAddr vaddr) { 273u8* GetPointer(const VAddr vaddr) {
@@ -308,7 +300,8 @@ std::string ReadCString(VAddr vaddr, std::size_t max_length) {
308 300
309u8* GetPhysicalPointer(PAddr address) { 301u8* GetPhysicalPointer(PAddr address) {
310 // TODO(Subv): This call should not go through the application's memory mapping. 302 // TODO(Subv): This call should not go through the application's memory mapping.
311 return GetPointer(PhysicalToVirtualAddress(address)); 303 boost::optional<VAddr> vaddr = PhysicalToVirtualAddress(address);
304 return vaddr ? GetPointer(*vaddr) : nullptr;
312} 305}
313 306
314void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) { 307void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
@@ -319,8 +312,12 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
319 u32 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1; 312 u32 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1;
320 PAddr paddr = start; 313 PAddr paddr = start;
321 314
322 for (unsigned i = 0; i < num_pages; ++i) { 315 for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) {
323 VAddr vaddr = PhysicalToVirtualAddress(paddr); 316 boost::optional<VAddr> maybe_vaddr = PhysicalToVirtualAddress(paddr);
317 if (!maybe_vaddr)
318 continue;
319 VAddr vaddr = *maybe_vaddr;
320
324 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; 321 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS];
325 ASSERT_MSG(count_delta <= UINT8_MAX - res_count, 322 ASSERT_MSG(count_delta <= UINT8_MAX - res_count,
326 "Rasterizer resource cache counter overflow!"); 323 "Rasterizer resource cache counter overflow!");
@@ -368,7 +365,6 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
368 UNREACHABLE(); 365 UNREACHABLE();
369 } 366 }
370 } 367 }
371 paddr += PAGE_SIZE;
372 } 368 }
373} 369}
374 370
@@ -379,11 +375,48 @@ void RasterizerFlushRegion(PAddr start, u32 size) {
379} 375}
380 376
381void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) { 377void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) {
378 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
379 // null here
382 if (VideoCore::g_renderer != nullptr) { 380 if (VideoCore::g_renderer != nullptr) {
383 VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(start, size); 381 VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(start, size);
384 } 382 }
385} 383}
386 384
385void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) {
386 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
387 // null here
388 if (VideoCore::g_renderer != nullptr) {
389 VAddr end = start + size;
390
391 auto CheckRegion = [&](VAddr region_start, VAddr region_end) {
392 if (start >= region_end || end <= region_start) {
393 // No overlap with region
394 return;
395 }
396
397 VAddr overlap_start = std::max(start, region_start);
398 VAddr overlap_end = std::min(end, region_end);
399
400 PAddr physical_start = TryVirtualToPhysicalAddress(overlap_start).value();
401 u32 overlap_size = overlap_end - overlap_start;
402
403 auto* rasterizer = VideoCore::g_renderer->Rasterizer();
404 switch (mode) {
405 case FlushMode::Flush:
406 rasterizer->FlushRegion(physical_start, overlap_size);
407 break;
408 case FlushMode::FlushAndInvalidate:
409 rasterizer->FlushAndInvalidateRegion(physical_start, overlap_size);
410 break;
411 }
412 };
413
414 CheckRegion(LINEAR_HEAP_VADDR, LINEAR_HEAP_VADDR_END);
415 CheckRegion(NEW_LINEAR_HEAP_VADDR, NEW_LINEAR_HEAP_VADDR_END);
416 CheckRegion(VRAM_VADDR, VRAM_VADDR_END);
417 }
418}
419
387u8 Read8(const VAddr addr) { 420u8 Read8(const VAddr addr) {
388 return Read<u8>(addr); 421 return Read<u8>(addr);
389} 422}
@@ -430,16 +463,13 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
430 break; 463 break;
431 } 464 }
432 case PageType::RasterizerCachedMemory: { 465 case PageType::RasterizerCachedMemory: {
433 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 466 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
434
435 std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); 467 std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount);
436 break; 468 break;
437 } 469 }
438 case PageType::RasterizerCachedSpecial: { 470 case PageType::RasterizerCachedSpecial: {
439 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 471 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
440 472 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
441 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
442
443 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); 473 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount);
444 break; 474 break;
445 } 475 }
@@ -500,18 +530,13 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
500 break; 530 break;
501 } 531 }
502 case PageType::RasterizerCachedMemory: { 532 case PageType::RasterizerCachedMemory: {
503 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), 533 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
504 copy_amount);
505
506 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); 534 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
507 break; 535 break;
508 } 536 }
509 case PageType::RasterizerCachedSpecial: { 537 case PageType::RasterizerCachedSpecial: {
510 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 538 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
511 539 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
512 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
513 copy_amount);
514
515 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); 540 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
516 break; 541 break;
517 } 542 }
@@ -557,18 +582,13 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
557 break; 582 break;
558 } 583 }
559 case PageType::RasterizerCachedMemory: { 584 case PageType::RasterizerCachedMemory: {
560 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), 585 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
561 copy_amount);
562
563 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); 586 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
564 break; 587 break;
565 } 588 }
566 case PageType::RasterizerCachedSpecial: { 589 case PageType::RasterizerCachedSpecial: {
567 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 590 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
568 591 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate);
569 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
570 copy_amount);
571
572 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); 592 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
573 break; 593 break;
574 } 594 }
@@ -613,15 +633,13 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
613 break; 633 break;
614 } 634 }
615 case PageType::RasterizerCachedMemory: { 635 case PageType::RasterizerCachedMemory: {
616 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 636 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
617
618 WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount); 637 WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount);
619 break; 638 break;
620 } 639 }
621 case PageType::RasterizerCachedSpecial: { 640 case PageType::RasterizerCachedSpecial: {
622 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 641 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
623 642 RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush);
624 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
625 643
626 std::vector<u8> buffer(copy_amount); 644 std::vector<u8> buffer(copy_amount);
627 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); 645 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size());
@@ -680,7 +698,7 @@ void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data)
680 mmio_handler->Write64(addr, data); 698 mmio_handler->Write64(addr, data);
681} 699}
682 700
683PAddr VirtualToPhysicalAddress(const VAddr addr) { 701boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
684 if (addr == 0) { 702 if (addr == 0) {
685 return 0; 703 return 0;
686 } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { 704 } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
@@ -697,12 +715,20 @@ PAddr VirtualToPhysicalAddress(const VAddr addr) {
697 return addr - N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_PADDR; 715 return addr - N3DS_EXTRA_RAM_VADDR + N3DS_EXTRA_RAM_PADDR;
698 } 716 }
699 717
700 LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr); 718 return boost::none;
701 // To help with debugging, set bit on address so that it's obviously invalid. 719}
702 return addr | 0x80000000; 720
721PAddr VirtualToPhysicalAddress(const VAddr addr) {
722 auto paddr = TryVirtualToPhysicalAddress(addr);
723 if (!paddr) {
724 LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08X", addr);
725 // To help with debugging, set bit on address so that it's obviously invalid.
726 return addr | 0x80000000;
727 }
728 return *paddr;
703} 729}
704 730
705VAddr PhysicalToVirtualAddress(const PAddr addr) { 731boost::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) {
706 if (addr == 0) { 732 if (addr == 0) {
707 return 0; 733 return 0;
708 } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { 734 } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
@@ -717,9 +743,7 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) {
717 return addr - N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_VADDR; 743 return addr - N3DS_EXTRA_RAM_PADDR + N3DS_EXTRA_RAM_VADDR;
718 } 744 }
719 745
720 LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08X", addr); 746 return boost::none;
721 // To help with debugging, set bit on address so that it's obviously invalid.
722 return addr | 0x80000000;
723} 747}
724 748
725} // namespace 749} // namespace
diff --git a/src/core/memory.h b/src/core/memory.h
index 71fb278ad..c8c56babd 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -7,6 +7,7 @@
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <string> 9#include <string>
10#include <boost/optional.hpp>
10#include "common/common_types.h" 11#include "common/common_types.h"
11 12
12namespace Memory { 13namespace Memory {
@@ -148,15 +149,23 @@ u8* GetPointer(VAddr virtual_address);
148std::string ReadCString(VAddr virtual_address, std::size_t max_length); 149std::string ReadCString(VAddr virtual_address, std::size_t max_length);
149 150
150/** 151/**
151* Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical 152 * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical
152* address. This should be used by services to translate addresses for use by the hardware. 153 * address. This should be used by services to translate addresses for use by the hardware.
153*/ 154 */
155boost::optional<PAddr> TryVirtualToPhysicalAddress(VAddr addr);
156
157/**
158 * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical
159 * address. This should be used by services to translate addresses for use by the hardware.
160 *
161 * @deprecated Use TryVirtualToPhysicalAddress(), which reports failure.
162 */
154PAddr VirtualToPhysicalAddress(VAddr addr); 163PAddr VirtualToPhysicalAddress(VAddr addr);
155 164
156/** 165/**
157* Undoes a mapping performed by VirtualToPhysicalAddress(). 166 * Undoes a mapping performed by VirtualToPhysicalAddress().
158*/ 167 */
159VAddr PhysicalToVirtualAddress(PAddr addr); 168boost::optional<VAddr> PhysicalToVirtualAddress(PAddr addr);
160 169
161/** 170/**
162 * Gets a pointer to the memory region beginning at the specified physical address. 171 * Gets a pointer to the memory region beginning at the specified physical address.
@@ -181,6 +190,19 @@ void RasterizerFlushRegion(PAddr start, u32 size);
181 */ 190 */
182void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size); 191void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size);
183 192
193enum class FlushMode {
194 /// Write back modified surfaces to RAM
195 Flush,
196 /// Write back modified surfaces to RAM, and also remove them from the cache
197 FlushAndInvalidate,
198};
199
200/**
201 * Flushes and invalidates any externally cached rasterizer resources touching the given virtual
202 * address region.
203 */
204void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode);
205
184/** 206/**
185 * Dynarmic has an optimization to memory accesses when the pointer to the page exists that 207 * Dynarmic has an optimization to memory accesses when the pointer to the page exists that
186 * can be used by setting up the current page table as a callback. This function is used to 208 * can be used by setting up the current page table as a callback. This function is used to