aboutsummaryrefslogtreecommitdiff
path: root/src/ARMeilleure
diff options
context:
space:
mode:
Diffstat (limited to 'src/ARMeilleure')
-rw-r--r--src/ARMeilleure/Memory/IJitMemoryAllocator.cs2
-rw-r--r--src/ARMeilleure/Memory/MemoryManagerType.cs2
-rw-r--r--src/ARMeilleure/Signal/NativeSignalHandlerGenerator.cs (renamed from src/ARMeilleure/Signal/NativeSignalHandler.cs)199
-rw-r--r--src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs83
-rw-r--r--src/ARMeilleure/Signal/WindowsPartialUnmapHandler.cs37
-rw-r--r--src/ARMeilleure/Signal/WindowsSignalHandlerRegistration.cs44
-rw-r--r--src/ARMeilleure/Translation/Translator.cs5
7 files changed, 40 insertions, 332 deletions
diff --git a/src/ARMeilleure/Memory/IJitMemoryAllocator.cs b/src/ARMeilleure/Memory/IJitMemoryAllocator.cs
index 171bfd2f..ff64bf13 100644
--- a/src/ARMeilleure/Memory/IJitMemoryAllocator.cs
+++ b/src/ARMeilleure/Memory/IJitMemoryAllocator.cs
@@ -4,7 +4,5 @@ namespace ARMeilleure.Memory
{
IJitMemoryBlock Allocate(ulong size);
IJitMemoryBlock Reserve(ulong size);
-
- ulong GetPageSize();
}
}
diff --git a/src/ARMeilleure/Memory/MemoryManagerType.cs b/src/ARMeilleure/Memory/MemoryManagerType.cs
index 1e656ba2..b1cdbb06 100644
--- a/src/ARMeilleure/Memory/MemoryManagerType.cs
+++ b/src/ARMeilleure/Memory/MemoryManagerType.cs
@@ -31,7 +31,7 @@ namespace ARMeilleure.Memory
HostMappedUnsafe,
}
- static class MemoryManagerTypeExtensions
+ public static class MemoryManagerTypeExtensions
{
public static bool IsHostMapped(this MemoryManagerType type)
{
diff --git a/src/ARMeilleure/Signal/NativeSignalHandler.cs b/src/ARMeilleure/Signal/NativeSignalHandlerGenerator.cs
index 31ec16cb..c5e708e1 100644
--- a/src/ARMeilleure/Signal/NativeSignalHandler.cs
+++ b/src/ARMeilleure/Signal/NativeSignalHandlerGenerator.cs
@@ -1,63 +1,14 @@
using ARMeilleure.IntermediateRepresentation;
-using ARMeilleure.Memory;
using ARMeilleure.Translation;
-using ARMeilleure.Translation.Cache;
using System;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal
{
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- struct SignalHandlerRange
+ public static class NativeSignalHandlerGenerator
{
- public int IsActive;
- public nuint RangeAddress;
- public nuint RangeEndAddress;
- public IntPtr ActionPointer;
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- struct SignalHandlerConfig
- {
- /// <summary>
- /// The byte offset of the faulting address in the SigInfo or ExceptionRecord struct.
- /// </summary>
- public int StructAddressOffset;
-
- /// <summary>
- /// The byte offset of the write flag in the SigInfo or ExceptionRecord struct.
- /// </summary>
- public int StructWriteOffset;
-
- /// <summary>
- /// The sigaction handler that was registered before this one. (unix only)
- /// </summary>
- public nuint UnixOldSigaction;
-
- /// <summary>
- /// The type of the previous sigaction. True for the 3 argument variant. (unix only)
- /// </summary>
- public int UnixOldSigaction3Arg;
-
- public SignalHandlerRange Range0;
- public SignalHandlerRange Range1;
- public SignalHandlerRange Range2;
- public SignalHandlerRange Range3;
- public SignalHandlerRange Range4;
- public SignalHandlerRange Range5;
- public SignalHandlerRange Range6;
- public SignalHandlerRange Range7;
- }
-
- public static class NativeSignalHandler
- {
- private delegate void UnixExceptionHandler(int sig, IntPtr info, IntPtr ucontext);
- [UnmanagedFunctionPointer(CallingConvention.Winapi)]
- private delegate int VectoredExceptionHandler(IntPtr exceptionInfo);
-
- private const int MaxTrackedRanges = 8;
+ public const int MaxTrackedRanges = 8;
private const int StructAddressOffset = 0;
private const int StructWriteOffset = 4;
@@ -70,125 +21,10 @@ namespace ARMeilleure.Signal
private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
- private static ulong _pageSize;
- private static ulong _pageMask;
-
- private static readonly IntPtr _handlerConfig;
- private static IntPtr _signalHandlerPtr;
- private static IntPtr _signalHandlerHandle;
-
- private static readonly object _lock = new();
- private static bool _initialized;
-
- static NativeSignalHandler()
- {
- _handlerConfig = Marshal.AllocHGlobal(Unsafe.SizeOf<SignalHandlerConfig>());
- ref SignalHandlerConfig config = ref GetConfigRef();
-
- config = new SignalHandlerConfig();
- }
-
- public static void Initialize(IJitMemoryAllocator allocator)
- {
- JitCache.Initialize(allocator);
- }
-
- public static void InitializeSignalHandler(ulong pageSize, Func<IntPtr, IntPtr, IntPtr> customSignalHandlerFactory = null)
+ private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite, int rangeStructSize, ulong pageSize)
{
- if (_initialized)
- {
- return;
- }
-
- lock (_lock)
- {
- if (_initialized)
- {
- return;
- }
-
- _pageSize = pageSize;
- _pageMask = pageSize - 1;
-
- ref SignalHandlerConfig config = ref GetConfigRef();
-
- if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
- {
- _signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
-
- if (customSignalHandlerFactory != null)
- {
- _signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr);
- }
-
- var old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
-
- config.UnixOldSigaction = (nuint)(ulong)old.sa_handler;
- config.UnixOldSigaction3Arg = old.sa_flags & 4;
- }
- else
- {
- config.StructAddressOffset = 40; // ExceptionInformation1
- config.StructWriteOffset = 32; // ExceptionInformation0
-
- _signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateWindowsSignalHandler(_handlerConfig));
-
- if (customSignalHandlerFactory != null)
- {
- _signalHandlerPtr = customSignalHandlerFactory(IntPtr.Zero, _signalHandlerPtr);
- }
+ ulong pageMask = pageSize - 1;
- _signalHandlerHandle = WindowsSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
- }
-
- _initialized = true;
- }
- }
-
- private static unsafe ref SignalHandlerConfig GetConfigRef()
- {
- return ref Unsafe.AsRef<SignalHandlerConfig>((void*)_handlerConfig);
- }
-
- public static unsafe bool AddTrackedRegion(nuint address, nuint endAddress, IntPtr action)
- {
- var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
-
- for (int i = 0; i < MaxTrackedRanges; i++)
- {
- if (ranges[i].IsActive == 0)
- {
- ranges[i].RangeAddress = address;
- ranges[i].RangeEndAddress = endAddress;
- ranges[i].ActionPointer = action;
- ranges[i].IsActive = 1;
-
- return true;
- }
- }
-
- return false;
- }
-
- public static unsafe bool RemoveTrackedRegion(nuint address)
- {
- var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
-
- for (int i = 0; i < MaxTrackedRanges; i++)
- {
- if (ranges[i].IsActive == 1 && ranges[i].RangeAddress == address)
- {
- ranges[i].IsActive = 0;
-
- return true;
- }
- }
-
- return false;
- }
-
- private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite)
- {
Operand inRegionLocal = context.AllocateLocal(OperandType.I32);
context.Copy(inRegionLocal, Const(0));
@@ -196,7 +32,7 @@ namespace ARMeilleure.Signal
for (int i = 0; i < MaxTrackedRanges; i++)
{
- ulong rangeBaseOffset = (ulong)(RangeOffset + i * Unsafe.SizeOf<SignalHandlerRange>());
+ ulong rangeBaseOffset = (ulong)(RangeOffset + i * rangeStructSize);
Operand nextLabel = Label();
@@ -210,13 +46,12 @@ namespace ARMeilleure.Signal
// Is the fault address within this tracked region?
Operand inRange = context.BitwiseAnd(
context.ICompare(faultAddress, rangeAddress, Comparison.GreaterOrEqualUI),
- context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI)
- );
+ context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI));
// Only call tracking if in range.
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
- Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~_pageMask));
+ Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~pageMask));
// Call the tracking action, with the pointer's relative offset to the base address.
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
@@ -227,7 +62,7 @@ namespace ARMeilleure.Signal
// Tracking action should be non-null to call it, otherwise assume false return.
context.BranchIfFalse(skipActionLabel, trackingActionPtr);
- Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(_pageSize), isWrite);
+ Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(pageSize), isWrite);
context.Copy(inRegionLocal, result);
context.MarkLabel(skipActionLabel);
@@ -269,8 +104,7 @@ namespace ARMeilleure.Signal
Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(EsrOffset)));
return context.BitwiseAnd(esr, Const(0x40ul));
}
-
- if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
+ else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
const ulong ErrOffset = 4; // __es.__err
Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(ErrOffset)));
@@ -310,8 +144,7 @@ namespace ARMeilleure.Signal
Operand esr = context.Load(OperandType.I64, context.Add(auxPtr, Const(8ul)));
return context.BitwiseAnd(esr, Const(0x40ul));
}
-
- if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
+ else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
const int ErrOffset = 192; // uc_mcontext.gregs[REG_ERR]
Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(ErrOffset)));
@@ -322,7 +155,7 @@ namespace ARMeilleure.Signal
throw new PlatformNotSupportedException();
}
- private static UnixExceptionHandler GenerateUnixSignalHandler(IntPtr signalStructPtr)
+ public static byte[] GenerateUnixSignalHandler(IntPtr signalStructPtr, int rangeStructSize, ulong pageSize)
{
EmitterContext context = new();
@@ -335,7 +168,7 @@ namespace ARMeilleure.Signal
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
- Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
+ Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite, rangeStructSize, pageSize);
Operand endLabel = Label();
@@ -367,10 +200,10 @@ namespace ARMeilleure.Signal
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
- return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<UnixExceptionHandler>();
+ return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
}
- private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr)
+ public static byte[] GenerateWindowsSignalHandler(IntPtr signalStructPtr, int rangeStructSize, ulong pageSize)
{
EmitterContext context = new();
@@ -399,7 +232,7 @@ namespace ARMeilleure.Signal
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
- Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
+ Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite, rangeStructSize, pageSize);
Operand endLabel = Label();
@@ -421,7 +254,7 @@ namespace ARMeilleure.Signal
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
- return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<VectoredExceptionHandler>();
+ return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
}
}
}
diff --git a/src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs b/src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs
deleted file mode 100644
index 70e9f220..00000000
--- a/src/ARMeilleure/Signal/UnixSignalHandlerRegistration.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace ARMeilleure.Signal
-{
- static partial class UnixSignalHandlerRegistration
- {
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public unsafe struct SigSet
- {
- fixed long sa_mask[16];
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct SigAction
- {
- public IntPtr sa_handler;
- public SigSet sa_mask;
- public int sa_flags;
- public IntPtr sa_restorer;
- }
-
- private const int SIGSEGV = 11;
- private const int SIGBUS = 10;
- private const int SA_SIGINFO = 0x00000004;
-
- [LibraryImport("libc", SetLastError = true)]
- private static partial int sigaction(int signum, ref SigAction sigAction, out SigAction oldAction);
-
- [LibraryImport("libc", SetLastError = true)]
- private static partial int sigaction(int signum, IntPtr sigAction, out SigAction oldAction);
-
- [LibraryImport("libc", SetLastError = true)]
- private static partial int sigemptyset(ref SigSet set);
-
- public static SigAction GetSegfaultExceptionHandler()
- {
- int result = sigaction(SIGSEGV, IntPtr.Zero, out SigAction old);
-
- if (result != 0)
- {
- throw new InvalidOperationException($"Could not get SIGSEGV sigaction. Error: {result}");
- }
-
- return old;
- }
-
- public static SigAction RegisterExceptionHandler(IntPtr action)
- {
- SigAction sig = new()
- {
- sa_handler = action,
- sa_flags = SA_SIGINFO,
- };
-
- sigemptyset(ref sig.sa_mask);
-
- int result = sigaction(SIGSEGV, ref sig, out SigAction old);
-
- if (result != 0)
- {
- throw new InvalidOperationException($"Could not register SIGSEGV sigaction. Error: {result}");
- }
-
- if (OperatingSystem.IsMacOS())
- {
- result = sigaction(SIGBUS, ref sig, out _);
-
- if (result != 0)
- {
- throw new InvalidOperationException($"Could not register SIGBUS sigaction. Error: {result}");
- }
- }
-
- return old;
- }
-
- public static bool RestoreExceptionHandler(SigAction oldAction)
- {
- return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
- }
- }
-}
diff --git a/src/ARMeilleure/Signal/WindowsPartialUnmapHandler.cs b/src/ARMeilleure/Signal/WindowsPartialUnmapHandler.cs
index 27a9ea83..3bf6a449 100644
--- a/src/ARMeilleure/Signal/WindowsPartialUnmapHandler.cs
+++ b/src/ARMeilleure/Signal/WindowsPartialUnmapHandler.cs
@@ -2,7 +2,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using Ryujinx.Common.Memory.PartialUnmaps;
using System;
-
+using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal
@@ -10,8 +10,28 @@ namespace ARMeilleure.Signal
/// <summary>
/// Methods to handle signals caused by partial unmaps. See the structs for C# implementations of the methods.
/// </summary>
- internal static class WindowsPartialUnmapHandler
+ internal static partial class WindowsPartialUnmapHandler
{
+ [LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
+ private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
+
+ [LibraryImport("kernel32.dll", SetLastError = true)]
+ private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
+
+ private static IntPtr _getCurrentThreadIdPtr;
+
+ public static IntPtr GetCurrentThreadIdFunc()
+ {
+ if (_getCurrentThreadIdPtr == IntPtr.Zero)
+ {
+ IntPtr handle = LoadLibrary("kernel32.dll");
+
+ _getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
+ }
+
+ return _getCurrentThreadIdPtr;
+ }
+
public static Operand EmitRetryFromAccessViolation(EmitterContext context)
{
IntPtr partialRemapStatePtr = PartialUnmapState.GlobalState;
@@ -20,7 +40,7 @@ namespace ARMeilleure.Signal
// Get the lock first.
EmitNativeReaderLockAcquire(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
- IntPtr getCurrentThreadId = WindowsSignalHandlerRegistration.GetCurrentThreadIdFunc();
+ IntPtr getCurrentThreadId = GetCurrentThreadIdFunc();
Operand threadId = context.Call(Const((ulong)getCurrentThreadId), OperandType.I32);
Operand threadIndex = EmitThreadLocalMapIntGetOrReserve(context, localCountsPtr, threadId, Const(0));
@@ -137,17 +157,6 @@ namespace ARMeilleure.Signal
return context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset));
}
-#pragma warning disable IDE0051 // Remove unused private member
- private static void EmitThreadLocalMapIntRelease(EmitterContext context, IntPtr threadLocalMapPtr, Operand threadId, Operand index)
- {
- Operand offset = context.Multiply(index, Const(sizeof(int)));
- Operand idsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
- Operand idPtr = context.Add(idsPtr, context.SignExtend32(OperandType.I64, offset));
-
- context.CompareAndSwap(idPtr, threadId, Const(0));
- }
-#pragma warning restore IDE0051
-
private static void EmitAtomicAddI32(EmitterContext context, Operand ptr, Operand additive)
{
Operand loop = Label();
diff --git a/src/ARMeilleure/Signal/WindowsSignalHandlerRegistration.cs b/src/ARMeilleure/Signal/WindowsSignalHandlerRegistration.cs
deleted file mode 100644
index 5444da0c..00000000
--- a/src/ARMeilleure/Signal/WindowsSignalHandlerRegistration.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-
-namespace ARMeilleure.Signal
-{
- unsafe partial class WindowsSignalHandlerRegistration
- {
- [LibraryImport("kernel32.dll")]
- private static partial IntPtr AddVectoredExceptionHandler(uint first, IntPtr handler);
-
- [LibraryImport("kernel32.dll")]
- private static partial ulong RemoveVectoredExceptionHandler(IntPtr handle);
-
- [LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
- private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
-
- [LibraryImport("kernel32.dll", SetLastError = true)]
- private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
-
- private static IntPtr _getCurrentThreadIdPtr;
-
- public static IntPtr RegisterExceptionHandler(IntPtr action)
- {
- return AddVectoredExceptionHandler(1, action);
- }
-
- public static bool RemoveExceptionHandler(IntPtr handle)
- {
- return RemoveVectoredExceptionHandler(handle) != 0;
- }
-
- public static IntPtr GetCurrentThreadIdFunc()
- {
- if (_getCurrentThreadIdPtr == IntPtr.Zero)
- {
- IntPtr handle = LoadLibrary("kernel32.dll");
-
- _getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
- }
-
- return _getCurrentThreadIdPtr;
- }
- }
-}
diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs
index dc18038b..7f6a25b0 100644
--- a/src/ARMeilleure/Translation/Translator.cs
+++ b/src/ARMeilleure/Translation/Translator.cs
@@ -79,11 +79,6 @@ namespace ARMeilleure.Translation
Stubs = new TranslatorStubs(this);
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
-
- if (memory.Type.IsHostMapped())
- {
- NativeSignalHandler.InitializeSignalHandler(allocator.GetPageSize());
- }
}
public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled)