summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/arm/arm_interface.h19
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp7
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h1
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp7
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h1
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/core.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp15
-rw-r--r--src/core/hle/kernel/kernel.h2
-rw-r--r--src/core/hle/kernel/memory/page_table.cpp5
-rw-r--r--src/core/hle/kernel/physical_core.h4
-rw-r--r--src/core/hle/service/ldr/ldr.cpp5
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:
/// Clear all instruction cache
virtual void ClearInstructionCache() = 0;
- /// Notifies CPU emulation that the current page table has changed.
- ///
- /// @param new_page_table The new page table.
- /// @param new_address_space_size_in_bits The new usable size of the address space in bits.
- /// This can be either 32, 36, or 39 on official software.
- ///
+ /**
+ * Clear instruction cache range
+ * @param addr Start address of the cache range to clear
+ * @param size Size of the cache range to clear, starting at addr
+ */
+ virtual void InvalidateCacheRange(VAddr addr, std::size_t size) = 0;
+
+ /**
+ * Notifies CPU emulation that the current page table has changed.
+ * @param new_page_table The new page table.
+ * @param new_address_space_size_in_bits The new usable size of the address space in bits.
+ * This can be either 32, 36, or 39 on official software.
+ */
virtual void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) = 0;
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() {
jit->ClearCache();
}
+void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) {
+ if (!jit) {
+ return;
+ }
+ jit->InvalidateCacheRange(static_cast<u32>(addr), size);
+}
+
void ARM_Dynarmic_32::ClearExclusiveState() {
jit->ClearExclusiveState();
}
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:
void ClearExclusiveState() override;
void ClearInstructionCache() override;
+ void InvalidateCacheRange(VAddr addr, std::size_t size) override;
void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override;
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() {
jit->ClearCache();
}
+void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) {
+ if (!jit) {
+ return;
+ }
+ jit->InvalidateCacheRange(addr, size);
+}
+
void ARM_Dynarmic_64::ClearExclusiveState() {
jit->ClearExclusiveState();
}
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:
void ClearExclusiveState() override;
void ClearInstructionCache() override;
+ void InvalidateCacheRange(VAddr addr, std::size_t size) override;
void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override;
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() {
impl->kernel.InvalidateAllInstructionCaches();
}
+void System::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
+ impl->kernel.InvalidateCpuInstructionCacheRange(addr, size);
+}
+
void System::Shutdown() {
impl->Shutdown();
}
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:
*/
void InvalidateCpuInstructionCaches();
+ void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
+
/// Shutdown the emulated system.
void Shutdown();
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 {
}
void KernelCore::InvalidateAllInstructionCaches() {
- if (!IsMulticore()) {
- for (auto& physical_core : impl->cores) {
- physical_core.ArmInterface().ClearInstructionCache();
+ for (auto& physical_core : impl->cores) {
+ physical_core.ArmInterface().ClearInstructionCache();
+ }
+}
+
+void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
+ for (auto& physical_core : impl->cores) {
+ if (!physical_core.IsInitialized()) {
+ continue;
}
- } else {
- UNIMPLEMENTED();
+ physical_core.ArmInterface().InvalidateCacheRange(addr, size);
}
}
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:
void InvalidateAllInstructionCaches();
+ void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
+
/// Adds a port to the named port table
void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
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
return RESULT_SUCCESS;
}
+ if ((prev_perm & MemoryPermission::Execute) != (perm & MemoryPermission::Execute)) {
+ // Memory execution state is changing, invalidate CPU cache range
+ system.InvalidateCpuInstructionCacheRange(addr, size);
+ }
+
const std::size_t num_pages{size / PageSize};
const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None
? 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:
// Shutdown this physical core.
void Shutdown();
+ bool IsInitialized() const {
+ return arm_interface != nullptr;
+ }
+
Core::ARM_Interface& ArmInterface() {
return *arm_interface;
}
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:
header.segment_headers[RO_INDEX].memory_size,
header.segment_headers[DATA_INDEX].memory_size, nro_address});
- // Invalidate JIT caches for the newly mapped process code
- system.InvalidateCpuInstructionCaches();
-
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push(*map_result);
@@ -590,8 +587,6 @@ public:
const auto result{UnmapNro(iter->second)};
- system.InvalidateCpuInstructionCaches();
-
nro.erase(iter);
IPC::ResponseBuilder rb{ctx, 2};