diff options
Diffstat (limited to 'src/core/memory.cpp')
| -rw-r--r-- | src/core/memory.cpp | 91 |
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 | ||
| 371 | void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size) { | 362 | void 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 | ||
| 370 | void 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 | |||
| 377 | u8 Read8(const VAddr addr) { | 405 | u8 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()); |