summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando S2022-04-07 16:21:41 +0200
committerGravatar GitHub2022-04-07 16:21:41 +0200
commit50192eb4adfa59703d13c7b77797a4eb092d9301 (patch)
treef1d4f9e5eb519185d343ec0f92f7e50da8bbe1dc /src
parentMerge pull request #8143 from merryhime/rdtsc (diff)
parentarm_dynarmic: Use HaltReason for svc calls and reschedules (diff)
downloadyuzu-50192eb4adfa59703d13c7b77797a4eb092d9301.tar.gz
yuzu-50192eb4adfa59703d13c7b77797a4eb092d9301.tar.xz
yuzu-50192eb4adfa59703d13c7b77797a4eb092d9301.zip
Merge pull request #8148 from merryhime/interrupts
dynarmic: Better interrupts
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/arm_interface.h3
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp37
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp38
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h4
-rw-r--r--src/core/hle/kernel/physical_core.cpp1
6 files changed, 42 insertions, 45 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index c60322442..dce2f4195 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -171,6 +171,9 @@ public:
171 /// Prepare core for thread reschedule (if needed to correctly handle state) 171 /// Prepare core for thread reschedule (if needed to correctly handle state)
172 virtual void PrepareReschedule() = 0; 172 virtual void PrepareReschedule() = 0;
173 173
174 /// Signal an interrupt and ask the core to halt as soon as possible.
175 virtual void SignalInterrupt() = 0;
176
174 struct BacktraceEntry { 177 struct BacktraceEntry {
175 std::string module; 178 std::string module;
176 u64 address; 179 u64 address;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 054572445..ab3210d84 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -25,6 +25,9 @@ namespace Core {
25 25
26using namespace Common::Literals; 26using namespace Common::Literals;
27 27
28constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
29constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
30
28class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { 31class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
29public: 32public:
30 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) 33 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
@@ -84,15 +87,13 @@ public:
84 } 87 }
85 88
86 void CallSVC(u32 swi) override { 89 void CallSVC(u32 swi) override {
87 parent.svc_called = true;
88 parent.svc_swi = swi; 90 parent.svc_swi = swi;
89 parent.jit->HaltExecution(); 91 parent.jit->HaltExecution(svc_call);
90 } 92 }
91 93
92 void AddTicks(u64 ticks) override { 94 void AddTicks(u64 ticks) override {
93 if (parent.uses_wall_clock) { 95 ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
94 return; 96
95 }
96 // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a 97 // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
97 // rough approximation of the amount of executed ticks in the system, it may be thrown off 98 // rough approximation of the amount of executed ticks in the system, it may be thrown off
98 // if not all cores are doing a similar amount of work. Instead of doing this, we should 99 // if not all cores are doing a similar amount of work. Instead of doing this, we should
@@ -108,12 +109,8 @@ public:
108 } 109 }
109 110
110 u64 GetTicksRemaining() override { 111 u64 GetTicksRemaining() override {
111 if (parent.uses_wall_clock) { 112 ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
112 if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) { 113
113 return minimum_run_cycles;
114 }
115 return 0U;
116 }
117 return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); 114 return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
118 } 115 }
119 116
@@ -148,6 +145,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
148 145
149 // Timing 146 // Timing
150 config.wall_clock_cntpct = uses_wall_clock; 147 config.wall_clock_cntpct = uses_wall_clock;
148 config.enable_cycle_counting = !uses_wall_clock;
151 149
152 // Code cache size 150 // Code cache size
153 config.code_cache_size = 512_MiB; 151 config.code_cache_size = 512_MiB;
@@ -230,13 +228,11 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
230 228
231void ARM_Dynarmic_32::Run() { 229void ARM_Dynarmic_32::Run() {
232 while (true) { 230 while (true) {
233 jit->Run(); 231 const auto hr = jit->Run();
234 if (!svc_called) { 232 if (Has(hr, svc_call)) {
235 break; 233 Kernel::Svc::Call(system, svc_swi);
236 } 234 }
237 svc_called = false; 235 if (Has(hr, break_loop)) {
238 Kernel::Svc::Call(system, svc_swi);
239 if (shutdown) {
240 break; 236 break;
241 } 237 }
242 } 238 }
@@ -322,8 +318,11 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
322} 318}
323 319
324void ARM_Dynarmic_32::PrepareReschedule() { 320void ARM_Dynarmic_32::PrepareReschedule() {
325 jit->HaltExecution(); 321 jit->HaltExecution(break_loop);
326 shutdown = true; 322}
323
324void ARM_Dynarmic_32::SignalInterrupt() {
325 jit->HaltExecution(break_loop);
327} 326}
328 327
329void ARM_Dynarmic_32::ClearInstructionCache() { 328void ARM_Dynarmic_32::ClearInstructionCache() {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 5d47b600d..3f68a4ff1 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -57,6 +57,7 @@ public:
57 void LoadContext(const ThreadContext64& ctx) override {} 57 void LoadContext(const ThreadContext64& ctx) override {}
58 58
59 void PrepareReschedule() override; 59 void PrepareReschedule() override;
60 void SignalInterrupt() override;
60 void ClearExclusiveState() override; 61 void ClearExclusiveState() override;
61 62
62 void ClearInstructionCache() override; 63 void ClearInstructionCache() override;
@@ -83,9 +84,6 @@ private:
83 84
84 // SVC callback 85 // SVC callback
85 u32 svc_swi{}; 86 u32 svc_swi{};
86 bool svc_called{};
87
88 bool shutdown{};
89}; 87};
90 88
91} // namespace Core 89} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 7ff8f9495..68822a1fc 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -26,6 +26,9 @@ namespace Core {
26using Vector = Dynarmic::A64::Vector; 26using Vector = Dynarmic::A64::Vector;
27using namespace Common::Literals; 27using namespace Common::Literals;
28 28
29constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
30constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
31
29class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { 32class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
30public: 33public:
31 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) 34 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
@@ -106,7 +109,7 @@ public:
106 break; 109 break;
107 } 110 }
108 111
109 parent.jit->HaltExecution(); 112 parent.jit->HaltExecution(Dynarmic::HaltReason::CacheInvalidation);
110 } 113 }
111 114
112 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { 115 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override {
@@ -126,15 +129,12 @@ public:
126 } 129 }
127 130
128 void CallSVC(u32 swi) override { 131 void CallSVC(u32 swi) override {
129 parent.svc_called = true;
130 parent.svc_swi = swi; 132 parent.svc_swi = swi;
131 parent.jit->HaltExecution(); 133 parent.jit->HaltExecution(svc_call);
132 } 134 }
133 135
134 void AddTicks(u64 ticks) override { 136 void AddTicks(u64 ticks) override {
135 if (parent.uses_wall_clock) { 137 ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
136 return;
137 }
138 138
139 // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a 139 // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
140 // rough approximation of the amount of executed ticks in the system, it may be thrown off 140 // rough approximation of the amount of executed ticks in the system, it may be thrown off
@@ -149,12 +149,8 @@ public:
149 } 149 }
150 150
151 u64 GetTicksRemaining() override { 151 u64 GetTicksRemaining() override {
152 if (parent.uses_wall_clock) { 152 ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
153 if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) { 153
154 return minimum_run_cycles;
155 }
156 return 0U;
157 }
158 return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); 154 return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
159 } 155 }
160 156
@@ -210,6 +206,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
210 206
211 // Timing 207 // Timing
212 config.wall_clock_cntpct = uses_wall_clock; 208 config.wall_clock_cntpct = uses_wall_clock;
209 config.enable_cycle_counting = !uses_wall_clock;
213 210
214 // Code cache size 211 // Code cache size
215 config.code_cache_size = 512_MiB; 212 config.code_cache_size = 512_MiB;
@@ -292,13 +289,11 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
292 289
293void ARM_Dynarmic_64::Run() { 290void ARM_Dynarmic_64::Run() {
294 while (true) { 291 while (true) {
295 jit->Run(); 292 const auto hr = jit->Run();
296 if (!svc_called) { 293 if (Has(hr, svc_call)) {
297 break; 294 Kernel::Svc::Call(system, svc_swi);
298 } 295 }
299 svc_called = false; 296 if (Has(hr, break_loop)) {
300 Kernel::Svc::Call(system, svc_swi);
301 if (shutdown) {
302 break; 297 break;
303 } 298 }
304 } 299 }
@@ -389,8 +384,11 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
389} 384}
390 385
391void ARM_Dynarmic_64::PrepareReschedule() { 386void ARM_Dynarmic_64::PrepareReschedule() {
392 jit->HaltExecution(); 387 jit->HaltExecution(break_loop);
393 shutdown = true; 388}
389
390void ARM_Dynarmic_64::SignalInterrupt() {
391 jit->HaltExecution(break_loop);
394} 392}
395 393
396void ARM_Dynarmic_64::ClearInstructionCache() { 394void ARM_Dynarmic_64::ClearInstructionCache() {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 0c4e46c64..58bc7fbec 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -51,6 +51,7 @@ public:
51 void LoadContext(const ThreadContext64& ctx) override; 51 void LoadContext(const ThreadContext64& ctx) override;
52 52
53 void PrepareReschedule() override; 53 void PrepareReschedule() override;
54 void SignalInterrupt() override;
54 void ClearExclusiveState() override; 55 void ClearExclusiveState() override;
55 56
56 void ClearInstructionCache() override; 57 void ClearInstructionCache() override;
@@ -77,9 +78,6 @@ private:
77 78
78 // SVC callback 79 // SVC callback
79 u32 svc_swi{}; 80 u32 svc_swi{};
80 bool svc_called{};
81
82 bool shutdown{};
83}; 81};
84 82
85} // namespace Core 83} // namespace Core
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp
index 7477668e4..18a5f40f8 100644
--- a/src/core/hle/kernel/physical_core.cpp
+++ b/src/core/hle/kernel/physical_core.cpp
@@ -58,6 +58,7 @@ bool PhysicalCore::IsInterrupted() const {
58void PhysicalCore::Interrupt() { 58void PhysicalCore::Interrupt() {
59 guard->lock(); 59 guard->lock();
60 interrupts[core_index].SetInterrupt(true); 60 interrupts[core_index].SetInterrupt(true);
61 arm_interface->SignalInterrupt();
61 guard->unlock(); 62 guard->unlock();
62} 63}
63 64