diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/memory.cpp | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index b7f21698f..54a848936 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <cstring> | 6 | #include <cstring> |
| 7 | #include <mutex> | ||
| 7 | #include <optional> | 8 | #include <optional> |
| 8 | #include <utility> | 9 | #include <utility> |
| 9 | 10 | ||
| @@ -497,7 +498,21 @@ struct Memory::Impl { | |||
| 497 | return CopyBlock(*system.CurrentProcess(), dest_addr, src_addr, size); | 498 | return CopyBlock(*system.CurrentProcess(), dest_addr, src_addr, size); |
| 498 | } | 499 | } |
| 499 | 500 | ||
| 501 | struct PageEntry { | ||
| 502 | u8* const pointer; | ||
| 503 | const Common::PageType attribute; | ||
| 504 | }; | ||
| 505 | |||
| 506 | PageEntry SafePageEntry(std::size_t base) const { | ||
| 507 | std::lock_guard lock{rasterizer_cache_guard}; | ||
| 508 | return { | ||
| 509 | .pointer = current_page_table->pointers[base], | ||
| 510 | .attribute = current_page_table->attributes[base], | ||
| 511 | }; | ||
| 512 | } | ||
| 513 | |||
| 500 | void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { | 514 | void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { |
| 515 | std::lock_guard lock{rasterizer_cache_guard}; | ||
| 501 | if (vaddr == 0) { | 516 | if (vaddr == 0) { |
| 502 | return; | 517 | return; |
| 503 | } | 518 | } |
| @@ -630,16 +645,22 @@ struct Memory::Impl { | |||
| 630 | */ | 645 | */ |
| 631 | template <typename T> | 646 | template <typename T> |
| 632 | T Read(const VAddr vaddr) { | 647 | T Read(const VAddr vaddr) { |
| 633 | const u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | 648 | // Avoid adding any extra logic to this fast-path block |
| 634 | if (page_pointer != nullptr) { | 649 | if (const u8* const pointer = current_page_table->pointers[vaddr >> PAGE_BITS]) { |
| 635 | // NOTE: Avoid adding any extra logic to this fast-path block | ||
| 636 | T value; | 650 | T value; |
| 637 | std::memcpy(&value, &page_pointer[vaddr], sizeof(T)); | 651 | std::memcpy(&value, &pointer[vaddr], sizeof(T)); |
| 638 | return value; | 652 | return value; |
| 639 | } | 653 | } |
| 640 | 654 | ||
| 641 | const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 655 | // Otherwise, we need to grab the page with a lock, in case it is currently being modified |
| 642 | switch (type) { | 656 | const auto entry = SafePageEntry(vaddr >> PAGE_BITS); |
| 657 | if (entry.pointer) { | ||
| 658 | T value; | ||
| 659 | std::memcpy(&value, &entry.pointer[vaddr], sizeof(T)); | ||
| 660 | return value; | ||
| 661 | } | ||
| 662 | |||
| 663 | switch (entry.attribute) { | ||
| 643 | case Common::PageType::Unmapped: | 664 | case Common::PageType::Unmapped: |
| 644 | LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr); | 665 | LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr); |
| 645 | return 0; | 666 | return 0; |
| @@ -670,15 +691,21 @@ struct Memory::Impl { | |||
| 670 | */ | 691 | */ |
| 671 | template <typename T> | 692 | template <typename T> |
| 672 | void Write(const VAddr vaddr, const T data) { | 693 | void Write(const VAddr vaddr, const T data) { |
| 673 | u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | 694 | // Avoid adding any extra logic to this fast-path block |
| 674 | if (page_pointer != nullptr) { | 695 | if (u8* const pointer = current_page_table->pointers[vaddr >> PAGE_BITS]) { |
| 675 | // NOTE: Avoid adding any extra logic to this fast-path block | 696 | std::memcpy(&pointer[vaddr], &data, sizeof(T)); |
| 676 | std::memcpy(&page_pointer[vaddr], &data, sizeof(T)); | ||
| 677 | return; | 697 | return; |
| 678 | } | 698 | } |
| 679 | 699 | ||
| 680 | const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 700 | // Otherwise, we need to grab the page with a lock, in case it is currently being modified |
| 681 | switch (type) { | 701 | const auto entry = SafePageEntry(vaddr >> PAGE_BITS); |
| 702 | if (entry.pointer) { | ||
| 703 | // Memory was mapped, we are done | ||
| 704 | std::memcpy(&entry.pointer[vaddr], &data, sizeof(T)); | ||
| 705 | return; | ||
| 706 | } | ||
| 707 | |||
| 708 | switch (entry.attribute) { | ||
| 682 | case Common::PageType::Unmapped: | 709 | case Common::PageType::Unmapped: |
| 683 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, | 710 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, |
| 684 | static_cast<u32>(data), vaddr); | 711 | static_cast<u32>(data), vaddr); |
| @@ -756,6 +783,7 @@ struct Memory::Impl { | |||
| 756 | return true; | 783 | return true; |
| 757 | } | 784 | } |
| 758 | 785 | ||
| 786 | mutable std::mutex rasterizer_cache_guard; | ||
| 759 | Common::PageTable* current_page_table = nullptr; | 787 | Common::PageTable* current_page_table = nullptr; |
| 760 | Core::System& system; | 788 | Core::System& system; |
| 761 | }; | 789 | }; |