HvVcpu.cs 1.9 KB

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