aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Cpu/AppleHv
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-11-07 13:24:10 -0300
committerGitHub <noreply@github.com>2023-11-07 13:24:10 -0300
commit815819767c5794624e3e7bc2bebcabe8ea4de0f6 (patch)
treea57b27ee8d43f243e7085dfbba16a388d13f9432 /src/Ryujinx.Cpu/AppleHv
parent623604c39186901fd64c8e04e9aa959d5c825529 (diff)
Force all exclusive memory accesses to be ordered on AppleHv (#5898)
* Implement reprotect method on virtual memory manager (currently stubbed) * Force all exclusive memory accesses to be ordered on AppleHv * Format whitespace * Fix test build * Fix comment copy/paste * Fix wrong bit for isLoad * Update src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs Co-authored-by: riperiperi <rhy3756547@hotmail.com> --------- Co-authored-by: riperiperi <rhy3756547@hotmail.com>
Diffstat (limited to 'src/Ryujinx.Cpu/AppleHv')
-rw-r--r--src/Ryujinx.Cpu/AppleHv/HvCodePatcher.cs62
-rw-r--r--src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs33
2 files changed, 80 insertions, 15 deletions
diff --git a/src/Ryujinx.Cpu/AppleHv/HvCodePatcher.cs b/src/Ryujinx.Cpu/AppleHv/HvCodePatcher.cs
new file mode 100644
index 00000000..876597b7
--- /dev/null
+++ b/src/Ryujinx.Cpu/AppleHv/HvCodePatcher.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+
+namespace Ryujinx.Cpu.AppleHv
+{
+ static class HvCodePatcher
+ {
+ private const uint XMask = 0x3f808000u;
+ private const uint XValue = 0x8000000u;
+
+ private const uint ZrIndex = 31u;
+
+ public static void RewriteUnorderedExclusiveInstructions(Span<byte> code)
+ {
+ Span<uint> codeUint = MemoryMarshal.Cast<byte, uint>(code);
+ Span<Vector128<uint>> codeVector = MemoryMarshal.Cast<byte, Vector128<uint>>(code);
+
+ Vector128<uint> mask = Vector128.Create(XMask);
+ Vector128<uint> value = Vector128.Create(XValue);
+
+ for (int index = 0; index < codeVector.Length; index++)
+ {
+ Vector128<uint> v = codeVector[index];
+
+ if (Vector128.EqualsAny(Vector128.BitwiseAnd(v, mask), value))
+ {
+ int baseIndex = index * 4;
+
+ for (int instIndex = baseIndex; instIndex < baseIndex + 4; instIndex++)
+ {
+ ref uint inst = ref codeUint[instIndex];
+
+ if ((inst & XMask) != XValue)
+ {
+ continue;
+ }
+
+ bool isPair = (inst & (1u << 21)) != 0;
+ bool isLoad = (inst & (1u << 22)) != 0;
+
+ uint rt2 = (inst >> 10) & 0x1fu;
+ uint rs = (inst >> 16) & 0x1fu;
+
+ if (isLoad && rs != ZrIndex)
+ {
+ continue;
+ }
+
+ if (!isPair && rt2 != ZrIndex)
+ {
+ continue;
+ }
+
+ // Set the ordered flag.
+ inst |= 1u << 15;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs b/src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs
index d5ce817a..947c3710 100644
--- a/src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs
+++ b/src/Ryujinx.Cpu/AppleHv/HvMemoryManager.cs
@@ -128,21 +128,6 @@ namespace Ryujinx.Cpu.AppleHv
}
}
-#pragma warning disable IDE0051 // Remove unused private member
- /// <summary>
- /// Ensures the combination of virtual address and size is part of the addressable space and fully mapped.
- /// </summary>
- /// <param name="va">Virtual address of the range</param>
- /// <param name="size">Size of the range in bytes</param>
- private void AssertMapped(ulong va, ulong size)
- {
- if (!ValidateAddressAndSize(va, size) || !IsRangeMappedImpl(va, size))
- {
- throw new InvalidMemoryRegionException($"Not mapped: va=0x{va:X16}, size=0x{size:X16}");
- }
- }
-#pragma warning restore IDE0051
-
/// <inheritdoc/>
public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
{
@@ -737,6 +722,24 @@ namespace Ryujinx.Cpu.AppleHv
}
/// <inheritdoc/>
+ public void Reprotect(ulong va, ulong size, MemoryPermission protection)
+ {
+ if (protection.HasFlag(MemoryPermission.Execute))
+ {
+ // Some applications use unordered exclusive memory access instructions
+ // where it is not valid to do so, leading to memory re-ordering that
+ // makes the code behave incorrectly on some CPUs.
+ // To work around this, we force all such accesses to be ordered.
+
+ using WritableRegion writableRegion = GetWritableRegion(va, (int)size);
+
+ HvCodePatcher.RewriteUnorderedExclusiveInstructions(writableRegion.Memory.Span);
+ }
+
+ // TODO
+ }
+
+ /// <inheritdoc/>
public void TrackingReprotect(ulong va, ulong size, MemoryPermission protection)
{
// Protection is inverted on software pages, since the default value is 0.