From 52cf1418743950fde932e92fcf9655d5c392d9d7 Mon Sep 17 00:00:00 2001 From: Mary Date: Sat, 3 Jun 2023 10:23:51 +0200 Subject: [PATCH] Armeilleure: Fix support for Windows on ARM64 (#5202) * Armeilleure: Fix support for Windows on ARM64 Tested on Windows DevKit 2023. * Address gdkchan's comments --- src/ARMeilleure/Translation/Cache/JitCache.cs | 22 ++++++++++++++++--- .../Translation/Cache/JitCacheInvalidation.cs | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/ARMeilleure/Translation/Cache/JitCache.cs b/src/ARMeilleure/Translation/Cache/JitCache.cs index f496a8e9..daa2eeac 100644 --- a/src/ARMeilleure/Translation/Cache/JitCache.cs +++ b/src/ARMeilleure/Translation/Cache/JitCache.cs @@ -6,10 +6,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Runtime.Versioning; namespace ARMeilleure.Translation.Cache { - static class JitCache + static partial class JitCache { private const int PageSize = 4 * 1024; private const int PageMask = PageSize - 1; @@ -27,6 +28,10 @@ namespace ARMeilleure.Translation.Cache private static readonly object _lock = new object(); private static bool _initialized; + [SupportedOSPlatform("windows")] + [LibraryImport("kernel32.dll", SetLastError = true)] + public static partial IntPtr FlushInstructionCache(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize); + public static void Initialize(IJitMemoryAllocator allocator) { if (_initialized) return; @@ -36,7 +41,11 @@ namespace ARMeilleure.Translation.Cache if (_initialized) return; _jitRegion = new ReservedRegion(allocator, CacheSize); - _jitCacheInvalidator = new JitCacheInvalidation(allocator); + + if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS()) + { + _jitCacheInvalidator = new JitCacheInvalidation(allocator); + } _cacheAllocator = new CacheMemoryAllocator(CacheSize); @@ -77,7 +86,14 @@ namespace ARMeilleure.Translation.Cache Marshal.Copy(code, 0, funcPtr, code.Length); ReprotectAsExecutable(funcOffset, code.Length); - _jitCacheInvalidator.Invalidate(funcPtr, (ulong)code.Length); + if (OperatingSystem.IsWindows() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64) + { + FlushInstructionCache(Process.GetCurrentProcess().Handle, funcPtr, (UIntPtr)code.Length); + } + else + { + _jitCacheInvalidator?.Invalidate(funcPtr, (ulong)code.Length); + } } Add(funcOffset, code.Length, func.UnwindInfo); diff --git a/src/ARMeilleure/Translation/Cache/JitCacheInvalidation.cs b/src/ARMeilleure/Translation/Cache/JitCacheInvalidation.cs index ec2ae73b..57f7bf12 100644 --- a/src/ARMeilleure/Translation/Cache/JitCacheInvalidation.cs +++ b/src/ARMeilleure/Translation/Cache/JitCacheInvalidation.cs @@ -47,8 +47,8 @@ namespace ARMeilleure.Translation.Cache public JitCacheInvalidation(IJitMemoryAllocator allocator) { - // On macOS, a different path is used to write to the JIT cache, which does the invalidation. - if (!OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64) + // On macOS and Windows, a different path is used to write to the JIT cache, which does the invalidation. + if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64) { ulong size = (ulong)_invalidationCode.Length * sizeof(int); ulong mask = (ulong)ReservedRegion.DefaultGranularity - 1;