From 8e0cd3d2fdb82bbf9140c9ff8f40f0ce1bc4ecb8 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 20 Feb 2019 18:39:26 -0300 Subject: [PATCH] Support multi-level page tables --- .../Instructions/InstEmitMemoryHelper.cs | 54 ++++--- ChocolArm64/Memory/MemoryManager.cs | 151 +++++++++++++++--- Ryujinx.HLE/DeviceMemory.cs | 1 - Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 45 ++++-- .../HOS/Kernel/SupervisorCall/SvcHandler.cs | 3 - .../HOS/Kernel/SupervisorCall/SvcIpc.cs | 4 +- .../HOS/Kernel/SupervisorCall/SvcMemory.cs | 16 +- .../HOS/Kernel/SupervisorCall/SvcSystem.cs | 2 +- .../HOS/Kernel/SupervisorCall/SvcThread.cs | 141 ++++++++-------- .../Kernel/SupervisorCall/SvcThreadSync.cs | 2 +- Ryujinx.Tests/Cpu/CpuTest.cs | 2 +- 11 files changed, 283 insertions(+), 138 deletions(-) diff --git a/ChocolArm64/Instructions/InstEmitMemoryHelper.cs b/ChocolArm64/Instructions/InstEmitMemoryHelper.cs index 4ebcc86938..9c8e5ecb3e 100644 --- a/ChocolArm64/Instructions/InstEmitMemoryHelper.cs +++ b/ChocolArm64/Instructions/InstEmitMemoryHelper.cs @@ -161,7 +161,7 @@ namespace ChocolArm64.Instructions EmitReadIntFallback(context, size); - context.Emit(OpCodes.Br_S, lblEnd); + context.Emit(OpCodes.Br, lblEnd); context.MarkLabel(lblFastPath); @@ -192,7 +192,7 @@ namespace ChocolArm64.Instructions EmitReadVectorFallback(context, size); - context.Emit(OpCodes.Br_S, lblEnd); + context.Emit(OpCodes.Br, lblEnd); context.MarkLabel(lblFastPath); @@ -217,7 +217,7 @@ namespace ChocolArm64.Instructions EmitWriteIntFallback(context, size); - context.Emit(OpCodes.Br_S, lblEnd); + context.Emit(OpCodes.Br, lblEnd); context.MarkLabel(lblFastPath); @@ -255,7 +255,7 @@ namespace ChocolArm64.Instructions EmitWriteVectorFallback(context, size); - context.Emit(OpCodes.Br_S, lblEnd); + context.Emit(OpCodes.Br, lblEnd); context.MarkLabel(lblFastPath); @@ -283,24 +283,40 @@ namespace ChocolArm64.Instructions private static void EmitPtPointerLoad(ILEmitterCtx context, ILLabel lblFallbackPath) { - context.EmitLdint(_tempIntAddress); - - context.EmitLsr(MemoryManager.PageBits); - - context.EmitLdc_I(IntPtr.Size); - - context.Emit(OpCodes.Mul); - - if (context.CurrOp.RegisterSize == RegisterSize.Int32) - { - context.Emit(OpCodes.Conv_U8); - } - context.EmitLdc_I8(context.Memory.PageTable.ToInt64()); - context.Emit(OpCodes.Add); context.Emit(OpCodes.Conv_I); - context.Emit(OpCodes.Ldind_I); + + int bit = MemoryManager.PageBits; + + do + { + context.EmitLdint(_tempIntAddress); + + if (context.CurrOp.RegisterSize == RegisterSize.Int32) + { + context.Emit(OpCodes.Conv_U8); + } + + context.EmitLsr(bit); + + bit += context.Memory.PtLevelBits; + + if (bit < context.Memory.AddressSpaceBits) + { + context.EmitLdc_I8(context.Memory.PtLevelMask); + + context.Emit(OpCodes.And); + } + + context.EmitLdc_I8(IntPtr.Size); + + context.Emit(OpCodes.Mul); + context.Emit(OpCodes.Conv_I); + context.Emit(OpCodes.Add); + context.Emit(OpCodes.Ldind_I); + } + while (bit < context.Memory.AddressSpaceBits); if (!context.Memory.HasWriteWatchSupport) { diff --git a/ChocolArm64/Memory/MemoryManager.cs b/ChocolArm64/Memory/MemoryManager.cs index 3c51956028..c46a2b2565 100644 --- a/ChocolArm64/Memory/MemoryManager.cs +++ b/ChocolArm64/Memory/MemoryManager.cs @@ -29,21 +29,46 @@ namespace ChocolArm64.Memory internal IntPtr PageTable => _pageTable; + internal int PtLevelBits { get; } + internal int PtLevelSize { get; } + internal int PtLevelMask { get; } + public bool HasWriteWatchSupport => MemoryManagement.HasWriteWatchSupport; + public int AddressSpaceBits { get; } public long AddressSpaceSize { get; } - public MemoryManager(IntPtr ram, long addressSpaceSize = 1L << 39) + public MemoryManager( + IntPtr ram, + int addressSpaceBits = 48, + bool useFlatPageTable = false) { Ram = ram; _ramPtr = (byte*)ram; - AddressSpaceSize = addressSpaceSize; + AddressSpaceBits = addressSpaceBits; + AddressSpaceSize = 1L << addressSpaceBits; - long pageTableSize = (addressSpaceSize / PageSize) * IntPtr.Size; + //When flag page table is requested, we use a single + //array for the mappings of the entire address space. + //This has better performance, but also high RAM usage. + //The multi level page table uses 9 bits per level, so + //the RAM usage is lower, but the performance is also + //lower, because it's needed to do multiple reads per translation. + if (useFlatPageTable) + { + PtLevelBits = addressSpaceBits - PageBits; + } + else + { + PtLevelBits = 9; + } - _pageTable = Allocate((ulong)pageTableSize); + PtLevelSize = 1 << PtLevelBits; + PtLevelMask = PtLevelSize - 1; + + _pageTable = Allocate((ulong)(PtLevelSize * IntPtr.Size)); } public void Map(long va, long pa, long size) @@ -75,14 +100,10 @@ namespace ChocolArm64.Memory return IntPtr.Zero; } - byte* ptr = ((byte**)_pageTable)[position >> PageBits]; - - IntPtr* pt = (IntPtr*)_pageTable; + byte* ptr = GetPtEntry(position); ulong ptrUlong = (ulong)ptr; - long ptrLong = (long)ptr; - if ((ptrUlong & PteFlagsMask) != 0) { ptrUlong &= ~(ulong)PteFlagsMask; @@ -100,7 +121,7 @@ namespace ChocolArm64.Memory return IntPtr.Zero; } - byte* ptr = ((byte**)_pageTable)[position >> PageBits]; + byte* ptr = GetPtEntry(position); ulong ptrUlong = (ulong)ptr; @@ -119,6 +140,11 @@ namespace ChocolArm64.Memory return new IntPtr(ptr + (position & PageMask)); } + private byte* GetPtEntry(long position) + { + return *(byte**)GetPtPtr(position); + } + private void SetPtEntries(long va, byte* ptr, long size) { long endPosition = (va + size + PageMask) & ~PageMask; @@ -138,12 +164,7 @@ namespace ChocolArm64.Memory private void SetPtEntry(long position, byte* ptr) { - if (!IsValidPosition(position)) - { - throw new ArgumentOutOfRangeException(nameof(position)); - } - - ((byte**)_pageTable)[position >> PageBits] = ptr; + *(byte**)GetPtPtr(position) = ptr; } private void SetPtEntryFlag(long position, long flag) @@ -162,13 +183,22 @@ namespace ChocolArm64.Memory while (true) { - IntPtr old = pt[position >> PageBits]; + IntPtr* ptPtr = GetPtPtr(position); - IntPtr modified = setFlag - ? new IntPtr(old.ToInt64() | flag) - : new IntPtr(old.ToInt64() & ~flag); + IntPtr old = *ptPtr; - IntPtr origValue = Interlocked.CompareExchange(ref pt[position >> PageBits], modified, old); + long modified = old.ToInt64(); + + if (setFlag) + { + modified |= flag; + } + else + { + modified &= ~flag; + } + + IntPtr origValue = Interlocked.CompareExchange(ref *ptPtr, new IntPtr(modified), old); if (origValue == old) { @@ -177,6 +207,57 @@ namespace ChocolArm64.Memory } } + private IntPtr* GetPtPtr(long position) + { + if (!IsValidPosition(position)) + { + throw new ArgumentOutOfRangeException(nameof(position)); + } + + IntPtr nextPtr = _pageTable; + + IntPtr* ptePtr = null; + + int bit = PageBits; + + while (true) + { + long index = (position >> bit) & PtLevelMask; + + ptePtr = &((IntPtr*)nextPtr)[index]; + + bit += PtLevelBits; + + if (bit >= AddressSpaceBits) + { + break; + } + + nextPtr = *ptePtr; + + if (nextPtr == IntPtr.Zero) + { + //Entry does not yet exist, allocate a new one. + IntPtr newPtr = Allocate((ulong)(PtLevelSize * IntPtr.Size)); + + //Try to swap the current pointer (should be zero), with the allocated one. + nextPtr = Interlocked.Exchange(ref *ptePtr, newPtr); + + //If the old pointer is not null, then another thread already has set it. + if (nextPtr != IntPtr.Zero) + { + Free(newPtr); + } + else + { + nextPtr = newPtr; + } + } + } + + return ptePtr; + } + public bool IsRegionModified(long position, long size) { if (!HasWriteWatchSupport) @@ -318,7 +399,7 @@ namespace ChocolArm64.Memory public bool IsValidPosition(long position) { - return (ulong)position <= (ulong)AddressSpaceSize; + return (ulong)position < (ulong)AddressSpaceSize; } internal bool AtomicCompareExchange2xInt32( @@ -899,8 +980,32 @@ namespace ChocolArm64.Memory if (ptr != IntPtr.Zero) { - Free(ptr); + FreePageTableEntry(ptr, PageBits); } } + + private void FreePageTableEntry(IntPtr ptr, int levelBitEnd) + { + levelBitEnd += PtLevelBits; + + if (levelBitEnd >= AddressSpaceBits) + { + Free(ptr); + + return; + } + + for (int index = 0; index < PtLevelSize; index++) + { + IntPtr ptePtr = ((IntPtr*)ptr)[index]; + + if (ptePtr != IntPtr.Zero) + { + FreePageTableEntry(ptePtr, levelBitEnd); + } + } + + Free(ptr); + } } } \ No newline at end of file diff --git a/Ryujinx.HLE/DeviceMemory.cs b/Ryujinx.HLE/DeviceMemory.cs index dc43903f11..524adb8466 100644 --- a/Ryujinx.HLE/DeviceMemory.cs +++ b/Ryujinx.HLE/DeviceMemory.cs @@ -1,6 +1,5 @@ using ChocolArm64.Memory; using System; -using System.Runtime.InteropServices; namespace Ryujinx.HLE { diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index 1d33d79358..909f6333a9 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -80,12 +80,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Process public bool IsPaused { get; private set; } - public Translator Translator { get; private set; } - public MemoryManager CpuMemory { get; private set; } + public Translator Translator { get; private set; } + private SvcHandler _svcHandler; + private Horizon _system; + public HleProcessDebugger Debugger { get; private set; } public KProcess(Horizon system) : base(system) @@ -93,12 +95,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process _processLock = new object(); _threadingLock = new object(); - CpuMemory = new MemoryManager(system.Device.Memory.RamPointer); + _system = system; AddressArbiter = new KAddressArbiter(system); - MemoryManager = new KMemoryManager(system, CpuMemory); - _fullTlsPages = new SortedDictionary(); _freeTlsPages = new SortedDictionary(); @@ -108,10 +108,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process _threads = new LinkedList(); - Translator = new Translator(CpuMemory); - - Translator.CpuTrace += CpuTraceHandler; - _svcHandler = new SvcHandler(system.Device, this); Debugger = new HleProcessDebugger(this); @@ -129,6 +125,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7); + InitializeMemoryManager(addrSpaceType, memRegion); + bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0; ulong codeAddress = creationInfo.CodeAddress; @@ -236,6 +234,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process AddressSpaceType addrSpaceType = (AddressSpaceType)((creationInfo.MmuFlags >> 1) & 7); + InitializeMemoryManager(addrSpaceType, memRegion); + bool aslrEnabled = ((creationInfo.MmuFlags >> 5) & 1) != 0; ulong codeAddress = creationInfo.CodeAddress; @@ -403,7 +403,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process case AddressSpaceType.Addr36Bits: case AddressSpaceType.Addr39Bits: _memoryUsageCapacity = MemoryManager.HeapRegionEnd - - MemoryManager.HeapRegionStart; + MemoryManager.HeapRegionStart; break; case AddressSpaceType.Addr32BitsNoMap: @@ -1008,6 +1008,31 @@ namespace Ryujinx.HLE.HOS.Kernel.Process } } + private void InitializeMemoryManager(AddressSpaceType addrSpaceType, MemoryRegion memRegion) + { + int addrSpaceBits; + + switch (addrSpaceType) + { + case AddressSpaceType.Addr32Bits: addrSpaceBits = 32; break; + case AddressSpaceType.Addr36Bits: addrSpaceBits = 36; break; + case AddressSpaceType.Addr32BitsNoMap: addrSpaceBits = 32; break; + case AddressSpaceType.Addr39Bits: addrSpaceBits = 39; break; + + default: throw new ArgumentException(nameof(addrSpaceType)); + } + + bool useFlatPageTable = memRegion == MemoryRegion.Application; + + CpuMemory = new MemoryManager(_system.Device.Memory.RamPointer, addrSpaceBits, useFlatPageTable); + + MemoryManager = new KMemoryManager(_system, CpuMemory); + + Translator = new Translator(CpuMemory); + + Translator.CpuTrace += CpuTraceHandler; + } + public void PrintCurrentThreadStackTrace() { System.Scheduler.GetCurrentThread().PrintGuestStackTrace(); diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs index 071b3c2019..cf881a7932 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs @@ -1,5 +1,4 @@ using ChocolArm64.Events; -using ChocolArm64.Memory; using ChocolArm64.State; using Ryujinx.HLE.HOS.Kernel.Process; using System; @@ -11,14 +10,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall private Switch _device; private KProcess _process; private Horizon _system; - private MemoryManager _memory; public SvcHandler(Switch device, KProcess process) { _device = device; _process = process; _system = device.System; - _memory = process.CpuMemory; } public void SvcCall(object sender, InstExceptionEventArgs e) diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs index 5493941894..e19d9d2687 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs @@ -93,7 +93,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle) { - byte[] messageData = _memory.ReadBytes((long)messagePtr, (long)size); + byte[] messageData = _process.CpuMemory.ReadBytes((long)messagePtr, (long)size); KClientSession clientSession = _process.HandleTable.GetObject(handle); @@ -142,7 +142,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall ipcMessage.Thread.ObjSyncResult = IpcHandler.IpcCall( _device, _process, - _memory, + _process.CpuMemory, ipcMessage.Session, ipcMessage.Message, ipcMessage.MessagePtr); diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs index 82397ef8db..f794d13073 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs @@ -152,14 +152,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { KMemoryInfo blkInfo = _process.MemoryManager.QueryMemory(position); - _memory.WriteUInt64((long)infoPtr + 0x00, blkInfo.Address); - _memory.WriteUInt64((long)infoPtr + 0x08, blkInfo.Size); - _memory.WriteInt32 ((long)infoPtr + 0x10, (int)blkInfo.State & 0xff); - _memory.WriteInt32 ((long)infoPtr + 0x14, (int)blkInfo.Attribute); - _memory.WriteInt32 ((long)infoPtr + 0x18, (int)blkInfo.Permission); - _memory.WriteInt32 ((long)infoPtr + 0x1c, blkInfo.IpcRefCount); - _memory.WriteInt32 ((long)infoPtr + 0x20, blkInfo.DeviceRefCount); - _memory.WriteInt32 ((long)infoPtr + 0x24, 0); + _process.CpuMemory.WriteUInt64((long)infoPtr + 0x00, blkInfo.Address); + _process.CpuMemory.WriteUInt64((long)infoPtr + 0x08, blkInfo.Size); + _process.CpuMemory.WriteInt32 ((long)infoPtr + 0x10, (int)blkInfo.State & 0xff); + _process.CpuMemory.WriteInt32 ((long)infoPtr + 0x14, (int)blkInfo.Attribute); + _process.CpuMemory.WriteInt32 ((long)infoPtr + 0x18, (int)blkInfo.Permission); + _process.CpuMemory.WriteInt32 ((long)infoPtr + 0x1c, blkInfo.IpcRefCount); + _process.CpuMemory.WriteInt32 ((long)infoPtr + 0x20, blkInfo.DeviceRefCount); + _process.CpuMemory.WriteInt32 ((long)infoPtr + 0x24, 0); return KernelResult.Success; } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs index be136ff0a5..efc10512ab 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs @@ -201,7 +201,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall private void OutputDebugString(ulong strPtr, ulong size) { - string str = MemoryHelper.ReadAsciiString(_memory, (long)strPtr, (long)size); + string str = MemoryHelper.ReadAsciiString(_process.CpuMemory, (long)strPtr, (long)size); Logger.PrintWarning(LogClass.KernelSvc, str); } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs index 64268ff23d..fa0b3a6c88 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs @@ -1,3 +1,4 @@ +using ChocolArm64.Memory; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Threading; @@ -346,79 +347,81 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return KernelResult.InvalidThread; } - _memory.WriteUInt64((long)address + 0x0, thread.Context.ThreadState.X0); - _memory.WriteUInt64((long)address + 0x8, thread.Context.ThreadState.X1); - _memory.WriteUInt64((long)address + 0x10, thread.Context.ThreadState.X2); - _memory.WriteUInt64((long)address + 0x18, thread.Context.ThreadState.X3); - _memory.WriteUInt64((long)address + 0x20, thread.Context.ThreadState.X4); - _memory.WriteUInt64((long)address + 0x28, thread.Context.ThreadState.X5); - _memory.WriteUInt64((long)address + 0x30, thread.Context.ThreadState.X6); - _memory.WriteUInt64((long)address + 0x38, thread.Context.ThreadState.X7); - _memory.WriteUInt64((long)address + 0x40, thread.Context.ThreadState.X8); - _memory.WriteUInt64((long)address + 0x48, thread.Context.ThreadState.X9); - _memory.WriteUInt64((long)address + 0x50, thread.Context.ThreadState.X10); - _memory.WriteUInt64((long)address + 0x58, thread.Context.ThreadState.X11); - _memory.WriteUInt64((long)address + 0x60, thread.Context.ThreadState.X12); - _memory.WriteUInt64((long)address + 0x68, thread.Context.ThreadState.X13); - _memory.WriteUInt64((long)address + 0x70, thread.Context.ThreadState.X14); - _memory.WriteUInt64((long)address + 0x78, thread.Context.ThreadState.X15); - _memory.WriteUInt64((long)address + 0x80, thread.Context.ThreadState.X16); - _memory.WriteUInt64((long)address + 0x88, thread.Context.ThreadState.X17); - _memory.WriteUInt64((long)address + 0x90, thread.Context.ThreadState.X18); - _memory.WriteUInt64((long)address + 0x98, thread.Context.ThreadState.X19); - _memory.WriteUInt64((long)address + 0xa0, thread.Context.ThreadState.X20); - _memory.WriteUInt64((long)address + 0xa8, thread.Context.ThreadState.X21); - _memory.WriteUInt64((long)address + 0xb0, thread.Context.ThreadState.X22); - _memory.WriteUInt64((long)address + 0xb8, thread.Context.ThreadState.X23); - _memory.WriteUInt64((long)address + 0xc0, thread.Context.ThreadState.X24); - _memory.WriteUInt64((long)address + 0xc8, thread.Context.ThreadState.X25); - _memory.WriteUInt64((long)address + 0xd0, thread.Context.ThreadState.X26); - _memory.WriteUInt64((long)address + 0xd8, thread.Context.ThreadState.X27); - _memory.WriteUInt64((long)address + 0xe0, thread.Context.ThreadState.X28); - _memory.WriteUInt64((long)address + 0xe8, thread.Context.ThreadState.X29); - _memory.WriteUInt64((long)address + 0xf0, thread.Context.ThreadState.X30); - _memory.WriteUInt64((long)address + 0xf8, thread.Context.ThreadState.X31); + MemoryManager memory = currentProcess.CpuMemory; - _memory.WriteInt64((long)address + 0x100, thread.LastPc); + memory.WriteUInt64((long)address + 0x0, thread.Context.ThreadState.X0); + memory.WriteUInt64((long)address + 0x8, thread.Context.ThreadState.X1); + memory.WriteUInt64((long)address + 0x10, thread.Context.ThreadState.X2); + memory.WriteUInt64((long)address + 0x18, thread.Context.ThreadState.X3); + memory.WriteUInt64((long)address + 0x20, thread.Context.ThreadState.X4); + memory.WriteUInt64((long)address + 0x28, thread.Context.ThreadState.X5); + memory.WriteUInt64((long)address + 0x30, thread.Context.ThreadState.X6); + memory.WriteUInt64((long)address + 0x38, thread.Context.ThreadState.X7); + memory.WriteUInt64((long)address + 0x40, thread.Context.ThreadState.X8); + memory.WriteUInt64((long)address + 0x48, thread.Context.ThreadState.X9); + memory.WriteUInt64((long)address + 0x50, thread.Context.ThreadState.X10); + memory.WriteUInt64((long)address + 0x58, thread.Context.ThreadState.X11); + memory.WriteUInt64((long)address + 0x60, thread.Context.ThreadState.X12); + memory.WriteUInt64((long)address + 0x68, thread.Context.ThreadState.X13); + memory.WriteUInt64((long)address + 0x70, thread.Context.ThreadState.X14); + memory.WriteUInt64((long)address + 0x78, thread.Context.ThreadState.X15); + memory.WriteUInt64((long)address + 0x80, thread.Context.ThreadState.X16); + memory.WriteUInt64((long)address + 0x88, thread.Context.ThreadState.X17); + memory.WriteUInt64((long)address + 0x90, thread.Context.ThreadState.X18); + memory.WriteUInt64((long)address + 0x98, thread.Context.ThreadState.X19); + memory.WriteUInt64((long)address + 0xa0, thread.Context.ThreadState.X20); + memory.WriteUInt64((long)address + 0xa8, thread.Context.ThreadState.X21); + memory.WriteUInt64((long)address + 0xb0, thread.Context.ThreadState.X22); + memory.WriteUInt64((long)address + 0xb8, thread.Context.ThreadState.X23); + memory.WriteUInt64((long)address + 0xc0, thread.Context.ThreadState.X24); + memory.WriteUInt64((long)address + 0xc8, thread.Context.ThreadState.X25); + memory.WriteUInt64((long)address + 0xd0, thread.Context.ThreadState.X26); + memory.WriteUInt64((long)address + 0xd8, thread.Context.ThreadState.X27); + memory.WriteUInt64((long)address + 0xe0, thread.Context.ThreadState.X28); + memory.WriteUInt64((long)address + 0xe8, thread.Context.ThreadState.X29); + memory.WriteUInt64((long)address + 0xf0, thread.Context.ThreadState.X30); + memory.WriteUInt64((long)address + 0xf8, thread.Context.ThreadState.X31); - _memory.WriteUInt64((long)address + 0x108, (ulong)thread.Context.ThreadState.Psr); + memory.WriteInt64((long)address + 0x100, thread.LastPc); - _memory.WriteVector128((long)address + 0x110, thread.Context.ThreadState.V0); - _memory.WriteVector128((long)address + 0x120, thread.Context.ThreadState.V1); - _memory.WriteVector128((long)address + 0x130, thread.Context.ThreadState.V2); - _memory.WriteVector128((long)address + 0x140, thread.Context.ThreadState.V3); - _memory.WriteVector128((long)address + 0x150, thread.Context.ThreadState.V4); - _memory.WriteVector128((long)address + 0x160, thread.Context.ThreadState.V5); - _memory.WriteVector128((long)address + 0x170, thread.Context.ThreadState.V6); - _memory.WriteVector128((long)address + 0x180, thread.Context.ThreadState.V7); - _memory.WriteVector128((long)address + 0x190, thread.Context.ThreadState.V8); - _memory.WriteVector128((long)address + 0x1a0, thread.Context.ThreadState.V9); - _memory.WriteVector128((long)address + 0x1b0, thread.Context.ThreadState.V10); - _memory.WriteVector128((long)address + 0x1c0, thread.Context.ThreadState.V11); - _memory.WriteVector128((long)address + 0x1d0, thread.Context.ThreadState.V12); - _memory.WriteVector128((long)address + 0x1e0, thread.Context.ThreadState.V13); - _memory.WriteVector128((long)address + 0x1f0, thread.Context.ThreadState.V14); - _memory.WriteVector128((long)address + 0x200, thread.Context.ThreadState.V15); - _memory.WriteVector128((long)address + 0x210, thread.Context.ThreadState.V16); - _memory.WriteVector128((long)address + 0x220, thread.Context.ThreadState.V17); - _memory.WriteVector128((long)address + 0x230, thread.Context.ThreadState.V18); - _memory.WriteVector128((long)address + 0x240, thread.Context.ThreadState.V19); - _memory.WriteVector128((long)address + 0x250, thread.Context.ThreadState.V20); - _memory.WriteVector128((long)address + 0x260, thread.Context.ThreadState.V21); - _memory.WriteVector128((long)address + 0x270, thread.Context.ThreadState.V22); - _memory.WriteVector128((long)address + 0x280, thread.Context.ThreadState.V23); - _memory.WriteVector128((long)address + 0x290, thread.Context.ThreadState.V24); - _memory.WriteVector128((long)address + 0x2a0, thread.Context.ThreadState.V25); - _memory.WriteVector128((long)address + 0x2b0, thread.Context.ThreadState.V26); - _memory.WriteVector128((long)address + 0x2c0, thread.Context.ThreadState.V27); - _memory.WriteVector128((long)address + 0x2d0, thread.Context.ThreadState.V28); - _memory.WriteVector128((long)address + 0x2e0, thread.Context.ThreadState.V29); - _memory.WriteVector128((long)address + 0x2f0, thread.Context.ThreadState.V30); - _memory.WriteVector128((long)address + 0x300, thread.Context.ThreadState.V31); + memory.WriteUInt64((long)address + 0x108, (ulong)thread.Context.ThreadState.Psr); - _memory.WriteInt32((long)address + 0x310, thread.Context.ThreadState.Fpcr); - _memory.WriteInt32((long)address + 0x314, thread.Context.ThreadState.Fpsr); - _memory.WriteInt64((long)address + 0x318, thread.Context.ThreadState.Tpidr); + memory.WriteVector128((long)address + 0x110, thread.Context.ThreadState.V0); + memory.WriteVector128((long)address + 0x120, thread.Context.ThreadState.V1); + memory.WriteVector128((long)address + 0x130, thread.Context.ThreadState.V2); + memory.WriteVector128((long)address + 0x140, thread.Context.ThreadState.V3); + memory.WriteVector128((long)address + 0x150, thread.Context.ThreadState.V4); + memory.WriteVector128((long)address + 0x160, thread.Context.ThreadState.V5); + memory.WriteVector128((long)address + 0x170, thread.Context.ThreadState.V6); + memory.WriteVector128((long)address + 0x180, thread.Context.ThreadState.V7); + memory.WriteVector128((long)address + 0x190, thread.Context.ThreadState.V8); + memory.WriteVector128((long)address + 0x1a0, thread.Context.ThreadState.V9); + memory.WriteVector128((long)address + 0x1b0, thread.Context.ThreadState.V10); + memory.WriteVector128((long)address + 0x1c0, thread.Context.ThreadState.V11); + memory.WriteVector128((long)address + 0x1d0, thread.Context.ThreadState.V12); + memory.WriteVector128((long)address + 0x1e0, thread.Context.ThreadState.V13); + memory.WriteVector128((long)address + 0x1f0, thread.Context.ThreadState.V14); + memory.WriteVector128((long)address + 0x200, thread.Context.ThreadState.V15); + memory.WriteVector128((long)address + 0x210, thread.Context.ThreadState.V16); + memory.WriteVector128((long)address + 0x220, thread.Context.ThreadState.V17); + memory.WriteVector128((long)address + 0x230, thread.Context.ThreadState.V18); + memory.WriteVector128((long)address + 0x240, thread.Context.ThreadState.V19); + memory.WriteVector128((long)address + 0x250, thread.Context.ThreadState.V20); + memory.WriteVector128((long)address + 0x260, thread.Context.ThreadState.V21); + memory.WriteVector128((long)address + 0x270, thread.Context.ThreadState.V22); + memory.WriteVector128((long)address + 0x280, thread.Context.ThreadState.V23); + memory.WriteVector128((long)address + 0x290, thread.Context.ThreadState.V24); + memory.WriteVector128((long)address + 0x2a0, thread.Context.ThreadState.V25); + memory.WriteVector128((long)address + 0x2b0, thread.Context.ThreadState.V26); + memory.WriteVector128((long)address + 0x2c0, thread.Context.ThreadState.V27); + memory.WriteVector128((long)address + 0x2d0, thread.Context.ThreadState.V28); + memory.WriteVector128((long)address + 0x2e0, thread.Context.ThreadState.V29); + memory.WriteVector128((long)address + 0x2f0, thread.Context.ThreadState.V30); + memory.WriteVector128((long)address + 0x300, thread.Context.ThreadState.V31); + + memory.WriteInt32((long)address + 0x310, thread.Context.ThreadState.Fpcr); + memory.WriteInt32((long)address + 0x314, thread.Context.ThreadState.Fpsr); + memory.WriteInt64((long)address + 0x318, thread.Context.ThreadState.Tpidr); return KernelResult.Success; } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs index ecda9e2d00..6e5b478251 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThreadSync.cs @@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall for (int index = 0; index < handlesCount; index++) { - int handle = _memory.ReadInt32((long)handlesPtr + index * 4); + int handle = _process.CpuMemory.ReadInt32((long)handlesPtr + index * 4); KSynchronizationObject syncObj = _process.HandleTable.GetObject(handle); diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index d9fef07e4a..47feb573eb 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -50,7 +50,7 @@ namespace Ryujinx.Tests.Cpu _entryPoint = Position; _ramPointer = Marshal.AllocHGlobal(new IntPtr(_size)); - _memory = new MemoryManager(_ramPointer, 1L << 32); + _memory = new MemoryManager(_ramPointer); _memory.Map(Position, 0, _size); Translator translator = new Translator(_memory);