diff options
| -rw-r--r-- | src/core/arm/arm_interface.h | 19 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 7 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.h | 1 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 7 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.h | 1 | ||||
| -rw-r--r-- | src/core/core.cpp | 4 | ||||
| -rw-r--r-- | src/core/core.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 15 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/memory/page_table.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/physical_core.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/ldr/ldr.cpp | 5 |
12 files changed, 56 insertions, 16 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index b3d8ceaf8..70098c526 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -70,12 +70,19 @@ public: | |||
| 70 | /// Clear all instruction cache | 70 | /// Clear all instruction cache |
| 71 | virtual void ClearInstructionCache() = 0; | 71 | virtual void ClearInstructionCache() = 0; |
| 72 | 72 | ||
| 73 | /// Notifies CPU emulation that the current page table has changed. | 73 | /** |
| 74 | /// | 74 | * Clear instruction cache range |
| 75 | /// @param new_page_table The new page table. | 75 | * @param addr Start address of the cache range to clear |
| 76 | /// @param new_address_space_size_in_bits The new usable size of the address space in bits. | 76 | * @param size Size of the cache range to clear, starting at addr |
| 77 | /// This can be either 32, 36, or 39 on official software. | 77 | */ |
| 78 | /// | 78 | virtual void InvalidateCacheRange(VAddr addr, std::size_t size) = 0; |
| 79 | |||
| 80 | /** | ||
| 81 | * Notifies CPU emulation that the current page table has changed. | ||
| 82 | * @param new_page_table The new page table. | ||
| 83 | * @param new_address_space_size_in_bits The new usable size of the address space in bits. | ||
| 84 | * This can be either 32, 36, or 39 on official software. | ||
| 85 | */ | ||
| 79 | virtual void PageTableChanged(Common::PageTable& new_page_table, | 86 | virtual void PageTableChanged(Common::PageTable& new_page_table, |
| 80 | std::size_t new_address_space_size_in_bits) = 0; | 87 | std::size_t new_address_space_size_in_bits) = 0; |
| 81 | 88 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index af23206f5..193fd7d62 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -286,6 +286,13 @@ void ARM_Dynarmic_32::ClearInstructionCache() { | |||
| 286 | jit->ClearCache(); | 286 | jit->ClearCache(); |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) { | ||
| 290 | if (!jit) { | ||
| 291 | return; | ||
| 292 | } | ||
| 293 | jit->InvalidateCacheRange(static_cast<u32>(addr), size); | ||
| 294 | } | ||
| 295 | |||
| 289 | void ARM_Dynarmic_32::ClearExclusiveState() { | 296 | void ARM_Dynarmic_32::ClearExclusiveState() { |
| 290 | jit->ClearExclusiveState(); | 297 | jit->ClearExclusiveState(); |
| 291 | } | 298 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index e16b689c8..35e9ced48 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -59,6 +59,7 @@ public: | |||
| 59 | void ClearExclusiveState() override; | 59 | void ClearExclusiveState() override; |
| 60 | 60 | ||
| 61 | void ClearInstructionCache() override; | 61 | void ClearInstructionCache() override; |
| 62 | void InvalidateCacheRange(VAddr addr, std::size_t size) override; | ||
| 62 | void PageTableChanged(Common::PageTable& new_page_table, | 63 | void PageTableChanged(Common::PageTable& new_page_table, |
| 63 | std::size_t new_address_space_size_in_bits) override; | 64 | std::size_t new_address_space_size_in_bits) override; |
| 64 | 65 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 1c9fd18b5..0f0585d0f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -322,6 +322,13 @@ void ARM_Dynarmic_64::ClearInstructionCache() { | |||
| 322 | jit->ClearCache(); | 322 | jit->ClearCache(); |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) { | ||
| 326 | if (!jit) { | ||
| 327 | return; | ||
| 328 | } | ||
| 329 | jit->InvalidateCacheRange(addr, size); | ||
| 330 | } | ||
| 331 | |||
| 325 | void ARM_Dynarmic_64::ClearExclusiveState() { | 332 | void ARM_Dynarmic_64::ClearExclusiveState() { |
| 326 | jit->ClearExclusiveState(); | 333 | jit->ClearExclusiveState(); |
| 327 | } | 334 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index aa0a5c424..329b59a32 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -56,6 +56,7 @@ public: | |||
| 56 | void ClearExclusiveState() override; | 56 | void ClearExclusiveState() override; |
| 57 | 57 | ||
| 58 | void ClearInstructionCache() override; | 58 | void ClearInstructionCache() override; |
| 59 | void InvalidateCacheRange(VAddr addr, std::size_t size) override; | ||
| 59 | void PageTableChanged(Common::PageTable& new_page_table, | 60 | void PageTableChanged(Common::PageTable& new_page_table, |
| 60 | std::size_t new_address_space_size_in_bits) override; | 61 | std::size_t new_address_space_size_in_bits) override; |
| 61 | 62 | ||
diff --git a/src/core/core.cpp b/src/core/core.cpp index 58368fe3c..01e4faac8 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -457,6 +457,10 @@ void System::InvalidateCpuInstructionCaches() { | |||
| 457 | impl->kernel.InvalidateAllInstructionCaches(); | 457 | impl->kernel.InvalidateAllInstructionCaches(); |
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | void System::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { | ||
| 461 | impl->kernel.InvalidateCpuInstructionCacheRange(addr, size); | ||
| 462 | } | ||
| 463 | |||
| 460 | void System::Shutdown() { | 464 | void System::Shutdown() { |
| 461 | impl->Shutdown(); | 465 | impl->Shutdown(); |
| 462 | } | 466 | } |
diff --git a/src/core/core.h b/src/core/core.h index f642befc0..29b8fb92a 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -166,6 +166,8 @@ public: | |||
| 166 | */ | 166 | */ |
| 167 | void InvalidateCpuInstructionCaches(); | 167 | void InvalidateCpuInstructionCaches(); |
| 168 | 168 | ||
| 169 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); | ||
| 170 | |||
| 169 | /// Shutdown the emulated system. | 171 | /// Shutdown the emulated system. |
| 170 | void Shutdown(); | 172 | void Shutdown(); |
| 171 | 173 | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index c426b6378..929db696d 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -497,12 +497,17 @@ const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { | |||
| 497 | } | 497 | } |
| 498 | 498 | ||
| 499 | void KernelCore::InvalidateAllInstructionCaches() { | 499 | void KernelCore::InvalidateAllInstructionCaches() { |
| 500 | if (!IsMulticore()) { | 500 | for (auto& physical_core : impl->cores) { |
| 501 | for (auto& physical_core : impl->cores) { | 501 | physical_core.ArmInterface().ClearInstructionCache(); |
| 502 | physical_core.ArmInterface().ClearInstructionCache(); | 502 | } |
| 503 | } | ||
| 504 | |||
| 505 | void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { | ||
| 506 | for (auto& physical_core : impl->cores) { | ||
| 507 | if (!physical_core.IsInitialized()) { | ||
| 508 | continue; | ||
| 503 | } | 509 | } |
| 504 | } else { | 510 | physical_core.ArmInterface().InvalidateCacheRange(addr, size); |
| 505 | UNIMPLEMENTED(); | ||
| 506 | } | 511 | } |
| 507 | } | 512 | } |
| 508 | 513 | ||
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index a9fdc5860..a73a93039 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -156,6 +156,8 @@ public: | |||
| 156 | 156 | ||
| 157 | void InvalidateAllInstructionCaches(); | 157 | void InvalidateAllInstructionCaches(); |
| 158 | 158 | ||
| 159 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); | ||
| 160 | |||
| 159 | /// Adds a port to the named port table | 161 | /// Adds a port to the named port table |
| 160 | void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port); | 162 | void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port); |
| 161 | 163 | ||
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index a3fadb533..f53a7be82 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp | |||
| @@ -670,6 +670,11 @@ ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, Memo | |||
| 670 | return RESULT_SUCCESS; | 670 | return RESULT_SUCCESS; |
| 671 | } | 671 | } |
| 672 | 672 | ||
| 673 | if ((prev_perm & MemoryPermission::Execute) != (perm & MemoryPermission::Execute)) { | ||
| 674 | // Memory execution state is changing, invalidate CPU cache range | ||
| 675 | system.InvalidateCpuInstructionCacheRange(addr, size); | ||
| 676 | } | ||
| 677 | |||
| 673 | const std::size_t num_pages{size / PageSize}; | 678 | const std::size_t num_pages{size / PageSize}; |
| 674 | const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None | 679 | const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None |
| 675 | ? OperationType::ChangePermissionsAndRefresh | 680 | ? OperationType::ChangePermissionsAndRefresh |
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index ace058a5a..37513130a 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h | |||
| @@ -58,6 +58,10 @@ public: | |||
| 58 | // Shutdown this physical core. | 58 | // Shutdown this physical core. |
| 59 | void Shutdown(); | 59 | void Shutdown(); |
| 60 | 60 | ||
| 61 | bool IsInitialized() const { | ||
| 62 | return arm_interface != nullptr; | ||
| 63 | } | ||
| 64 | |||
| 61 | Core::ARM_Interface& ArmInterface() { | 65 | Core::ARM_Interface& ArmInterface() { |
| 62 | return *arm_interface; | 66 | return *arm_interface; |
| 63 | } | 67 | } |
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index fff68326b..9da786b4e 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -527,9 +527,6 @@ public: | |||
| 527 | header.segment_headers[RO_INDEX].memory_size, | 527 | header.segment_headers[RO_INDEX].memory_size, |
| 528 | header.segment_headers[DATA_INDEX].memory_size, nro_address}); | 528 | header.segment_headers[DATA_INDEX].memory_size, nro_address}); |
| 529 | 529 | ||
| 530 | // Invalidate JIT caches for the newly mapped process code | ||
| 531 | system.InvalidateCpuInstructionCaches(); | ||
| 532 | |||
| 533 | IPC::ResponseBuilder rb{ctx, 4}; | 530 | IPC::ResponseBuilder rb{ctx, 4}; |
| 534 | rb.Push(RESULT_SUCCESS); | 531 | rb.Push(RESULT_SUCCESS); |
| 535 | rb.Push(*map_result); | 532 | rb.Push(*map_result); |
| @@ -590,8 +587,6 @@ public: | |||
| 590 | 587 | ||
| 591 | const auto result{UnmapNro(iter->second)}; | 588 | const auto result{UnmapNro(iter->second)}; |
| 592 | 589 | ||
| 593 | system.InvalidateCpuInstructionCaches(); | ||
| 594 | |||
| 595 | nro.erase(iter); | 590 | nro.erase(iter); |
| 596 | 591 | ||
| 597 | IPC::ResponseBuilder rb{ctx, 2}; | 592 | IPC::ResponseBuilder rb{ctx, 2}; |