Răsfoiți Sursa

Merge pull request #8148 from merryhime/interrupts

dynarmic: Better interrupts
Fernando S 4 ani în urmă
părinte
comite
50192eb4ad

+ 1 - 1
externals/dynarmic

@@ -1 +1 @@
-Subproject commit af2d50288fc537201014c4230bb55ab9018a7438
+Subproject commit 644172477eaf0d822178cb7e96c62b75caa96573

+ 3 - 0
src/core/arm/arm_interface.h

@@ -171,6 +171,9 @@ public:
     /// Prepare core for thread reschedule (if needed to correctly handle state)
     virtual void PrepareReschedule() = 0;
 
+    /// Signal an interrupt and ask the core to halt as soon as possible.
+    virtual void SignalInterrupt() = 0;
+
     struct BacktraceEntry {
         std::string module;
         u64 address;

+ 18 - 19
src/core/arm/dynarmic/arm_dynarmic_32.cpp

@@ -25,6 +25,9 @@ namespace Core {
 
 using namespace Common::Literals;
 
+constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
+constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
+
 class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
 public:
     explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
@@ -84,15 +87,13 @@ public:
     }
 
     void CallSVC(u32 swi) override {
-        parent.svc_called = true;
         parent.svc_swi = swi;
-        parent.jit->HaltExecution();
+        parent.jit->HaltExecution(svc_call);
     }
 
     void AddTicks(u64 ticks) override {
-        if (parent.uses_wall_clock) {
-            return;
-        }
+        ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
+
         // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
         // rough approximation of the amount of executed ticks in the system, it may be thrown off
         // if not all cores are doing a similar amount of work. Instead of doing this, we should
@@ -108,12 +109,8 @@ public:
     }
 
     u64 GetTicksRemaining() override {
-        if (parent.uses_wall_clock) {
-            if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) {
-                return minimum_run_cycles;
-            }
-            return 0U;
-        }
+        ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
+
         return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
     }
 
@@ -148,6 +145,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
 
     // Timing
     config.wall_clock_cntpct = uses_wall_clock;
+    config.enable_cycle_counting = !uses_wall_clock;
 
     // Code cache size
     config.code_cache_size = 512_MiB;
@@ -230,13 +228,11 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
 
 void ARM_Dynarmic_32::Run() {
     while (true) {
-        jit->Run();
-        if (!svc_called) {
-            break;
+        const auto hr = jit->Run();
+        if (Has(hr, svc_call)) {
+            Kernel::Svc::Call(system, svc_swi);
         }
-        svc_called = false;
-        Kernel::Svc::Call(system, svc_swi);
-        if (shutdown) {
+        if (Has(hr, break_loop)) {
             break;
         }
     }
@@ -322,8 +318,11 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
 }
 
 void ARM_Dynarmic_32::PrepareReschedule() {
-    jit->HaltExecution();
-    shutdown = true;
+    jit->HaltExecution(break_loop);
+}
+
+void ARM_Dynarmic_32::SignalInterrupt() {
+    jit->HaltExecution(break_loop);
 }
 
 void ARM_Dynarmic_32::ClearInstructionCache() {

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

@@ -57,6 +57,7 @@ public:
     void LoadContext(const ThreadContext64& ctx) override {}
 
     void PrepareReschedule() override;
+    void SignalInterrupt() override;
     void ClearExclusiveState() override;
 
     void ClearInstructionCache() override;
@@ -83,9 +84,6 @@ private:
 
     // SVC callback
     u32 svc_swi{};
-    bool svc_called{};
-
-    bool shutdown{};
 };
 
 } // namespace Core

+ 18 - 20
src/core/arm/dynarmic/arm_dynarmic_64.cpp

@@ -26,6 +26,9 @@ namespace Core {
 using Vector = Dynarmic::A64::Vector;
 using namespace Common::Literals;
 
+constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
+constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
+
 class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
 public:
     explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
@@ -106,7 +109,7 @@ public:
             break;
         }
 
-        parent.jit->HaltExecution();
+        parent.jit->HaltExecution(Dynarmic::HaltReason::CacheInvalidation);
     }
 
     void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override {
@@ -126,15 +129,12 @@ public:
     }
 
     void CallSVC(u32 swi) override {
-        parent.svc_called = true;
         parent.svc_swi = swi;
-        parent.jit->HaltExecution();
+        parent.jit->HaltExecution(svc_call);
     }
 
     void AddTicks(u64 ticks) override {
-        if (parent.uses_wall_clock) {
-            return;
-        }
+        ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
 
         // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
         // rough approximation of the amount of executed ticks in the system, it may be thrown off
@@ -149,12 +149,8 @@ public:
     }
 
     u64 GetTicksRemaining() override {
-        if (parent.uses_wall_clock) {
-            if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) {
-                return minimum_run_cycles;
-            }
-            return 0U;
-        }
+        ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
+
         return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
     }
 
@@ -210,6 +206,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
 
     // Timing
     config.wall_clock_cntpct = uses_wall_clock;
+    config.enable_cycle_counting = !uses_wall_clock;
 
     // Code cache size
     config.code_cache_size = 512_MiB;
@@ -292,13 +289,11 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
 
 void ARM_Dynarmic_64::Run() {
     while (true) {
-        jit->Run();
-        if (!svc_called) {
-            break;
+        const auto hr = jit->Run();
+        if (Has(hr, svc_call)) {
+            Kernel::Svc::Call(system, svc_swi);
         }
-        svc_called = false;
-        Kernel::Svc::Call(system, svc_swi);
-        if (shutdown) {
+        if (Has(hr, break_loop)) {
             break;
         }
     }
@@ -389,8 +384,11 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
 }
 
 void ARM_Dynarmic_64::PrepareReschedule() {
-    jit->HaltExecution();
-    shutdown = true;
+    jit->HaltExecution(break_loop);
+}
+
+void ARM_Dynarmic_64::SignalInterrupt() {
+    jit->HaltExecution(break_loop);
 }
 
 void ARM_Dynarmic_64::ClearInstructionCache() {

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

@@ -51,6 +51,7 @@ public:
     void LoadContext(const ThreadContext64& ctx) override;
 
     void PrepareReschedule() override;
+    void SignalInterrupt() override;
     void ClearExclusiveState() override;
 
     void ClearInstructionCache() override;
@@ -77,9 +78,6 @@ private:
 
     // SVC callback
     u32 svc_swi{};
-    bool svc_called{};
-
-    bool shutdown{};
 };
 
 } // namespace Core

+ 1 - 0
src/core/hle/kernel/physical_core.cpp

@@ -58,6 +58,7 @@ bool PhysicalCore::IsInterrupted() const {
 void PhysicalCore::Interrupt() {
     guard->lock();
     interrupts[core_index].SetInterrupt(true);
+    arm_interface->SignalInterrupt();
     guard->unlock();
 }