/ src / Ryujinx.Cpu / AppleHv / HvVcpu.cs
HvVcpu.cs
 1  using System.Diagnostics;
 2  using System.Runtime.Versioning;
 3  
 4  namespace Ryujinx.Cpu.AppleHv
 5  {
 6      [SupportedOSPlatform("macos")]
 7      unsafe class HvVcpu
 8      {
 9          private const ulong InterruptIntervalNs = 16 * 1000000; // 16 ms
10  
11          private static ulong _interruptTimeDeltaTicks = 0;
12  
13          public readonly ulong Handle;
14          public readonly HvVcpuExit* ExitInfo;
15          public readonly IHvExecutionContext ShadowContext;
16          public readonly IHvExecutionContext NativeContext;
17          public readonly bool IsEphemeral;
18  
19          public HvVcpu(
20              ulong handle,
21              HvVcpuExit* exitInfo,
22              IHvExecutionContext shadowContext,
23              IHvExecutionContext nativeContext,
24              bool isEphemeral)
25          {
26              Handle = handle;
27              ExitInfo = exitInfo;
28              ShadowContext = shadowContext;
29              NativeContext = nativeContext;
30              IsEphemeral = isEphemeral;
31          }
32  
33          public void EnableAndUpdateVTimer()
34          {
35              // We need to ensure interrupts will be serviced,
36              // and for that we set up the VTime to trigger an interrupt at fixed intervals.
37  
38              ulong deltaTicks = _interruptTimeDeltaTicks;
39  
40              if (deltaTicks == 0)
41              {
42                  // Calculate our time delta in ticks based on the current clock frequency.
43  
44                  int result = TimeApi.mach_timebase_info(out var timeBaseInfo);
45  
46                  Debug.Assert(result == 0);
47  
48                  deltaTicks = ((InterruptIntervalNs * timeBaseInfo.Denom) + (timeBaseInfo.Numer - 1)) / timeBaseInfo.Numer;
49                  _interruptTimeDeltaTicks = deltaTicks;
50              }
51  
52              HvApi.hv_vcpu_set_sys_reg(Handle, HvSysReg.CNTV_CTL_EL0, 1).ThrowOnError();
53              HvApi.hv_vcpu_set_sys_reg(Handle, HvSysReg.CNTV_CVAL_EL0, TimeApi.mach_absolute_time() + deltaTicks).ThrowOnError();
54          }
55      }
56  }