diff options
Diffstat (limited to 'src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs')
| -rw-r--r-- | src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs b/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs index 2c9afdc4..fc2b76d1 100644 --- a/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs +++ b/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs @@ -2,9 +2,12 @@ using ARMeilleure.State; using Ryujinx.Cpu.AppleHv.Arm; using Ryujinx.Memory.Tracking; using System; +using System.Runtime.Versioning; +using System.Threading; namespace Ryujinx.Cpu.AppleHv { + [SupportedOSPlatform("macos")] class HvExecutionContext : IExecutionContext { /// <inheritdoc/> @@ -67,6 +70,8 @@ namespace Ryujinx.Cpu.AppleHv private readonly ExceptionCallbacks _exceptionCallbacks; + private int _interruptRequested; + public HvExecutionContext(ICounter counter, ExceptionCallbacks exceptionCallbacks) { _counter = counter; @@ -111,7 +116,15 @@ namespace Ryujinx.Cpu.AppleHv /// <inheritdoc/> public void RequestInterrupt() { - _impl.RequestInterrupt(); + if (Interlocked.Exchange(ref _interruptRequested, 1) == 0 && _impl is HvExecutionContextVcpu impl) + { + impl.RequestInterrupt(); + } + } + + private bool GetAndClearInterruptRequested() + { + return Interlocked.Exchange(ref _interruptRequested, 0) != 0; } /// <inheritdoc/> @@ -131,9 +144,9 @@ namespace Ryujinx.Cpu.AppleHv { HvApi.hv_vcpu_run(vcpu.Handle).ThrowOnError(); - uint reason = vcpu.ExitInfo->Reason; + HvExitReason reason = vcpu.ExitInfo->Reason; - if (reason == 1) + if (reason == HvExitReason.Exception) { uint hvEsr = (uint)vcpu.ExitInfo->Exception.Syndrome; ExceptionClass hvEc = (ExceptionClass)(hvEsr >> 26); @@ -146,14 +159,22 @@ namespace Ryujinx.Cpu.AppleHv address = SynchronousException(memoryManager, ref vcpu); HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError(); } - else if (reason == 0) + else if (reason == HvExitReason.Canceled || reason == HvExitReason.VTimerActivated) { - if (_impl.GetAndClearInterruptRequested()) + if (GetAndClearInterruptRequested()) { ReturnToPool(vcpu); InterruptHandler(); vcpu = RentFromPool(memoryManager.AddressSpace, vcpu); } + + if (reason == HvExitReason.VTimerActivated) + { + vcpu.EnableAndUpdateVTimer(); + + // Unmask VTimer interrupts. + HvApi.hv_vcpu_set_vtimer_mask(vcpu.Handle, false).ThrowOnError(); + } } else { |
