diff options
| author | 2023-11-30 09:20:55 -0500 | |
|---|---|---|
| committer | 2023-11-30 09:20:55 -0500 | |
| commit | 57a391e71db13ade7a3d96f59d53781eff18d2ac (patch) | |
| tree | 0b4223de40a2d77598ac9095b1374353c2e9da7c /src/core/memory.cpp | |
| parent | Merge pull request #12223 from liamwhite/fruit-company (diff) | |
| parent | core: Rename patcher file (diff) | |
| download | yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.gz yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.tar.xz yuzu-57a391e71db13ade7a3d96f59d53781eff18d2ac.zip | |
Merge pull request #12074 from GPUCode/yuwu-on-the-metal
Implement Native Code Execution (NCE)
Diffstat (limited to 'src/core/memory.cpp')
| -rw-r--r-- | src/core/memory.cpp | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index a3431772a..5b376b202 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -53,7 +53,7 @@ struct Memory::Impl { | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, | 55 | void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, |
| 56 | Common::PhysicalAddress target) { | 56 | Common::PhysicalAddress target, Common::MemoryPermission perms) { |
| 57 | ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); | 57 | ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); |
| 58 | ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base)); | 58 | ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base)); |
| 59 | ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", | 59 | ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", |
| @@ -63,7 +63,7 @@ struct Memory::Impl { | |||
| 63 | 63 | ||
| 64 | if (Settings::IsFastmemEnabled()) { | 64 | if (Settings::IsFastmemEnabled()) { |
| 65 | system.DeviceMemory().buffer.Map(GetInteger(base), | 65 | system.DeviceMemory().buffer.Map(GetInteger(base), |
| 66 | GetInteger(target) - DramMemoryMap::Base, size); | 66 | GetInteger(target) - DramMemoryMap::Base, size, perms); |
| 67 | } | 67 | } |
| 68 | } | 68 | } |
| 69 | 69 | ||
| @@ -78,6 +78,51 @@ struct Memory::Impl { | |||
| 78 | } | 78 | } |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | void ProtectRegion(Common::PageTable& page_table, VAddr vaddr, u64 size, | ||
| 82 | Common::MemoryPermission perms) { | ||
| 83 | ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); | ||
| 84 | ASSERT_MSG((vaddr & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", vaddr); | ||
| 85 | |||
| 86 | if (!Settings::IsFastmemEnabled()) { | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | const bool is_r = True(perms & Common::MemoryPermission::Read); | ||
| 91 | const bool is_w = True(perms & Common::MemoryPermission::Write); | ||
| 92 | const bool is_x = | ||
| 93 | True(perms & Common::MemoryPermission::Execute) && Settings::IsNceEnabled(); | ||
| 94 | |||
| 95 | if (!current_page_table) { | ||
| 96 | system.DeviceMemory().buffer.Protect(vaddr, size, is_r, is_w, is_x); | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | |||
| 100 | u64 protect_bytes{}; | ||
| 101 | u64 protect_begin{}; | ||
| 102 | for (u64 addr = vaddr; addr < vaddr + size; addr += YUZU_PAGESIZE) { | ||
| 103 | const Common::PageType page_type{ | ||
| 104 | current_page_table->pointers[addr >> YUZU_PAGEBITS].Type()}; | ||
| 105 | switch (page_type) { | ||
| 106 | case Common::PageType::RasterizerCachedMemory: | ||
| 107 | if (protect_bytes > 0) { | ||
| 108 | system.DeviceMemory().buffer.Protect(protect_begin, protect_bytes, is_r, is_w, | ||
| 109 | is_x); | ||
| 110 | protect_bytes = 0; | ||
| 111 | } | ||
| 112 | break; | ||
| 113 | default: | ||
| 114 | if (protect_bytes == 0) { | ||
| 115 | protect_begin = addr; | ||
| 116 | } | ||
| 117 | protect_bytes += YUZU_PAGESIZE; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | if (protect_bytes > 0) { | ||
| 122 | system.DeviceMemory().buffer.Protect(protect_begin, protect_bytes, is_r, is_w, is_x); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 81 | [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const { | 126 | [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const { |
| 82 | const Common::PhysicalAddress paddr{ | 127 | const Common::PhysicalAddress paddr{ |
| 83 | current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]}; | 128 | current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]}; |
| @@ -831,14 +876,19 @@ void Memory::SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) { | |||
| 831 | } | 876 | } |
| 832 | 877 | ||
| 833 | void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, | 878 | void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, |
| 834 | Common::PhysicalAddress target) { | 879 | Common::PhysicalAddress target, Common::MemoryPermission perms) { |
| 835 | impl->MapMemoryRegion(page_table, base, size, target); | 880 | impl->MapMemoryRegion(page_table, base, size, target, perms); |
| 836 | } | 881 | } |
| 837 | 882 | ||
| 838 | void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) { | 883 | void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) { |
| 839 | impl->UnmapRegion(page_table, base, size); | 884 | impl->UnmapRegion(page_table, base, size); |
| 840 | } | 885 | } |
| 841 | 886 | ||
| 887 | void Memory::ProtectRegion(Common::PageTable& page_table, Common::ProcessAddress vaddr, u64 size, | ||
| 888 | Common::MemoryPermission perms) { | ||
| 889 | impl->ProtectRegion(page_table, GetInteger(vaddr), size, perms); | ||
| 890 | } | ||
| 891 | |||
| 842 | bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const { | 892 | bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const { |
| 843 | const Kernel::KProcess& process = *system.ApplicationProcess(); | 893 | const Kernel::KProcess& process = *system.ApplicationProcess(); |
| 844 | const auto& page_table = process.GetPageTable().GetImpl(); | 894 | const auto& page_table = process.GetPageTable().GetImpl(); |
| @@ -1001,4 +1051,17 @@ void Memory::FlushRegion(Common::ProcessAddress dest_addr, size_t size) { | |||
| 1001 | impl->FlushRegion(dest_addr, size); | 1051 | impl->FlushRegion(dest_addr, size); |
| 1002 | } | 1052 | } |
| 1003 | 1053 | ||
| 1054 | bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { | ||
| 1055 | bool mapped = true; | ||
| 1056 | u8* const ptr = impl->GetPointerImpl( | ||
| 1057 | GetInteger(vaddr), | ||
| 1058 | [&] { | ||
| 1059 | LOG_ERROR(HW_Memory, "Unmapped InvalidateNCE for {} bytes @ {:#x}", size, | ||
| 1060 | GetInteger(vaddr)); | ||
| 1061 | mapped = false; | ||
| 1062 | }, | ||
| 1063 | [&] { impl->system.GPU().InvalidateRegion(GetInteger(vaddr), size); }); | ||
| 1064 | return mapped && ptr != nullptr; | ||
| 1065 | } | ||
| 1066 | |||
| 1004 | } // namespace Core::Memory | 1067 | } // namespace Core::Memory |