From 6f28c4abadfead6fb5146caa5775dba1641bd79f Mon Sep 17 00:00:00 2001
From: Mary <mary@mary.zone>
Date: Wed, 14 Jun 2023 18:02:41 +0200
Subject: test: Make tests runnable on system without 4KiB page size (#5184)

* ARMeilleure: Do not hardcode 4KiB page size in JitCache

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Memory.Tests

Fix running tests on Asahi Linux with 16KiB pages.

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Cpu

Fix running tests on Asahi Linux.

Test runner still crash when trying to run all test suite.

* test: Do not hardcode page size to 4KiB for Ryujinx.Tests.Cpu

Fix somecrashes on Asahi Linux.

* test: Ignore Vshl test on ARM64 due to unicorn crashes

* test: Workaround hardcoded size on some tests

Change mapping of code and data in case of non 4KiB configuration.

* test: Make CpuTestT32Flow depends on code address

Fix failure with different page size.

* test: Disable CpuTestThumb.TestRandomTestCases when page size isn't 4KiB

The test data needs to be reevaluated to take different page size into account.

* Address gdkchan's comments
---
 src/ARMeilleure/Translation/Cache/JitCache.cs |  5 ++--
 src/Ryujinx.Tests.Memory/Tests.cs             | 35 ++++++++++++++++-----------
 src/Ryujinx.Tests/Cpu/CpuTest.cs              | 24 +++++++++++++-----
 src/Ryujinx.Tests/Cpu/CpuTest32.cs            | 24 +++++++++++++-----
 src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs  | 34 ++++++++++++++------------
 src/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs     |  6 +++++
 src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs       |  6 ++---
 src/Ryujinx.Tests/Cpu/CpuTestThumb.cs         |  6 +++++
 8 files changed, 93 insertions(+), 47 deletions(-)

(limited to 'src')

diff --git a/src/ARMeilleure/Translation/Cache/JitCache.cs b/src/ARMeilleure/Translation/Cache/JitCache.cs
index daa2eeac..aa732d0a 100644
--- a/src/ARMeilleure/Translation/Cache/JitCache.cs
+++ b/src/ARMeilleure/Translation/Cache/JitCache.cs
@@ -2,6 +2,7 @@ using ARMeilleure.CodeGen;
 using ARMeilleure.CodeGen.Unwinding;
 using ARMeilleure.Memory;
 using ARMeilleure.Native;
+using Ryujinx.Memory;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -12,8 +13,8 @@ namespace ARMeilleure.Translation.Cache
 {
     static partial class JitCache
     {
-        private const int PageSize = 4 * 1024;
-        private const int PageMask = PageSize - 1;
+        private static readonly int PageSize = (int)MemoryBlock.GetPageSize();
+        private static readonly int PageMask = PageSize - 1;
 
         private const int CodeAlignment = 4; // Bytes.
         private const int CacheSize = 2047 * 1024 * 1024;
diff --git a/src/Ryujinx.Tests.Memory/Tests.cs b/src/Ryujinx.Tests.Memory/Tests.cs
index d8a243e3..5ab01d5a 100644
--- a/src/Ryujinx.Tests.Memory/Tests.cs
+++ b/src/Ryujinx.Tests.Memory/Tests.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.Tests.Memory
 {
     public class Tests
     {
-        private const ulong MemorySize = 0x8000;
+        private static readonly ulong MemorySize = MemoryBlock.GetPageSize() * 8;
 
         private MemoryBlock _memoryBlock;
 
@@ -44,14 +44,17 @@ namespace Ryujinx.Tests.Memory
         [Platform(Exclude = "MacOsX")]
         public void Test_Alias()
         {
-            using MemoryBlock backing = new MemoryBlock(0x10000, MemoryAllocationFlags.Mirrorable);
-            using MemoryBlock toAlias = new MemoryBlock(0x10000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
+            ulong pageSize = MemoryBlock.GetPageSize();
+            ulong blockSize = MemoryBlock.GetPageSize() * 16;
 
-            toAlias.MapView(backing, 0x1000, 0, 0x4000);
-            toAlias.UnmapView(backing, 0x3000, 0x1000);
+            using MemoryBlock backing = new MemoryBlock(blockSize, MemoryAllocationFlags.Mirrorable);
+            using MemoryBlock toAlias = new MemoryBlock(blockSize, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
+
+            toAlias.MapView(backing, pageSize, 0, pageSize * 4);
+            toAlias.UnmapView(backing, pageSize * 3, pageSize);
 
             toAlias.Write(0, 0xbadc0de);
-            Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, 0x1000), 0xbadc0de);
+            Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (int)pageSize), 0xbadc0de);
         }
 
         [Test]
@@ -59,8 +62,12 @@ namespace Ryujinx.Tests.Memory
         [Platform(Exclude = "MacOsX")]
         public void Test_AliasRandom()
         {
-            using MemoryBlock backing = new MemoryBlock(0x80000, MemoryAllocationFlags.Mirrorable);
-            using MemoryBlock toAlias = new MemoryBlock(0x80000, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
+            ulong pageSize = MemoryBlock.GetPageSize();
+            int pageBits = (int)ulong.Log2(pageSize);
+            ulong blockSize = MemoryBlock.GetPageSize() * 128;
+
+            using MemoryBlock backing = new MemoryBlock(blockSize, MemoryAllocationFlags.Mirrorable);
+            using MemoryBlock toAlias = new MemoryBlock(blockSize, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible);
 
             Random rng = new Random(123);
 
@@ -72,16 +79,16 @@ namespace Ryujinx.Tests.Memory
 
                 if ((rng.Next() & 1) != 0)
                 {
-                    toAlias.MapView(backing, (ulong)srcPage << 12, (ulong)dstPage << 12, (ulong)pages << 12);
+                    toAlias.MapView(backing, (ulong)srcPage << pageBits, (ulong)dstPage << pageBits, (ulong)pages << pageBits);
 
-                    int offset = rng.Next(0, 0x1000 - sizeof(int));
+                    int offset = rng.Next(0, (int)pageSize - sizeof(int));
 
-                    toAlias.Write((ulong)((dstPage << 12) + offset), 0xbadc0de);
-                    Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (srcPage << 12) + offset), 0xbadc0de);
+                    toAlias.Write((ulong)((dstPage << pageBits) + offset), 0xbadc0de);
+                    Assert.AreEqual(Marshal.ReadInt32(backing.Pointer, (srcPage << pageBits) + offset), 0xbadc0de);
                 }
                 else
                 {
-                    toAlias.UnmapView(backing, (ulong)dstPage << 12, (ulong)pages << 12);
+                    toAlias.UnmapView(backing, (ulong)dstPage << pageBits, (ulong)pages << pageBits);
                 }
             }
         }
@@ -91,7 +98,7 @@ namespace Ryujinx.Tests.Memory
         [Platform(Exclude = "MacOsX")]
         public void Test_AliasMapLeak()
         {
-            ulong pageSize = 4096;
+            ulong pageSize = MemoryBlock.GetPageSize();
             ulong size = 100000 * pageSize; // The mappings limit on Linux is usually around 65K, so let's make sure we are above that.
 
             using MemoryBlock backing = new MemoryBlock(pageSize, MemoryAllocationFlags.Mirrorable);
diff --git a/src/Ryujinx.Tests/Cpu/CpuTest.cs b/src/Ryujinx.Tests/Cpu/CpuTest.cs
index 979b313b..ad4ba539 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTest.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTest.cs
@@ -13,9 +13,9 @@ namespace Ryujinx.Tests.Cpu
     [TestFixture]
     public class CpuTest
     {
-        protected const ulong Size = 0x1000;
-        protected const ulong CodeBaseAddress = 0x1000;
-        protected const ulong DataBaseAddress = CodeBaseAddress + Size;
+        protected static readonly ulong Size = MemoryBlock.GetPageSize();
+        protected static ulong CodeBaseAddress = Size;
+        protected static ulong DataBaseAddress = CodeBaseAddress + Size;
 
         private static bool Ignore_FpcrFz = false;
         private static bool Ignore_FpcrDn = false;
@@ -39,12 +39,24 @@ namespace Ryujinx.Tests.Cpu
         [SetUp]
         public void Setup()
         {
-            _currAddress = CodeBaseAddress;
+            int pageBits = (int)ulong.Log2(Size);
 
             _ram = new MemoryBlock(Size * 2);
-            _memory = new MemoryManager(_ram, 1ul << 16);
+            _memory = new MemoryManager(_ram, 1ul << (pageBits + 4));
             _memory.IncrementReferenceCount();
-            _memory.Map(CodeBaseAddress, 0, Size * 2, MemoryMapFlags.Private);
+
+            // Some tests depends on hardcoded address that were computed for 4KiB.
+            // We change the layout on non 4KiB platforms to keep compat here.
+            if (Size > 0x1000)
+            {
+                DataBaseAddress = 0;
+                CodeBaseAddress = Size;
+            }
+
+            _currAddress = CodeBaseAddress;
+
+            _memory.Map(CodeBaseAddress, 0, Size, MemoryMapFlags.Private);
+            _memory.Map(DataBaseAddress, Size, Size, MemoryMapFlags.Private);
 
             _context = CpuContext.CreateExecutionContext();
             Translator.IsReadyForTranslation.Set();
diff --git a/src/Ryujinx.Tests/Cpu/CpuTest32.cs b/src/Ryujinx.Tests/Cpu/CpuTest32.cs
index 47dc9f8a..a1f6431c 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTest32.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTest32.cs
@@ -13,9 +13,9 @@ namespace Ryujinx.Tests.Cpu
     [TestFixture]
     public class CpuTest32
     {
-        protected const uint Size = 0x1000;
-        protected const uint CodeBaseAddress = 0x1000;
-        protected const uint DataBaseAddress = CodeBaseAddress + Size;
+        protected static readonly uint Size = (uint)MemoryBlock.GetPageSize();
+        protected static uint CodeBaseAddress = Size;
+        protected static uint DataBaseAddress = CodeBaseAddress + Size;
 
         private uint _currAddress;
 
@@ -33,12 +33,24 @@ namespace Ryujinx.Tests.Cpu
         [SetUp]
         public void Setup()
         {
-            _currAddress = CodeBaseAddress;
+            int pageBits = (int)ulong.Log2(Size);
 
             _ram = new MemoryBlock(Size * 2);
-            _memory = new MemoryManager(_ram, 1ul << 16);
+            _memory = new MemoryManager(_ram, 1ul << (pageBits + 4));
             _memory.IncrementReferenceCount();
-            _memory.Map(CodeBaseAddress, 0, Size * 2, MemoryMapFlags.Private);
+
+            // Some tests depends on hardcoded address that were computed for 4KiB.
+            // We change the layout on non 4KiB platforms to keep compat here.
+            if (Size > 0x1000)
+            {
+                DataBaseAddress = 0;
+                CodeBaseAddress = Size;
+            }
+
+            _currAddress = CodeBaseAddress;
+
+            _memory.Map(CodeBaseAddress, 0, Size, MemoryMapFlags.Private);
+            _memory.Map(DataBaseAddress, Size, Size, MemoryMapFlags.Private);
 
             _context = CpuContext.CreateExecutionContext();
             _context.IsAarch32 = true;
diff --git a/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs b/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs
index 2f9504cb..c88c02c1 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTestSimdMemory32.cs
@@ -1,6 +1,7 @@
 #define SimdMemory32
 
 using ARMeilleure.State;
+using Ryujinx.Memory;
 using NUnit.Framework;
 using System;
 
@@ -9,6 +10,7 @@ namespace Ryujinx.Tests.Cpu
     [Category("SimdMemory32")]
     public sealed class CpuTestSimdMemory32 : CpuTest32
     {
+        private static readonly uint TestOffset = DataBaseAddress + 0x500;
 #if SimdMemory32
 
         private uint[] _ldStModes =
@@ -42,7 +44,7 @@ namespace Ryujinx.Tests.Cpu
                                 [Range(0u, 3u)] uint n,
                                 [Values(0x0u)] uint offset)
         {
-            var data = GenerateVectorSequence(0x1000);
+            var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
             SetWorkingMemory(0, data);
 
             uint opcode = 0xf4a00000u; // VLD1.8 {D0[0]}, [R0], R0
@@ -58,7 +60,7 @@ namespace Ryujinx.Tests.Cpu
 
             opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
 
-            SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500);
+            SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
 
             CompareAgainstUnicorn();
         }
@@ -72,7 +74,7 @@ namespace Ryujinx.Tests.Cpu
                              [Values] bool t,
                              [Values(0x0u)] uint offset)
         {
-            var data = GenerateVectorSequence(0x1000);
+            var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
             SetWorkingMemory(0, data);
 
             uint opcode = 0xf4a00c00u; // VLD1.8 {D0[0]}, [R0], R0
@@ -85,7 +87,7 @@ namespace Ryujinx.Tests.Cpu
             opcode |= (n & 3) << 8; // LD1 is 0, LD2 is 1 etc.
             if (t) opcode |= 1 << 5;
 
-            SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500);
+            SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
 
             CompareAgainstUnicorn();
         }
@@ -98,7 +100,7 @@ namespace Ryujinx.Tests.Cpu
                               [Range(0u, 10u)] uint mode,
                               [Values(0x0u)] uint offset)
         {
-            var data = GenerateVectorSequence(0x1000);
+            var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
             SetWorkingMemory(0, data);
 
             uint opcode = 0xf4200000u; // VLD4.8 {D0, D1, D2, D3}, [R0], R0
@@ -114,7 +116,7 @@ namespace Ryujinx.Tests.Cpu
             opcode |= ((vd & 0x10) << 18);
             opcode |= ((vd & 0xf) << 12);
 
-            SingleOpcode(opcode, r0: 0x2500, r1: offset, sp: 0x2500);
+            SingleOpcode(opcode, r0: TestOffset, r1: offset, sp: TestOffset);
 
             CompareAgainstUnicorn();
         }
@@ -128,7 +130,7 @@ namespace Ryujinx.Tests.Cpu
                                 [Range(0u, 3u)] uint n,
                                 [Values(0x0u)] uint offset)
         {
-            var data = GenerateVectorSequence(0x1000);
+            var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
             SetWorkingMemory(0, data);
 
             (V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors();
@@ -146,7 +148,7 @@ namespace Ryujinx.Tests.Cpu
 
             opcode |= (n & 3) << 8; // ST1 is 0, ST2 is 1 etc.
 
-            SingleOpcode(opcode, r0: 0x2500, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: 0x2500);
+            SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset);
 
             CompareAgainstUnicorn();
         }
@@ -159,7 +161,7 @@ namespace Ryujinx.Tests.Cpu
                               [Range(0u, 10u)] uint mode,
                               [Values(0x0u)] uint offset)
         {
-            var data = GenerateVectorSequence(0x1000);
+            var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
             SetWorkingMemory(0, data);
 
             (V128 vec1, V128 vec2, V128 vec3, V128 vec4) = GenerateTestVectors();
@@ -177,7 +179,7 @@ namespace Ryujinx.Tests.Cpu
             opcode |= ((vd & 0x10) << 18);
             opcode |= ((vd & 0xf) << 12);
 
-            SingleOpcode(opcode, r0: 0x2500, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: 0x2500);
+            SingleOpcode(opcode, r0: TestOffset, r1: offset, v1: vec1, v2: vec2, v3: vec3, v4: vec4, sp: TestOffset);
 
             CompareAgainstUnicorn();
         }
@@ -189,7 +191,7 @@ namespace Ryujinx.Tests.Cpu
                          [Values(0x1u, 0x32u)] uint regs,
                          [Values] bool single)
         {
-            var data = GenerateVectorSequence(0x1000);
+            var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
             SetWorkingMemory(0, data);
 
             uint opcode = 0xec100a00u; // VST4.8 {D0, D1, D2, D3}, [R0], R0
@@ -225,7 +227,7 @@ namespace Ryujinx.Tests.Cpu
 
             opcode |= regs & 0xff;
 
-            SingleOpcode(opcode, r0: 0x2500, sp: 0x2500);
+            SingleOpcode(opcode, r0: TestOffset, sp: TestOffset);
 
             CompareAgainstUnicorn();
         }
@@ -237,7 +239,7 @@ namespace Ryujinx.Tests.Cpu
                          [Values(0x0u)] uint imm,
                          [Values] bool sub)
         {
-            var data = GenerateVectorSequence(0x1000);
+            var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
             SetWorkingMemory(0, data);
 
             uint opcode = 0xed900a00u; // VLDR.32 S0, [R0, #0]
@@ -260,7 +262,7 @@ namespace Ryujinx.Tests.Cpu
             }
             opcode |= imm & 0xff;
 
-            SingleOpcode(opcode, r0: 0x2500);
+            SingleOpcode(opcode, r0: TestOffset);
 
             CompareAgainstUnicorn();
         }
@@ -272,7 +274,7 @@ namespace Ryujinx.Tests.Cpu
                 [Values(0x0u)] uint imm,
                 [Values] bool sub)
         {
-            var data = GenerateVectorSequence(0x1000);
+            var data = GenerateVectorSequence((int)MemoryBlock.GetPageSize());
             SetWorkingMemory(0, data);
 
             uint opcode = 0xed800a00u; // VSTR.32 S0, [R0, #0]
@@ -297,7 +299,7 @@ namespace Ryujinx.Tests.Cpu
 
             (V128 vec1, V128 vec2, _, _) = GenerateTestVectors();
 
-            SingleOpcode(opcode, r0: 0x2500, v0: vec1, v1: vec2);
+            SingleOpcode(opcode, r0: TestOffset, v0: vec1, v1: vec2);
 
             CompareAgainstUnicorn();
         }
diff --git a/src/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs b/src/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs
index b19137a4..603e2a55 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTestSimdReg32.cs
@@ -3,6 +3,7 @@
 using ARMeilleure.State;
 using NUnit.Framework;
 using System.Collections.Generic;
+using System.Runtime.InteropServices;
 
 namespace Ryujinx.Tests.Cpu
 {
@@ -703,6 +704,11 @@ namespace Ryujinx.Tests.Cpu
                          [Values] bool q,
                          [Values] bool u)
         {
+            if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
+            {
+                Assert.Ignore("Unicorn on ARM64 crash while executing this test");
+            }
+
             uint opcode = 0xf2000400u; // VSHL.S8 D0, D0, D0
             if (q)
             {
diff --git a/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs b/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs
index 2c83b01d..03d90a1f 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTestT32Flow.cs
@@ -109,7 +109,7 @@ namespace Ryujinx.Tests.Cpu
 
             ExecuteOpcodes(runUnicorn: false);
 
-            Assert.That(GetContext().GetX(0), Is.EqualTo(0x1005));
+            Assert.That(GetContext().GetX(0), Is.EqualTo(CodeBaseAddress + 0x5));
         }
 
         [Test]
@@ -133,7 +133,7 @@ namespace Ryujinx.Tests.Cpu
 
             ExecuteOpcodes(runUnicorn: false);
 
-            Assert.That(GetContext().GetX(0), Is.EqualTo(0x1005));
+            Assert.That(GetContext().GetX(0), Is.EqualTo(CodeBaseAddress + 0x5));
             Assert.That(GetContext().GetPstateFlag(PState.TFlag), Is.EqualTo(false));
         }
 
@@ -160,7 +160,7 @@ namespace Ryujinx.Tests.Cpu
 
             ExecuteOpcodes(runUnicorn: false);
 
-            Assert.That(GetContext().GetX(0), Is.EqualTo(0x1007));
+            Assert.That(GetContext().GetX(0), Is.EqualTo(CodeBaseAddress + 0x7));
             Assert.That(GetContext().GetPstateFlag(PState.TFlag), Is.EqualTo(false));
         }
     }
diff --git a/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs b/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs
index b740f524..3d13ff73 100644
--- a/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs
+++ b/src/Ryujinx.Tests/Cpu/CpuTestThumb.cs
@@ -268,6 +268,12 @@ namespace Ryujinx.Tests.Cpu
         [Test]
         public void TestRandomTestCases([ValueSource(nameof(RandomTestCases))] PrecomputedThumbTestCase test)
         {
+            if (Size != 0x1000)
+            {
+                // TODO: Change it to depend on DataBaseAddress instead.
+                Assert.Ignore("This test currently only support 4KiB page size");
+            }
+
             RunPrecomputedTestCase(test);
         }
 
-- 
cgit v1.2.3-70-g09d2