aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs')
-rw-r--r--src/Ryujinx.Cpu/AppleHv/HvExecutionContext.cs31
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
{