JitCacheInvalidation.cs 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using ARMeilleure.Memory;
  2. using System;
  3. using System.Runtime.InteropServices;
  4. namespace ARMeilleure.Translation.Cache
  5. {
  6. class JitCacheInvalidation
  7. {
  8. private static int[] _invalidationCode = new int[]
  9. {
  10. unchecked((int)0xd53b0022), // mrs x2, ctr_el0
  11. unchecked((int)0xd3504c44), // ubfx x4, x2, #16, #4
  12. unchecked((int)0x52800083), // mov w3, #0x4
  13. unchecked((int)0x12000c45), // and w5, w2, #0xf
  14. unchecked((int)0x1ac42064), // lsl w4, w3, w4
  15. unchecked((int)0x51000482), // sub w2, w4, #0x1
  16. unchecked((int)0x8a220002), // bic x2, x0, x2
  17. unchecked((int)0x1ac52063), // lsl w3, w3, w5
  18. unchecked((int)0xeb01005f), // cmp x2, x1
  19. unchecked((int)0x93407c84), // sxtw x4, w4
  20. unchecked((int)0x540000a2), // b.cs 3c <do_ic_clear>
  21. unchecked((int)0xd50b7b22), // dc cvau, x2
  22. unchecked((int)0x8b040042), // add x2, x2, x4
  23. unchecked((int)0xeb02003f), // cmp x1, x2
  24. unchecked((int)0x54ffffa8), // b.hi 2c <dc_clear_loop>
  25. unchecked((int)0xd5033b9f), // dsb ish
  26. unchecked((int)0x51000462), // sub w2, w3, #0x1
  27. unchecked((int)0x93407c63), // sxtw x3, w3
  28. unchecked((int)0x8a220000), // bic x0, x0, x2
  29. unchecked((int)0xeb00003f), // cmp x1, x0
  30. unchecked((int)0x540000a9), // b.ls 64 <exit>
  31. unchecked((int)0xd50b7520), // ic ivau, x0
  32. unchecked((int)0x8b030000), // add x0, x0, x3
  33. unchecked((int)0xeb00003f), // cmp x1, x0
  34. unchecked((int)0x54ffffa8), // b.hi 54 <ic_clear_loop>
  35. unchecked((int)0xd5033b9f), // dsb ish
  36. unchecked((int)0xd5033fdf), // isb
  37. unchecked((int)0xd65f03c0), // ret
  38. };
  39. private delegate void InvalidateCache(ulong start, ulong end);
  40. private InvalidateCache _invalidateCache;
  41. private ReservedRegion _invalidateCacheCodeRegion;
  42. private readonly bool _needsInvalidation;
  43. public JitCacheInvalidation(IJitMemoryAllocator allocator)
  44. {
  45. // On macOS, a different path is used to write to the JIT cache, which does the invalidation.
  46. if (!OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
  47. {
  48. ulong size = (ulong)_invalidationCode.Length * sizeof(int);
  49. ulong mask = (ulong)ReservedRegion.DefaultGranularity - 1;
  50. size = (size + mask) & ~mask;
  51. _invalidateCacheCodeRegion = new ReservedRegion(allocator, size);
  52. _invalidateCacheCodeRegion.ExpandIfNeeded(size);
  53. Marshal.Copy(_invalidationCode, 0, _invalidateCacheCodeRegion.Pointer, _invalidationCode.Length);
  54. _invalidateCacheCodeRegion.Block.MapAsRx(0, size);
  55. _invalidateCache = Marshal.GetDelegateForFunctionPointer<InvalidateCache>(_invalidateCacheCodeRegion.Pointer);
  56. _needsInvalidation = true;
  57. }
  58. }
  59. public void Invalidate(IntPtr basePointer, ulong size)
  60. {
  61. if (_needsInvalidation)
  62. {
  63. _invalidateCache((ulong)basePointer, (ulong)basePointer + size);
  64. }
  65. }
  66. }
  67. }