aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Cpu/AppleHv/HvVcpu.cs
blob: ee91c478b0b4bab4d09b3d547eb52314450f821d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System.Diagnostics;
using System.Runtime.Versioning;

namespace Ryujinx.Cpu.AppleHv
{
    [SupportedOSPlatform("macos")]
    unsafe class HvVcpu
    {
        private const ulong InterruptIntervalNs = 16 * 1000000; // 16 ms

        private static ulong _interruptTimeDeltaTicks = 0;

        public readonly ulong Handle;
        public readonly HvVcpuExit* ExitInfo;
        public readonly IHvExecutionContext ShadowContext;
        public readonly IHvExecutionContext NativeContext;
        public readonly bool IsEphemeral;

        public HvVcpu(
            ulong handle,
            HvVcpuExit* exitInfo,
            IHvExecutionContext shadowContext,
            IHvExecutionContext nativeContext,
            bool isEphemeral)
        {
            Handle = handle;
            ExitInfo = exitInfo;
            ShadowContext = shadowContext;
            NativeContext = nativeContext;
            IsEphemeral = isEphemeral;
        }

        public void EnableAndUpdateVTimer()
        {
            // We need to ensure interrupts will be serviced,
            // and for that we set up the VTime to trigger an interrupt at fixed intervals.

            ulong deltaTicks = _interruptTimeDeltaTicks;

            if (deltaTicks == 0)
            {
                // Calculate our time delta in ticks based on the current clock frequency.

                int result = TimeApi.mach_timebase_info(out var timeBaseInfo);

                Debug.Assert(result == 0);

                deltaTicks = ((InterruptIntervalNs * timeBaseInfo.Denom) + (timeBaseInfo.Numer - 1)) / timeBaseInfo.Numer;
                _interruptTimeDeltaTicks = deltaTicks;
            }

            HvApi.hv_vcpu_set_sys_reg(Handle, HvSysReg.CNTV_CTL_EL0, 1).ThrowOnError();
            HvApi.hv_vcpu_set_sys_reg(Handle, HvSysReg.CNTV_CVAL_EL0, TimeApi.mach_absolute_time() + deltaTicks).ThrowOnError();
        }
    }
}