diff options
| author | 2020-07-04 00:59:40 -0400 | |
|---|---|---|
| committer | 2020-07-04 00:59:40 -0400 | |
| commit | f829932ed191ad469df01342191bf2725e8a20bb (patch) | |
| tree | 0ae185ce3ef43ef9b085aae7b9ad5abb04e3d239 /src/core/memory.cpp | |
| parent | Fix for always firing triggers on some controllers, trigger threshold more un... (diff) | |
| parent | Merge pull request #4218 from ogniK5377/opus-external (diff) | |
| download | yuzu-f829932ed191ad469df01342191bf2725e8a20bb.tar.gz yuzu-f829932ed191ad469df01342191bf2725e8a20bb.tar.xz yuzu-f829932ed191ad469df01342191bf2725e8a20bb.zip | |
Fix merge conflicts?
Diffstat (limited to 'src/core/memory.cpp')
| -rw-r--r-- | src/core/memory.cpp | 109 |
1 files changed, 102 insertions, 7 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 9d87045a0..7def00768 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <utility> | 8 | #include <utility> |
| 9 | 9 | ||
| 10 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 11 | #include "common/atomic_ops.h" | ||
| 11 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 12 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 13 | #include "common/page_table.h" | 14 | #include "common/page_table.h" |
| @@ -29,15 +30,12 @@ namespace Core::Memory { | |||
| 29 | struct Memory::Impl { | 30 | struct Memory::Impl { |
| 30 | explicit Impl(Core::System& system_) : system{system_} {} | 31 | explicit Impl(Core::System& system_) : system{system_} {} |
| 31 | 32 | ||
| 32 | void SetCurrentPageTable(Kernel::Process& process) { | 33 | void SetCurrentPageTable(Kernel::Process& process, u32 core_id) { |
| 33 | current_page_table = &process.PageTable().PageTableImpl(); | 34 | current_page_table = &process.PageTable().PageTableImpl(); |
| 34 | 35 | ||
| 35 | const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth(); | 36 | const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth(); |
| 36 | 37 | ||
| 37 | system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width); | 38 | system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width); |
| 38 | system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width); | ||
| 39 | system.ArmInterface(2).PageTableChanged(*current_page_table, address_space_width); | ||
| 40 | system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width); | ||
| 41 | } | 39 | } |
| 42 | 40 | ||
| 43 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { | 41 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { |
| @@ -179,6 +177,22 @@ struct Memory::Impl { | |||
| 179 | } | 177 | } |
| 180 | } | 178 | } |
| 181 | 179 | ||
| 180 | bool WriteExclusive8(const VAddr addr, const u8 data, const u8 expected) { | ||
| 181 | return WriteExclusive<u8>(addr, data, expected); | ||
| 182 | } | ||
| 183 | |||
| 184 | bool WriteExclusive16(const VAddr addr, const u16 data, const u16 expected) { | ||
| 185 | return WriteExclusive<u16_le>(addr, data, expected); | ||
| 186 | } | ||
| 187 | |||
| 188 | bool WriteExclusive32(const VAddr addr, const u32 data, const u32 expected) { | ||
| 189 | return WriteExclusive<u32_le>(addr, data, expected); | ||
| 190 | } | ||
| 191 | |||
| 192 | bool WriteExclusive64(const VAddr addr, const u64 data, const u64 expected) { | ||
| 193 | return WriteExclusive<u64_le>(addr, data, expected); | ||
| 194 | } | ||
| 195 | |||
| 182 | std::string ReadCString(VAddr vaddr, std::size_t max_length) { | 196 | std::string ReadCString(VAddr vaddr, std::size_t max_length) { |
| 183 | std::string string; | 197 | std::string string; |
| 184 | string.reserve(max_length); | 198 | string.reserve(max_length); |
| @@ -682,6 +696,67 @@ struct Memory::Impl { | |||
| 682 | } | 696 | } |
| 683 | } | 697 | } |
| 684 | 698 | ||
| 699 | template <typename T> | ||
| 700 | bool WriteExclusive(const VAddr vaddr, const T data, const T expected) { | ||
| 701 | u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||
| 702 | if (page_pointer != nullptr) { | ||
| 703 | // NOTE: Avoid adding any extra logic to this fast-path block | ||
| 704 | T volatile* pointer = reinterpret_cast<T volatile*>(&page_pointer[vaddr]); | ||
| 705 | return Common::AtomicCompareAndSwap(pointer, data, expected); | ||
| 706 | } | ||
| 707 | |||
| 708 | const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | ||
| 709 | switch (type) { | ||
| 710 | case Common::PageType::Unmapped: | ||
| 711 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, | ||
| 712 | static_cast<u32>(data), vaddr); | ||
| 713 | return true; | ||
| 714 | case Common::PageType::Memory: | ||
| 715 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); | ||
| 716 | break; | ||
| 717 | case Common::PageType::RasterizerCachedMemory: { | ||
| 718 | u8* host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)}; | ||
| 719 | system.GPU().InvalidateRegion(vaddr, sizeof(T)); | ||
| 720 | T volatile* pointer = reinterpret_cast<T volatile*>(&host_ptr); | ||
| 721 | return Common::AtomicCompareAndSwap(pointer, data, expected); | ||
| 722 | break; | ||
| 723 | } | ||
| 724 | default: | ||
| 725 | UNREACHABLE(); | ||
| 726 | } | ||
| 727 | return true; | ||
| 728 | } | ||
| 729 | |||
| 730 | bool WriteExclusive128(const VAddr vaddr, const u128 data, const u128 expected) { | ||
| 731 | u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||
| 732 | if (page_pointer != nullptr) { | ||
| 733 | // NOTE: Avoid adding any extra logic to this fast-path block | ||
| 734 | u64 volatile* pointer = reinterpret_cast<u64 volatile*>(&page_pointer[vaddr]); | ||
| 735 | return Common::AtomicCompareAndSwap(pointer, data, expected); | ||
| 736 | } | ||
| 737 | |||
| 738 | const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | ||
| 739 | switch (type) { | ||
| 740 | case Common::PageType::Unmapped: | ||
| 741 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}{:016X}", sizeof(data) * 8, | ||
| 742 | static_cast<u64>(data[1]), static_cast<u64>(data[0]), vaddr); | ||
| 743 | return true; | ||
| 744 | case Common::PageType::Memory: | ||
| 745 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); | ||
| 746 | break; | ||
| 747 | case Common::PageType::RasterizerCachedMemory: { | ||
| 748 | u8* host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)}; | ||
| 749 | system.GPU().InvalidateRegion(vaddr, sizeof(u128)); | ||
| 750 | u64 volatile* pointer = reinterpret_cast<u64 volatile*>(&host_ptr); | ||
| 751 | return Common::AtomicCompareAndSwap(pointer, data, expected); | ||
| 752 | break; | ||
| 753 | } | ||
| 754 | default: | ||
| 755 | UNREACHABLE(); | ||
| 756 | } | ||
| 757 | return true; | ||
| 758 | } | ||
| 759 | |||
| 685 | Common::PageTable* current_page_table = nullptr; | 760 | Common::PageTable* current_page_table = nullptr; |
| 686 | Core::System& system; | 761 | Core::System& system; |
| 687 | }; | 762 | }; |
| @@ -689,8 +764,8 @@ struct Memory::Impl { | |||
| 689 | Memory::Memory(Core::System& system) : impl{std::make_unique<Impl>(system)} {} | 764 | Memory::Memory(Core::System& system) : impl{std::make_unique<Impl>(system)} {} |
| 690 | Memory::~Memory() = default; | 765 | Memory::~Memory() = default; |
| 691 | 766 | ||
| 692 | void Memory::SetCurrentPageTable(Kernel::Process& process) { | 767 | void Memory::SetCurrentPageTable(Kernel::Process& process, u32 core_id) { |
| 693 | impl->SetCurrentPageTable(process); | 768 | impl->SetCurrentPageTable(process, core_id); |
| 694 | } | 769 | } |
| 695 | 770 | ||
| 696 | void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { | 771 | void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { |
| @@ -764,6 +839,26 @@ void Memory::Write64(VAddr addr, u64 data) { | |||
| 764 | impl->Write64(addr, data); | 839 | impl->Write64(addr, data); |
| 765 | } | 840 | } |
| 766 | 841 | ||
| 842 | bool Memory::WriteExclusive8(VAddr addr, u8 data, u8 expected) { | ||
| 843 | return impl->WriteExclusive8(addr, data, expected); | ||
| 844 | } | ||
| 845 | |||
| 846 | bool Memory::WriteExclusive16(VAddr addr, u16 data, u16 expected) { | ||
| 847 | return impl->WriteExclusive16(addr, data, expected); | ||
| 848 | } | ||
| 849 | |||
| 850 | bool Memory::WriteExclusive32(VAddr addr, u32 data, u32 expected) { | ||
| 851 | return impl->WriteExclusive32(addr, data, expected); | ||
| 852 | } | ||
| 853 | |||
| 854 | bool Memory::WriteExclusive64(VAddr addr, u64 data, u64 expected) { | ||
| 855 | return impl->WriteExclusive64(addr, data, expected); | ||
| 856 | } | ||
| 857 | |||
| 858 | bool Memory::WriteExclusive128(VAddr addr, u128 data, u128 expected) { | ||
| 859 | return impl->WriteExclusive128(addr, data, expected); | ||
| 860 | } | ||
| 861 | |||
| 767 | std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) { | 862 | std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) { |
| 768 | return impl->ReadCString(vaddr, max_length); | 863 | return impl->ReadCString(vaddr, max_length); |
| 769 | } | 864 | } |