Przeglądaj źródła

core: arm: Implement InvalidateCacheRange for CPU cache invalidation.

bunnei 5 lat temu
rodzic
commit
63fd1bb503

+ 13 - 6
src/core/arm/arm_interface.h

@@ -70,12 +70,19 @@ public:
     /// Clear all instruction cache
     /// Clear all instruction cache
     virtual void ClearInstructionCache() = 0;
     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,
     virtual void PageTableChanged(Common::PageTable& new_page_table,
                                   std::size_t new_address_space_size_in_bits) = 0;
                                   std::size_t new_address_space_size_in_bits) = 0;
 
 

+ 7 - 0
src/core/arm/dynarmic/arm_dynarmic_32.cpp

@@ -286,6 +286,13 @@ void ARM_Dynarmic_32::ClearInstructionCache() {
     jit->ClearCache();
     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() {
 void ARM_Dynarmic_32::ClearExclusiveState() {
     jit->ClearExclusiveState();
     jit->ClearExclusiveState();
 }
 }

+ 1 - 0
src/core/arm/dynarmic/arm_dynarmic_32.h

@@ -59,6 +59,7 @@ public:
     void ClearExclusiveState() override;
     void ClearExclusiveState() override;
 
 
     void ClearInstructionCache() override;
     void ClearInstructionCache() override;
+    void InvalidateCacheRange(VAddr addr, std::size_t size) override;
     void PageTableChanged(Common::PageTable& new_page_table,
     void PageTableChanged(Common::PageTable& new_page_table,
                           std::size_t new_address_space_size_in_bits) override;
                           std::size_t new_address_space_size_in_bits) override;
 
 

+ 7 - 0
src/core/arm/dynarmic/arm_dynarmic_64.cpp

@@ -322,6 +322,13 @@ void ARM_Dynarmic_64::ClearInstructionCache() {
     jit->ClearCache();
     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() {
 void ARM_Dynarmic_64::ClearExclusiveState() {
     jit->ClearExclusiveState();
     jit->ClearExclusiveState();
 }
 }

+ 1 - 0
src/core/arm/dynarmic/arm_dynarmic_64.h

@@ -56,6 +56,7 @@ public:
     void ClearExclusiveState() override;
     void ClearExclusiveState() override;
 
 
     void ClearInstructionCache() override;
     void ClearInstructionCache() override;
+    void InvalidateCacheRange(VAddr addr, std::size_t size) override;
     void PageTableChanged(Common::PageTable& new_page_table,
     void PageTableChanged(Common::PageTable& new_page_table,
                           std::size_t new_address_space_size_in_bits) override;
                           std::size_t new_address_space_size_in_bits) override;
 
 

+ 4 - 0
src/core/core.cpp

@@ -457,6 +457,10 @@ void System::InvalidateCpuInstructionCaches() {
     impl->kernel.InvalidateAllInstructionCaches();
     impl->kernel.InvalidateAllInstructionCaches();
 }
 }
 
 
+void System::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
+    impl->kernel.InvalidateCpuInstructionCacheRange(addr, size);
+}
+
 void System::Shutdown() {
 void System::Shutdown() {
     impl->Shutdown();
     impl->Shutdown();
 }
 }

+ 2 - 0
src/core/core.h

@@ -166,6 +166,8 @@ public:
      */
      */
     void InvalidateCpuInstructionCaches();
     void InvalidateCpuInstructionCaches();
 
 
+    void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
+
     /// Shutdown the emulated system.
     /// Shutdown the emulated system.
     void Shutdown();
     void Shutdown();
 
 

+ 10 - 5
src/core/hle/kernel/kernel.cpp

@@ -497,12 +497,17 @@ const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
 }
 }
 
 
 void KernelCore::InvalidateAllInstructionCaches() {
 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);
     }
     }
 }
 }
 
 

+ 2 - 0
src/core/hle/kernel/kernel.h

@@ -156,6 +156,8 @@ public:
 
 
     void InvalidateAllInstructionCaches();
     void InvalidateAllInstructionCaches();
 
 
+    void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
+
     /// Adds a port to the named port table
     /// Adds a port to the named port table
     void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
     void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
 
 

+ 5 - 0
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;
         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 std::size_t num_pages{size / PageSize};
     const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None
     const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None
                                       ? OperationType::ChangePermissionsAndRefresh
                                       ? OperationType::ChangePermissionsAndRefresh

+ 4 - 0
src/core/hle/kernel/physical_core.h

@@ -58,6 +58,10 @@ public:
     // Shutdown this physical core.
     // Shutdown this physical core.
     void Shutdown();
     void Shutdown();
 
 
+    bool IsInitialized() const {
+        return arm_interface != nullptr;
+    }
+
     Core::ARM_Interface& ArmInterface() {
     Core::ARM_Interface& ArmInterface() {
         return *arm_interface;
         return *arm_interface;
     }
     }

+ 0 - 5
src/core/hle/service/ldr/ldr.cpp

@@ -527,9 +527,6 @@ public:
                                      header.segment_headers[RO_INDEX].memory_size,
                                      header.segment_headers[RO_INDEX].memory_size,
                                      header.segment_headers[DATA_INDEX].memory_size, nro_address});
                                      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};
         IPC::ResponseBuilder rb{ctx, 4};
         rb.Push(RESULT_SUCCESS);
         rb.Push(RESULT_SUCCESS);
         rb.Push(*map_result);
         rb.Push(*map_result);
@@ -590,8 +587,6 @@ public:
 
 
         const auto result{UnmapNro(iter->second)};
         const auto result{UnmapNro(iter->second)};
 
 
-        system.InvalidateCpuInstructionCaches();
-
         nro.erase(iter);
         nro.erase(iter);
 
 
         IPC::ResponseBuilder rb{ctx, 2};
         IPC::ResponseBuilder rb{ctx, 2};