Implement a new physical memory manager and replace DeviceMemory (#856)

* Implement a new physical memory manager and replace DeviceMemory

* Proper generic constraints

* Fix debug build

* Add memory tests

* New CPU memory manager and general code cleanup

* Remove host memory management from CPU project, use Ryujinx.Memory instead

* Fix tests

* Document exceptions on MemoryBlock

* Fix leak on unix memory allocation

* Proper disposal of some objects on tests

* Fix JitCache not being set as initialized

* GetRef without checks for 8-bits and 16-bits CAS

* Add MemoryBlock destructor

* Throw in separate method to improve codegen

* Address PR feedback

* QueryModified improvements

* Fix memory write tracking not marking all pages as modified in some cases

* Simplify MarkRegionAsModified

* Remove XML doc for ghost param

* Add back optimization to avoid useless buffer updates

* Add Ryujinx.Cpu project, move MemoryManager there and remove MemoryBlockWrapper

* Some nits

* Do not perform address translation when size is 0

* Address PR feedback and format NativeInterface class

* Remove ghost parameter description

* Update Ryujinx.Cpu to .NET Core 3.1

* Address PR feedback

* Fix build

* Return a well defined value for GetPhysicalAddress with invalid VA, and do not return unmapped ranges as modified

* Typo
This commit is contained in:
gdkchan 2020-05-03 19:54:50 -03:00 committed by GitHub
parent 1758424208
commit f77694e4f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
126 changed files with 2176 additions and 2092 deletions

View file

@ -1,10 +1,12 @@
using ARMeilleure.Memory;
using ARMeilleure.State;
using ARMeilleure.Translation;
using ARMeilleure.State;
using NUnit.Framework;
using Ryujinx.Cpu;
using Ryujinx.Memory;
using Ryujinx.Tests.Unicorn;
using System;
using System.Runtime.InteropServices;
using MemoryPermission = Ryujinx.Tests.Unicorn.MemoryPermission;
namespace Ryujinx.Tests.Cpu
{
@ -12,17 +14,17 @@ namespace Ryujinx.Tests.Cpu
public class CpuTest32
{
private uint _currAddress;
private long _size;
private ulong _size;
private uint _entryPoint;
private IntPtr _ramPointer;
private MemoryBlock _ram;
private MemoryManager _memory;
private ExecutionContext _context;
private Translator _translator;
private CpuContext _cpuContext;
private static bool _unicornAvailable;
private UnicornAArch32 _unicornEmu;
@ -47,20 +49,20 @@ namespace Ryujinx.Tests.Cpu
_entryPoint = _currAddress;
_ramPointer = Marshal.AllocHGlobal(new IntPtr(_size * 2));
_memory = new MemoryManager(_ramPointer, addressSpaceBits: 16, useFlatPageTable: true);
_memory.Map((long)_currAddress, 0, _size*2);
_ram = new MemoryBlock(_size * 2);
_memory = new MemoryManager(_ram, 1UL << 16);
_memory.Map(_currAddress, 0, _size * 2);
_context = new ExecutionContext();
_context = CpuContext.CreateExecutionContext();
_context.IsAarch32 = true;
_translator = new Translator(_memory);
_cpuContext = new CpuContext(_memory);
if (_unicornAvailable)
{
_unicornEmu = new UnicornAArch32();
_unicornEmu.MemoryMap(_currAddress, (ulong)_size, MemoryPermission.READ | MemoryPermission.EXEC);
_unicornEmu.MemoryMap((ulong)(_currAddress + _size), (ulong)_size, MemoryPermission.READ | MemoryPermission.WRITE);
_unicornEmu.MemoryMap(_currAddress, _size, MemoryPermission.READ | MemoryPermission.EXEC);
_unicornEmu.MemoryMap(_currAddress + _size, _size, MemoryPermission.READ | MemoryPermission.WRITE);
_unicornEmu.PC = _entryPoint;
}
}
@ -68,10 +70,12 @@ namespace Ryujinx.Tests.Cpu
[TearDown]
public void Teardown()
{
Marshal.FreeHGlobal(_ramPointer);
_memory.Dispose();
_context.Dispose();
_ram.Dispose();
_memory = null;
_context = null;
_translator = null;
_cpuContext = null;
_unicornEmu = null;
}
@ -83,11 +87,11 @@ namespace Ryujinx.Tests.Cpu
protected void Opcode(uint opcode)
{
_memory.WriteUInt32((long)_currAddress, opcode);
_memory.Write(_currAddress, opcode);
if (_unicornAvailable)
{
_unicornEmu.MemoryWrite32((ulong)_currAddress, opcode);
_unicornEmu.MemoryWrite32(_currAddress, opcode);
}
_currAddress += 4;
@ -166,7 +170,7 @@ namespace Ryujinx.Tests.Cpu
protected void ExecuteOpcodes(bool runUnicorn = true)
{
_translator.Execute(_context, _entryPoint);
_cpuContext.Execute(_context, _entryPoint);
if (_unicornAvailable && runUnicorn)
{
@ -210,7 +214,7 @@ namespace Ryujinx.Tests.Cpu
protected void SetWorkingMemory(byte[] data)
{
_memory.WriteBytes(0x2000, data);
_memory.Write(0x2000, data);
if (_unicornAvailable)
{
@ -357,10 +361,10 @@ namespace Ryujinx.Tests.Cpu
if (usingMemory)
{
byte[] meilleureMem = _memory.ReadBytes((long)(0x2000), _size);
byte[] unicornMem = _unicornEmu.MemoryRead((ulong)(0x2000), (ulong)_size);
ReadOnlySpan<byte> meilleureMem = _memory.GetSpan(0x2000, (int)_size);
byte[] unicornMem = _unicornEmu.MemoryRead(0x2000, _size);
for (int i = 0; i < _size; i++)
for (int i = 0; i < (int)_size; i++)
{
Assert.AreEqual(meilleureMem[i], unicornMem[i]);
}