summaryrefslogtreecommitdiff
path: root/src/core/memory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r--src/core/memory.cpp84
1 files changed, 49 insertions, 35 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 9aa8c4e5a..4de510fe5 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -25,11 +25,13 @@ enum class PageType {
25 Unmapped, 25 Unmapped,
26 /// Page is mapped to regular memory. This is the only type you can get pointers to. 26 /// Page is mapped to regular memory. This is the only type you can get pointers to.
27 Memory, 27 Memory,
28 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and invalidation 28 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and
29 /// invalidation
29 RasterizerCachedMemory, 30 RasterizerCachedMemory,
30 /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. 31 /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions.
31 Special, 32 Special,
32 /// Page is mapped to a I/O region, but also needs to check for rasterizer cache flushing and invalidation 33 /// Page is mapped to a I/O region, but also needs to check for rasterizer cache flushing and
34 /// invalidation
33 RasterizerCachedSpecial, 35 RasterizerCachedSpecial,
34}; 36};
35 37
@@ -55,7 +57,8 @@ struct PageTable {
55 std::array<u8*, NUM_ENTRIES> pointers; 57 std::array<u8*, NUM_ENTRIES> pointers;
56 58
57 /** 59 /**
58 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of type `Special`. 60 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of
61 * type `Special`.
59 */ 62 */
60 std::vector<SpecialRegion> special_regions; 63 std::vector<SpecialRegion> special_regions;
61 64
@@ -78,17 +81,20 @@ static PageTable main_page_table;
78static PageTable* current_page_table = &main_page_table; 81static PageTable* current_page_table = &main_page_table;
79 82
80static void MapPages(u32 base, u32 size, u8* memory, PageType type) { 83static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
81 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE); 84 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE,
85 (base + size) * PAGE_SIZE);
82 86
83 u32 end = base + size; 87 u32 end = base + size;
84 88
85 while (base != end) { 89 while (base != end) {
86 ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); 90 ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base);
87 91
88 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be null here 92 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
93 // null here
89 if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory || 94 if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory ||
90 current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) { 95 current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) {
91 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS), PAGE_SIZE); 96 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS),
97 PAGE_SIZE);
92 } 98 }
93 99
94 current_page_table->attributes[base] = type; 100 current_page_table->attributes[base] = type;
@@ -162,7 +168,7 @@ static MMIORegionPointer GetMMIOHandler(VAddr vaddr) {
162 return nullptr; // Should never happen 168 return nullptr; // Should never happen
163} 169}
164 170
165template<typename T> 171template <typename T>
166T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); 172T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr);
167 173
168template <typename T> 174template <typename T>
@@ -183,8 +189,7 @@ T Read(const VAddr vaddr) {
183 case PageType::Memory: 189 case PageType::Memory:
184 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 190 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
185 break; 191 break;
186 case PageType::RasterizerCachedMemory: 192 case PageType::RasterizerCachedMemory: {
187 {
188 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 193 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
189 194
190 T value; 195 T value;
@@ -193,8 +198,7 @@ T Read(const VAddr vaddr) {
193 } 198 }
194 case PageType::Special: 199 case PageType::Special:
195 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 200 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
196 case PageType::RasterizerCachedSpecial: 201 case PageType::RasterizerCachedSpecial: {
197 {
198 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 202 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
199 203
200 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 204 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
@@ -204,7 +208,7 @@ T Read(const VAddr vaddr) {
204 } 208 }
205} 209}
206 210
207template<typename T> 211template <typename T>
208void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); 212void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data);
209 213
210template <typename T> 214template <typename T>
@@ -219,13 +223,13 @@ void Write(const VAddr vaddr, const T data) {
219 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 223 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
220 switch (type) { 224 switch (type) {
221 case PageType::Unmapped: 225 case PageType::Unmapped:
222 LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32) data, vaddr); 226 LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data,
227 vaddr);
223 return; 228 return;
224 case PageType::Memory: 229 case PageType::Memory:
225 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 230 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
226 break; 231 break;
227 case PageType::RasterizerCachedMemory: 232 case PageType::RasterizerCachedMemory: {
228 {
229 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 233 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
230 234
231 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); 235 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T));
@@ -234,8 +238,7 @@ void Write(const VAddr vaddr, const T data) {
234 case PageType::Special: 238 case PageType::Special:
235 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 239 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
236 break; 240 break;
237 case PageType::RasterizerCachedSpecial: 241 case PageType::RasterizerCachedSpecial: {
238 {
239 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 242 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
240 243
241 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 244 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
@@ -310,7 +313,8 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
310 for (unsigned i = 0; i < num_pages; ++i) { 313 for (unsigned i = 0; i < num_pages; ++i) {
311 VAddr vaddr = PhysicalToVirtualAddress(paddr); 314 VAddr vaddr = PhysicalToVirtualAddress(paddr);
312 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; 315 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS];
313 ASSERT_MSG(count_delta <= UINT8_MAX - res_count, "Rasterizer resource cache counter overflow!"); 316 ASSERT_MSG(count_delta <= UINT8_MAX - res_count,
317 "Rasterizer resource cache counter overflow!");
314 ASSERT_MSG(count_delta >= -res_count, "Rasterizer resource cache counter underflow!"); 318 ASSERT_MSG(count_delta >= -res_count, "Rasterizer resource cache counter underflow!");
315 319
316 // Switch page type to cached if now cached 320 // Switch page type to cached if now cached
@@ -337,7 +341,8 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
337 switch (page_type) { 341 switch (page_type) {
338 case PageType::RasterizerCachedMemory: 342 case PageType::RasterizerCachedMemory:
339 page_type = PageType::Memory; 343 page_type = PageType::Memory;
340 current_page_table->pointers[vaddr >> PAGE_BITS] = GetPointerFromVMA(vaddr & ~PAGE_MASK); 344 current_page_table->pointers[vaddr >> PAGE_BITS] =
345 GetPointerFromVMA(vaddr & ~PAGE_MASK);
341 break; 346 break;
342 case PageType::RasterizerCachedSpecial: 347 case PageType::RasterizerCachedSpecial:
343 page_type = PageType::Special; 348 page_type = PageType::Special;
@@ -389,7 +394,8 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
389 394
390 switch (current_page_table->attributes[page_index]) { 395 switch (current_page_table->attributes[page_index]) {
391 case PageType::Unmapped: { 396 case PageType::Unmapped: {
392 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); 397 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
398 current_vaddr, src_addr, size);
393 std::memset(dest_buffer, 0, copy_amount); 399 std::memset(dest_buffer, 0, copy_amount);
394 break; 400 break;
395 } 401 }
@@ -458,7 +464,9 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
458 464
459 switch (current_page_table->attributes[page_index]) { 465 switch (current_page_table->attributes[page_index]) {
460 case PageType::Unmapped: { 466 case PageType::Unmapped: {
461 LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); 467 LOG_ERROR(HW_Memory,
468 "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
469 current_vaddr, dest_addr, size);
462 break; 470 break;
463 } 471 }
464 case PageType::Memory: { 472 case PageType::Memory: {
@@ -475,7 +483,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
475 break; 483 break;
476 } 484 }
477 case PageType::RasterizerCachedMemory: { 485 case PageType::RasterizerCachedMemory: {
478 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 486 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
487 copy_amount);
479 488
480 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); 489 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
481 break; 490 break;
@@ -483,7 +492,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
483 case PageType::RasterizerCachedSpecial: { 492 case PageType::RasterizerCachedSpecial: {
484 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 493 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
485 494
486 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 495 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
496 copy_amount);
487 497
488 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); 498 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
489 break; 499 break;
@@ -512,7 +522,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
512 522
513 switch (current_page_table->attributes[page_index]) { 523 switch (current_page_table->attributes[page_index]) {
514 case PageType::Unmapped: { 524 case PageType::Unmapped: {
515 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); 525 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
526 current_vaddr, dest_addr, size);
516 break; 527 break;
517 } 528 }
518 case PageType::Memory: { 529 case PageType::Memory: {
@@ -529,7 +540,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
529 break; 540 break;
530 } 541 }
531 case PageType::RasterizerCachedMemory: { 542 case PageType::RasterizerCachedMemory: {
532 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 543 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
544 copy_amount);
533 545
534 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); 546 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
535 break; 547 break;
@@ -537,7 +549,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
537 case PageType::RasterizerCachedSpecial: { 549 case PageType::RasterizerCachedSpecial: {
538 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 550 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
539 551
540 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 552 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
553 copy_amount);
541 554
542 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); 555 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
543 break; 556 break;
@@ -563,7 +576,8 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
563 576
564 switch (current_page_table->attributes[page_index]) { 577 switch (current_page_table->attributes[page_index]) {
565 case PageType::Unmapped: { 578 case PageType::Unmapped: {
566 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); 579 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
580 current_vaddr, src_addr, size);
567 ZeroBlock(dest_addr, copy_amount); 581 ZeroBlock(dest_addr, copy_amount);
568 break; 582 break;
569 } 583 }
@@ -609,42 +623,42 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
609 } 623 }
610} 624}
611 625
612template<> 626template <>
613u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) { 627u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) {
614 return mmio_handler->Read8(addr); 628 return mmio_handler->Read8(addr);
615} 629}
616 630
617template<> 631template <>
618u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) { 632u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) {
619 return mmio_handler->Read16(addr); 633 return mmio_handler->Read16(addr);
620} 634}
621 635
622template<> 636template <>
623u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) { 637u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) {
624 return mmio_handler->Read32(addr); 638 return mmio_handler->Read32(addr);
625} 639}
626 640
627template<> 641template <>
628u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) { 642u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) {
629 return mmio_handler->Read64(addr); 643 return mmio_handler->Read64(addr);
630} 644}
631 645
632template<> 646template <>
633void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) { 647void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) {
634 mmio_handler->Write8(addr, data); 648 mmio_handler->Write8(addr, data);
635} 649}
636 650
637template<> 651template <>
638void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) { 652void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) {
639 mmio_handler->Write16(addr, data); 653 mmio_handler->Write16(addr, data);
640} 654}
641 655
642template<> 656template <>
643void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) { 657void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) {
644 mmio_handler->Write32(addr, data); 658 mmio_handler->Write32(addr, data);
645} 659}
646 660
647template<> 661template <>
648void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) { 662void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) {
649 mmio_handler->Write64(addr, data); 663 mmio_handler->Write64(addr, data);
650} 664}