Optimize address translation and write tracking on the MMU (#571)
* Implement faster address translation and write tracking on the MMU * Rename MemoryAlloc to MemoryManagement, and other nits * Support multi-level page tables * Fix typo * Reword comment a bit * Support scalar vector loads/stores on the memory fast path, and minor fixes * Add missing cast * Alignment * Fix VirtualFree function signature * Change MemoryProtection enum to uint aswell for consistency
This commit is contained in:
parent
a3d46e4133
commit
5001f78b1d
24 changed files with 1005 additions and 621 deletions
|
@ -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,14 +95,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
_processLock = new object();
|
||||
_threadingLock = new object();
|
||||
|
||||
CpuMemory = new MemoryManager(system.Device.Memory.RamPointer);
|
||||
|
||||
CpuMemory.InvalidAccess += InvalidAccessHandler;
|
||||
_system = system;
|
||||
|
||||
AddressArbiter = new KAddressArbiter(system);
|
||||
|
||||
MemoryManager = new KMemoryManager(system, CpuMemory);
|
||||
|
||||
_fullTlsPages = new SortedDictionary<ulong, KTlsPageInfo>();
|
||||
_freeTlsPages = new SortedDictionary<ulong, KTlsPageInfo>();
|
||||
|
||||
|
@ -110,10 +108,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
|
||||
_threads = new LinkedList<KThread>();
|
||||
|
||||
Translator = new Translator(CpuMemory);
|
||||
|
||||
Translator.CpuTrace += CpuTraceHandler;
|
||||
|
||||
_svcHandler = new SvcHandler(system.Device, this);
|
||||
|
||||
Debugger = new HleProcessDebugger(this);
|
||||
|
@ -131,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;
|
||||
|
@ -238,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;
|
||||
|
@ -405,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:
|
||||
|
@ -1010,9 +1008,29 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
}
|
||||
}
|
||||
|
||||
private void InvalidAccessHandler(object sender, MemoryAccessEventArgs e)
|
||||
private void InitializeMemoryManager(AddressSpaceType addrSpaceType, MemoryRegion memRegion)
|
||||
{
|
||||
PrintCurrentThreadStackTrace();
|
||||
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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<KClientSession>(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);
|
||||
|
|
|
@ -62,11 +62,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|||
attributeMask,
|
||||
attributeValue);
|
||||
|
||||
if (result == KernelResult.Success)
|
||||
{
|
||||
_memory.StopObservingRegion((long)position, (long)size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -157,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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<KSynchronizationObject>(handle);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue