summaryrefslogtreecommitdiff
path: root/src/core/arm
diff options
context:
space:
mode:
authorGravatar Liam2022-05-31 14:37:37 -0400
committerGravatar Liam2022-06-01 02:15:15 -0400
commit989d4a7a41f449af0ea09e34bee331a3a3ac8170 (patch)
treedf24bd9d7e6942b939e3ea42d08c0d65006e539f /src/core/arm
parentcore/debugger: Implement new GDB stub debugger (diff)
downloadyuzu-989d4a7a41f449af0ea09e34bee331a3a3ac8170.tar.gz
yuzu-989d4a7a41f449af0ea09e34bee331a3a3ac8170.tar.xz
yuzu-989d4a7a41f449af0ea09e34bee331a3a3ac8170.zip
core/debugger: Improved stepping mechanism and misc fixes
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/arm_interface.cpp45
-rw-r--r--src/core/arm/arm_interface.h14
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp45
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h9
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp45
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h9
6 files changed, 87 insertions, 80 deletions
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 1310f72bf..9b5a5ca57 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -11,6 +11,7 @@
11#include "core/core.h" 11#include "core/core.h"
12#include "core/debugger/debugger.h" 12#include "core/debugger/debugger.h"
13#include "core/hle/kernel/k_process.h" 13#include "core/hle/kernel/k_process.h"
14#include "core/hle/kernel/svc.h"
14#include "core/loader/loader.h" 15#include "core/loader/loader.h"
15#include "core/memory.h" 16#include "core/memory.h"
16 17
@@ -89,8 +90,48 @@ void ARM_Interface::LogBacktrace() const {
89 } 90 }
90} 91}
91 92
92bool ARM_Interface::ShouldStep() const { 93void ARM_Interface::Run() {
93 return system.DebuggerEnabled() && system.GetDebugger().IsStepping(); 94 using Kernel::StepState;
95 using Kernel::SuspendType;
96
97 while (true) {
98 Kernel::KThread* current_thread{system.Kernel().CurrentScheduler()->GetCurrentThread()};
99 Dynarmic::HaltReason hr{};
100
101 // Notify the debugger and go to sleep if a step was performed
102 // and this thread has been scheduled again.
103 if (current_thread->GetStepState() == StepState::StepPerformed) {
104 system.GetDebugger().NotifyThreadStopped(current_thread);
105 current_thread->RequestSuspend(SuspendType::Debug);
106 break;
107 }
108
109 // Otherwise, run the thread.
110 if (current_thread->GetStepState() == StepState::StepPending) {
111 hr = StepJit();
112
113 if (Has(hr, step_thread)) {
114 current_thread->SetStepState(StepState::StepPerformed);
115 }
116 } else {
117 hr = RunJit();
118 }
119
120 // Notify the debugger and go to sleep if a breakpoint was hit.
121 if (Has(hr, breakpoint)) {
122 system.GetDebugger().NotifyThreadStopped(current_thread);
123 current_thread->RequestSuspend(Kernel::SuspendType::Debug);
124 break;
125 }
126
127 // Handle syscalls and scheduling (this may change the current thread)
128 if (Has(hr, svc_call)) {
129 Kernel::Svc::Call(system, GetSvcNumber());
130 }
131 if (Has(hr, break_loop) || !uses_wall_clock) {
132 break;
133 }
134 }
94} 135}
95 136
96} // namespace Core 137} // namespace Core
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 7842c626b..66f6107e9 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -6,6 +6,9 @@
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <vector>
9
10#include <dynarmic/interface/halt_reason.h>
11
9#include "common/common_funcs.h" 12#include "common/common_funcs.h"
10#include "common/common_types.h" 13#include "common/common_types.h"
11#include "core/hardware_properties.h" 14#include "core/hardware_properties.h"
@@ -64,7 +67,7 @@ public:
64 static_assert(sizeof(ThreadContext64) == 0x320); 67 static_assert(sizeof(ThreadContext64) == 0x320);
65 68
66 /// Runs the CPU until an event happens 69 /// Runs the CPU until an event happens
67 virtual void Run() = 0; 70 void Run();
68 71
69 /// Clear all instruction cache 72 /// Clear all instruction cache
70 virtual void ClearInstructionCache() = 0; 73 virtual void ClearInstructionCache() = 0;
@@ -191,7 +194,10 @@ public:
191 194
192 void LogBacktrace() const; 195 void LogBacktrace() const;
193 196
194 bool ShouldStep() const; 197 static constexpr Dynarmic::HaltReason step_thread = Dynarmic::HaltReason::Step;
198 static constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
199 static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
200 static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;
195 201
196protected: 202protected:
197 /// System context that this ARM interface is running under. 203 /// System context that this ARM interface is running under.
@@ -200,6 +206,10 @@ protected:
200 bool uses_wall_clock; 206 bool uses_wall_clock;
201 207
202 static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out); 208 static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out);
209
210 virtual Dynarmic::HaltReason RunJit() = 0;
211 virtual Dynarmic::HaltReason StepJit() = 0;
212 virtual u32 GetSvcNumber() const = 0;
203}; 213};
204 214
205} // namespace Core 215} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 894c1c527..7c82d0b96 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -26,10 +26,6 @@ namespace Core {
26 26
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;
31constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;
32
33class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { 29class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
34public: 30public:
35 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) 31 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
@@ -82,8 +78,8 @@ public:
82 78
83 void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { 79 void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
84 if (parent.system.DebuggerEnabled()) { 80 if (parent.system.DebuggerEnabled()) {
85 parent.breakpoint_pc = pc; 81 parent.jit.load()->Regs()[15] = pc;
86 parent.jit.load()->HaltExecution(breakpoint); 82 parent.jit.load()->HaltExecution(ARM_Interface::breakpoint);
87 return; 83 return;
88 } 84 }
89 85
@@ -95,7 +91,7 @@ public:
95 91
96 void CallSVC(u32 swi) override { 92 void CallSVC(u32 swi) override {
97 parent.svc_swi = swi; 93 parent.svc_swi = swi;
98 parent.jit.load()->HaltExecution(svc_call); 94 parent.jit.load()->HaltExecution(ARM_Interface::svc_call);
99 } 95 }
100 96
101 void AddTicks(u64 ticks) override { 97 void AddTicks(u64 ticks) override {
@@ -240,35 +236,16 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
240 return std::make_unique<Dynarmic::A32::Jit>(config); 236 return std::make_unique<Dynarmic::A32::Jit>(config);
241} 237}
242 238
243void ARM_Dynarmic_32::Run() { 239Dynarmic::HaltReason ARM_Dynarmic_32::RunJit() {
244 while (true) { 240 return jit.load()->Run();
245 const auto hr = ShouldStep() ? jit.load()->Step() : jit.load()->Run(); 241}
246 if (Has(hr, svc_call)) {
247 Kernel::Svc::Call(system, svc_swi);
248 }
249
250 // Check to see if breakpoint is triggered.
251 // Recheck step condition in case stop is no longer desired.
252 Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread();
253 if (Has(hr, breakpoint)) {
254 jit.load()->Regs()[15] = breakpoint_pc;
255 242
256 if (system.GetDebugger().NotifyThreadStopped(current_thread)) { 243Dynarmic::HaltReason ARM_Dynarmic_32::StepJit() {
257 current_thread->RequestSuspend(Kernel::SuspendType::Debug); 244 return jit.load()->Step();
258 } 245}
259 break;
260 }
261 if (ShouldStep()) {
262 // When stepping, this should be the only thread running.
263 ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread));
264 current_thread->RequestSuspend(Kernel::SuspendType::Debug);
265 break;
266 }
267 246
268 if (Has(hr, break_loop) || !uses_wall_clock) { 247u32 ARM_Dynarmic_32::GetSvcNumber() const {
269 break; 248 return svc_swi;
270 }
271 }
272} 249}
273 250
274ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, 251ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_,
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 0557d5940..5b1d60005 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -41,7 +41,6 @@ public:
41 void SetVectorReg(int index, u128 value) override; 41 void SetVectorReg(int index, u128 value) override;
42 u32 GetPSTATE() const override; 42 u32 GetPSTATE() const override;
43 void SetPSTATE(u32 pstate) override; 43 void SetPSTATE(u32 pstate) override;
44 void Run() override;
45 VAddr GetTlsAddress() const override; 44 VAddr GetTlsAddress() const override;
46 void SetTlsAddress(VAddr address) override; 45 void SetTlsAddress(VAddr address) override;
47 void SetTPIDR_EL0(u64 value) override; 46 void SetTPIDR_EL0(u64 value) override;
@@ -69,6 +68,11 @@ public:
69 68
70 std::vector<BacktraceEntry> GetBacktrace() const override; 69 std::vector<BacktraceEntry> GetBacktrace() const override;
71 70
71protected:
72 Dynarmic::HaltReason RunJit() override;
73 Dynarmic::HaltReason StepJit() override;
74 u32 GetSvcNumber() const override;
75
72private: 76private:
73 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; 77 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const;
74 78
@@ -94,9 +98,6 @@ private:
94 98
95 // SVC callback 99 // SVC callback
96 u32 svc_swi{}; 100 u32 svc_swi{};
97
98 // Debug restart address
99 u32 breakpoint_pc{};
100}; 101};
101 102
102} // namespace Core 103} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 1f596cfef..d4c67eafd 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -26,10 +26,6 @@ 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;
31constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;
32
33class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { 29class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
34public: 30public:
35 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) 31 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
@@ -123,8 +119,8 @@ public:
123 return; 119 return;
124 default: 120 default:
125 if (parent.system.DebuggerEnabled()) { 121 if (parent.system.DebuggerEnabled()) {
126 parent.breakpoint_pc = pc; 122 parent.jit.load()->SetPC(pc);
127 parent.jit.load()->HaltExecution(breakpoint); 123 parent.jit.load()->HaltExecution(ARM_Interface::breakpoint);
128 return; 124 return;
129 } 125 }
130 126
@@ -136,7 +132,7 @@ public:
136 132
137 void CallSVC(u32 swi) override { 133 void CallSVC(u32 swi) override {
138 parent.svc_swi = swi; 134 parent.svc_swi = swi;
139 parent.jit.load()->HaltExecution(svc_call); 135 parent.jit.load()->HaltExecution(ARM_Interface::svc_call);
140 } 136 }
141 137
142 void AddTicks(u64 ticks) override { 138 void AddTicks(u64 ticks) override {
@@ -300,35 +296,16 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
300 return std::make_shared<Dynarmic::A64::Jit>(config); 296 return std::make_shared<Dynarmic::A64::Jit>(config);
301} 297}
302 298
303void ARM_Dynarmic_64::Run() { 299Dynarmic::HaltReason ARM_Dynarmic_64::RunJit() {
304 while (true) { 300 return jit.load()->Run();
305 const auto hr = jit.load()->Run(); 301}
306 if (Has(hr, svc_call)) {
307 Kernel::Svc::Call(system, svc_swi);
308 }
309
310 // Check to see if breakpoint is triggered.
311 // Recheck step condition in case stop is no longer desired.
312 Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread();
313 if (Has(hr, breakpoint)) {
314 jit.load()->SetPC(breakpoint_pc);
315 302
316 if (system.GetDebugger().NotifyThreadStopped(current_thread)) { 303Dynarmic::HaltReason ARM_Dynarmic_64::StepJit() {
317 current_thread->RequestSuspend(Kernel::SuspendType::Debug); 304 return jit.load()->Step();
318 } 305}
319 break;
320 }
321 if (ShouldStep()) {
322 // When stepping, this should be the only thread running.
323 ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread));
324 current_thread->RequestSuspend(Kernel::SuspendType::Debug);
325 break;
326 }
327 306
328 if (Has(hr, break_loop) || !uses_wall_clock) { 307u32 ARM_Dynarmic_64::GetSvcNumber() const {
329 break; 308 return svc_swi;
330 }
331 }
332} 309}
333 310
334ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, 311ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_,
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index aa7054e0c..abfbc3c3f 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -39,7 +39,6 @@ public:
39 void SetVectorReg(int index, u128 value) override; 39 void SetVectorReg(int index, u128 value) override;
40 u32 GetPSTATE() const override; 40 u32 GetPSTATE() const override;
41 void SetPSTATE(u32 pstate) override; 41 void SetPSTATE(u32 pstate) override;
42 void Run() override;
43 VAddr GetTlsAddress() const override; 42 VAddr GetTlsAddress() const override;
44 void SetTlsAddress(VAddr address) override; 43 void SetTlsAddress(VAddr address) override;
45 void SetTPIDR_EL0(u64 value) override; 44 void SetTPIDR_EL0(u64 value) override;
@@ -63,6 +62,11 @@ public:
63 62
64 std::vector<BacktraceEntry> GetBacktrace() const override; 63 std::vector<BacktraceEntry> GetBacktrace() const override;
65 64
65protected:
66 Dynarmic::HaltReason RunJit() override;
67 Dynarmic::HaltReason StepJit() override;
68 u32 GetSvcNumber() const override;
69
66private: 70private:
67 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, 71 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table,
68 std::size_t address_space_bits) const; 72 std::size_t address_space_bits) const;
@@ -87,9 +91,6 @@ private:
87 91
88 // SVC callback 92 // SVC callback
89 u32 svc_swi{}; 93 u32 svc_swi{};
90
91 // Debug restart address
92 u64 breakpoint_pc{};
93}; 94};
94 95
95} // namespace Core 96} // namespace Core