mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 10:44:49 +01:00 
			
		
		
		
	Merge pull request #8148 from merryhime/interrupts
dynarmic: Better interrupts
This commit is contained in:
		
						commit
						50192eb4ad
					
				
							
								
								
									
										2
									
								
								externals/dynarmic
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								externals/dynarmic
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | |||||||
| Subproject commit af2d50288fc537201014c4230bb55ab9018a7438 | Subproject commit 644172477eaf0d822178cb7e96c62b75caa96573 | ||||||
| @ -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; | ||||||
|  | |||||||
| @ -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; |             Kernel::Svc::Call(system, svc_swi); | ||||||
|         } |         } | ||||||
|         svc_called = false; |         if (Has(hr, break_loop)) { | ||||||
|         Kernel::Svc::Call(system, svc_swi); |  | ||||||
|         if (shutdown) { |  | ||||||
|             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() { | ||||||
|  | |||||||
| @ -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
 | ||||||
|  | |||||||
| @ -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; |             Kernel::Svc::Call(system, svc_swi); | ||||||
|         } |         } | ||||||
|         svc_called = false; |         if (Has(hr, break_loop)) { | ||||||
|         Kernel::Svc::Call(system, svc_swi); |  | ||||||
|         if (shutdown) { |  | ||||||
|             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() { | ||||||
|  | |||||||
| @ -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
 | ||||||
|  | |||||||
| @ -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(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user