Merge pull request #8148 from merryhime/interrupts

dynarmic: Better interrupts
This commit is contained in:
Fernando S 2022-04-07 16:21:41 +02:00 committed by GitHub
commit 50192eb4ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 43 additions and 46 deletions

2
externals/dynarmic vendored

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

View file

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

View file

@ -25,6 +25,9 @@ namespace Core {
using namespace Common::Literals; 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 { class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
public: public:
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
@ -84,15 +87,13 @@ public:
} }
void CallSVC(u32 swi) override { void CallSVC(u32 swi) override {
parent.svc_called = true;
parent.svc_swi = swi; parent.svc_swi = swi;
parent.jit->HaltExecution(); parent.jit->HaltExecution(svc_call);
} }
void AddTicks(u64 ticks) override { void AddTicks(u64 ticks) override {
if (parent.uses_wall_clock) { ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
return;
}
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a // 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 // 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 // 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 { u64 GetTicksRemaining() override {
if (parent.uses_wall_clock) { ASSERT_MSG(!parent.uses_wall_clock, "This should never happen - dynarmic ticking disabled");
if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) {
return minimum_run_cycles;
}
return 0U;
}
return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); 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 // Timing
config.wall_clock_cntpct = uses_wall_clock; config.wall_clock_cntpct = uses_wall_clock;
config.enable_cycle_counting = !uses_wall_clock;
// Code cache size // Code cache size
config.code_cache_size = 512_MiB; 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() { void ARM_Dynarmic_32::Run() {
while (true) { while (true) {
jit->Run(); const auto hr = jit->Run();
if (!svc_called) { if (Has(hr, svc_call)) {
break;
}
svc_called = false;
Kernel::Svc::Call(system, svc_swi); Kernel::Svc::Call(system, svc_swi);
if (shutdown) { }
if (Has(hr, break_loop)) {
break; break;
} }
} }
@ -322,8 +318,11 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
} }
void ARM_Dynarmic_32::PrepareReschedule() { void ARM_Dynarmic_32::PrepareReschedule() {
jit->HaltExecution(); jit->HaltExecution(break_loop);
shutdown = true; }
void ARM_Dynarmic_32::SignalInterrupt() {
jit->HaltExecution(break_loop);
} }
void ARM_Dynarmic_32::ClearInstructionCache() { void ARM_Dynarmic_32::ClearInstructionCache() {

View file

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

View file

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

View file

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

View file

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