From 1cbca5eecbb6b7bce94dca864b5cffda4db02d39 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 3 May 2022 08:16:31 -0300 Subject: [PATCH] Implement code memory syscalls (#2958) * Implement code memory syscalls * Remove owner process validation * Add 32-bit code memory syscalls * Remove unused field --- Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs | 168 +++++++++++ .../HOS/Kernel/Memory/KPageTableBase.cs | 146 +++++++++ .../SupervisorCall/CodeMemoryOperation.cs | 10 + .../HOS/Kernel/SupervisorCall/Syscall.cs | 279 +++++++++++++++--- .../HOS/Kernel/SupervisorCall/Syscall32.cs | 62 +++- .../HOS/Kernel/SupervisorCall/Syscall64.cs | 30 +- .../HOS/Kernel/SupervisorCall/SyscallTable.cs | 8 + 7 files changed, 647 insertions(+), 56 deletions(-) create mode 100644 Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs create mode 100644 Ryujinx.HLE/HOS/Kernel/SupervisorCall/CodeMemoryOperation.cs diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs new file mode 100644 index 00000000..2df93d78 --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs @@ -0,0 +1,168 @@ +using Ryujinx.Common; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Process; +using System; +using System.Diagnostics; + +namespace Ryujinx.HLE.HOS.Kernel.Memory +{ + class KCodeMemory : KAutoObject + { + public KProcess Owner { get; private set; } + private readonly KPageList _pageList; + private readonly object _lock; + private ulong _address; + private bool _isOwnerMapped; + private bool _isMapped; + + public KCodeMemory(KernelContext context) : base(context) + { + _pageList = new KPageList(); + _lock = new object(); + } + + public KernelResult Initialize(ulong address, ulong size) + { + Owner = KernelStatic.GetCurrentProcess(); + + KernelResult result = Owner.MemoryManager.BorrowCodeMemory(_pageList, address, size); + + if (result != KernelResult.Success) + { + return result; + } + + Owner.CpuMemory.Fill(address, size, 0xff); + Owner.IncrementReferenceCount(); + + _address = address; + _isMapped = false; + _isOwnerMapped = false; + + return KernelResult.Success; + } + + public KernelResult Map(ulong address, ulong size, KMemoryPermission perm) + { + if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) + { + return KernelResult.InvalidSize; + } + + lock (_lock) + { + if (_isMapped) + { + return KernelResult.InvalidState; + } + + KProcess process = KernelStatic.GetCurrentProcess(); + + KernelResult result = process.MemoryManager.MapPages(address, _pageList, MemoryState.CodeWritable, KMemoryPermission.ReadAndWrite); + + if (result != KernelResult.Success) + { + return result; + } + + _isMapped = true; + } + + return KernelResult.Success; + } + + public KernelResult MapToOwner(ulong address, ulong size, KMemoryPermission permission) + { + if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) + { + return KernelResult.InvalidSize; + } + + lock (_lock) + { + if (_isOwnerMapped) + { + return KernelResult.InvalidState; + } + + Debug.Assert(permission == KMemoryPermission.Read || permission == KMemoryPermission.ReadAndExecute); + + KernelResult result = Owner.MemoryManager.MapPages(address, _pageList, MemoryState.CodeReadOnly, permission); + + if (result != KernelResult.Success) + { + return result; + } + + _isOwnerMapped = true; + } + + return KernelResult.Success; + } + + public KernelResult Unmap(ulong address, ulong size) + { + if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) + { + return KernelResult.InvalidSize; + } + + lock (_lock) + { + KProcess process = KernelStatic.GetCurrentProcess(); + + KernelResult result = process.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeWritable); + + if (result != KernelResult.Success) + { + return result; + } + + Debug.Assert(_isMapped); + + _isMapped = false; + } + + return KernelResult.Success; + } + + public KernelResult UnmapFromOwner(ulong address, ulong size) + { + if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) + { + return KernelResult.InvalidSize; + } + + lock (_lock) + { + KernelResult result = Owner.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeReadOnly); + + if (result != KernelResult.Success) + { + return result; + } + + Debug.Assert(_isOwnerMapped); + + _isOwnerMapped = false; + } + + return KernelResult.Success; + } + + protected override void Destroy() + { + if (!_isMapped && !_isOwnerMapped) + { + ulong size = _pageList.GetPagesCount() * KPageTableBase.PageSize; + + if (Owner.MemoryManager.UnborrowCodeMemory(_address, size, _pageList) != KernelResult.Success) + { + throw new InvalidOperationException("Unexpected failure restoring transfer memory attributes."); + } + } + + Owner.DecrementReferenceCount(); + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index 518a0f09..94e8fb6a 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -1095,6 +1095,77 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory } } + public KernelResult UnmapProcessMemory(ulong dst, ulong size, KPageTableBase srcPageTable, ulong src) + { + lock (_blockManager) + { + lock (srcPageTable._blockManager) + { + bool success = CheckRange( + dst, + size, + MemoryState.Mask, + MemoryState.ProcessMemory, + KMemoryPermission.ReadAndWrite, + KMemoryPermission.ReadAndWrite, + MemoryAttribute.Mask, + MemoryAttribute.None, + MemoryAttribute.IpcAndDeviceMapped, + out _, + out _, + out _); + + success &= srcPageTable.CheckRange( + src, + size, + MemoryState.MapProcessAllowed, + MemoryState.MapProcessAllowed, + KMemoryPermission.None, + KMemoryPermission.None, + MemoryAttribute.Mask, + MemoryAttribute.None, + MemoryAttribute.IpcAndDeviceMapped, + out _, + out _, + out _); + + if (!success) + { + return KernelResult.InvalidMemState; + } + + KPageList srcPageList = new KPageList(); + KPageList dstPageList = new KPageList(); + + srcPageTable.GetPhysicalRegions(src, size, srcPageList); + GetPhysicalRegions(dst, size, dstPageList); + + if (!dstPageList.IsEqual(srcPageList)) + { + return KernelResult.InvalidMemRange; + } + } + + if (!_slabManager.CanAllocate(MaxBlocksNeededForInsertion)) + { + return KernelResult.OutOfResource; + } + + ulong pagesCount = size / PageSize; + + KernelResult result = Unmap(dst, pagesCount); + + if (result != KernelResult.Success) + { + return result; + } + + _blockManager.InsertBlock(dst, pagesCount, MemoryState.Unmapped); + + return KernelResult.Success; + } + } + public KernelResult SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission) { lock (_blockManager) @@ -2023,6 +2094,49 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory block.RestoreIpcMappingPermission(); } + public KernelResult GetPagesIfStateEquals( + ulong address, + ulong size, + MemoryState stateMask, + MemoryState stateExpected, + KMemoryPermission permissionMask, + KMemoryPermission permissionExpected, + MemoryAttribute attributeMask, + MemoryAttribute attributeExpected, + KPageList pageList) + { + if (!InsideAddrSpace(address, size)) + { + return KernelResult.InvalidMemState; + } + + lock (_blockManager) + { + if (CheckRange( + address, + size, + stateMask | MemoryState.IsPoolAllocated, + stateExpected | MemoryState.IsPoolAllocated, + permissionMask, + permissionExpected, + attributeMask, + attributeExpected, + MemoryAttribute.IpcAndDeviceMapped, + out _, + out _, + out _)) + { + GetPhysicalRegions(address, size, pageList); + + return KernelResult.Success; + } + else + { + return KernelResult.InvalidMemState; + } + } + } + public KernelResult BorrowIpcBuffer(ulong address, ulong size) { return SetAttributesAndChangePermission( @@ -2054,6 +2168,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory pageList); } + public KernelResult BorrowCodeMemory(KPageList pageList, ulong address, ulong size) + { + return SetAttributesAndChangePermission( + address, + size, + MemoryState.CodeMemoryAllowed, + MemoryState.CodeMemoryAllowed, + KMemoryPermission.Mask, + KMemoryPermission.ReadAndWrite, + MemoryAttribute.Mask, + MemoryAttribute.None, + KMemoryPermission.None, + MemoryAttribute.Borrowed, + pageList); + } + private KernelResult SetAttributesAndChangePermission( ulong address, ulong size, @@ -2159,6 +2289,22 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory pageList); } + public KernelResult UnborrowCodeMemory(ulong address, ulong size, KPageList pageList) + { + return ClearAttributesAndChangePermission( + address, + size, + MemoryState.CodeMemoryAllowed, + MemoryState.CodeMemoryAllowed, + KMemoryPermission.None, + KMemoryPermission.None, + MemoryAttribute.Mask, + MemoryAttribute.Borrowed, + KMemoryPermission.ReadAndWrite, + MemoryAttribute.Borrowed, + pageList); + } + private KernelResult ClearAttributesAndChangePermission( ulong address, ulong size, diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/CodeMemoryOperation.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/CodeMemoryOperation.cs new file mode 100644 index 00000000..511ee99a --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/CodeMemoryOperation.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall +{ + enum CodeMemoryOperation : uint + { + Map, + MapToOwner, + Unmap, + UnmapFromOwner + }; +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index 3c6e2586..0c111bc4 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -1317,6 +1317,248 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return process.MemoryManager.UnmapPhysicalMemory(address, size); } + public KernelResult CreateCodeMemory(ulong address, ulong size, out int handle) + { + handle = 0; + + if (!PageAligned(address)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (size + address <= address) + { + return KernelResult.InvalidMemState; + } + + KCodeMemory codeMemory = new KCodeMemory(_context); + + using var _ = new OnScopeExit(codeMemory.DecrementReferenceCount); + + KProcess currentProcess = KernelStatic.GetCurrentProcess(); + + if (!currentProcess.MemoryManager.InsideAddrSpace(address, size)) + { + return KernelResult.InvalidMemState; + } + + KernelResult result = codeMemory.Initialize(address, size); + + if (result != KernelResult.Success) + { + return result; + } + + return currentProcess.HandleTable.GenerateHandle(codeMemory, out handle); + } + + public KernelResult ControlCodeMemory(int handle, CodeMemoryOperation op, ulong address, ulong size, KMemoryPermission permission) + { + KProcess currentProcess = KernelStatic.GetCurrentProcess(); + + KCodeMemory codeMemory = currentProcess.HandleTable.GetObject(handle); + + // Newer versions of the return also returns an error here if the owner and process + // where the operation will happen are the same. We do not return an error here + // because some homebrew requires this to be patched out to work (for JIT). + if (codeMemory == null /* || codeMemory.Owner == currentProcess */) + { + return KernelResult.InvalidHandle; + } + + switch (op) + { + case CodeMemoryOperation.Map: + if (!currentProcess.MemoryManager.CanContain(address, size, MemoryState.CodeWritable)) + { + return KernelResult.InvalidMemRange; + } + + if (permission != KMemoryPermission.ReadAndWrite) + { + return KernelResult.InvalidPermission; + } + + return codeMemory.Map(address, size, permission); + + case CodeMemoryOperation.MapToOwner: + if (!currentProcess.MemoryManager.CanContain(address, size, MemoryState.CodeReadOnly)) + { + return KernelResult.InvalidMemRange; + } + + if (permission != KMemoryPermission.Read && permission != KMemoryPermission.ReadAndExecute) + { + return KernelResult.InvalidPermission; + } + + return codeMemory.MapToOwner(address, size, permission); + + case CodeMemoryOperation.Unmap: + if (!currentProcess.MemoryManager.CanContain(address, size, MemoryState.CodeWritable)) + { + return KernelResult.InvalidMemRange; + } + + if (permission != KMemoryPermission.None) + { + return KernelResult.InvalidPermission; + } + + return codeMemory.Unmap(address, size); + + case CodeMemoryOperation.UnmapFromOwner: + if (!currentProcess.MemoryManager.CanContain(address, size, MemoryState.CodeReadOnly)) + { + return KernelResult.InvalidMemRange; + } + + if (permission != KMemoryPermission.None) + { + return KernelResult.InvalidPermission; + } + + return codeMemory.UnmapFromOwner(address, size); + + default: return KernelResult.InvalidEnumValue; + } + } + + public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, KMemoryPermission permission) + { + if (!PageAligned(src)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (permission != KMemoryPermission.None && + permission != KMemoryPermission.Read && + permission != KMemoryPermission.ReadAndWrite && + permission != KMemoryPermission.ReadAndExecute) + { + return KernelResult.InvalidPermission; + } + + KProcess currentProcess = KernelStatic.GetCurrentProcess(); + + KProcess targetProcess = currentProcess.HandleTable.GetObject(handle); + + if (targetProcess == null) + { + return KernelResult.InvalidHandle; + } + + if (targetProcess.MemoryManager.OutsideAddrSpace(src, size)) + { + return KernelResult.InvalidMemState; + } + + return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission); + } + + public KernelResult MapProcessMemory(ulong dst, int handle, ulong src, ulong size) + { + if (!PageAligned(src) || !PageAligned(dst)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (dst + size <= dst || src + size <= src) + { + return KernelResult.InvalidMemRange; + } + + KProcess dstProcess = KernelStatic.GetCurrentProcess(); + KProcess srcProcess = dstProcess.HandleTable.GetObject(handle); + + if (srcProcess == null) + { + return KernelResult.InvalidHandle; + } + + if (!srcProcess.MemoryManager.InsideAddrSpace(src, size) || + !dstProcess.MemoryManager.CanContain(dst, size, MemoryState.ProcessMemory)) + { + return KernelResult.InvalidMemRange; + } + + KPageList pageList = new KPageList(); + + KernelResult result = srcProcess.MemoryManager.GetPagesIfStateEquals( + src, + size, + MemoryState.MapProcessAllowed, + MemoryState.MapProcessAllowed, + KMemoryPermission.None, + KMemoryPermission.None, + MemoryAttribute.Mask, + MemoryAttribute.None, + pageList); + + if (result != KernelResult.Success) + { + return result; + } + + return dstProcess.MemoryManager.MapPages(dst, pageList, MemoryState.ProcessMemory, KMemoryPermission.ReadAndWrite); + } + + public KernelResult UnmapProcessMemory(ulong dst, int handle, ulong src, ulong size) + { + if (!PageAligned(src) || !PageAligned(dst)) + { + return KernelResult.InvalidAddress; + } + + if (!PageAligned(size) || size == 0) + { + return KernelResult.InvalidSize; + } + + if (dst + size <= dst || src + size <= src) + { + return KernelResult.InvalidMemRange; + } + + KProcess dstProcess = KernelStatic.GetCurrentProcess(); + KProcess srcProcess = dstProcess.HandleTable.GetObject(handle); + + if (srcProcess == null) + { + return KernelResult.InvalidHandle; + } + + if (!srcProcess.MemoryManager.InsideAddrSpace(src, size) || + !dstProcess.MemoryManager.CanContain(dst, size, MemoryState.ProcessMemory)) + { + return KernelResult.InvalidMemRange; + } + + KernelResult result = dstProcess.MemoryManager.UnmapProcessMemory(dst, size, srcProcess.MemoryManager, src); + + if (result != KernelResult.Success) + { + return result; + } + + return KernelResult.Success; + } + public KernelResult MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) { if (!PageAligned(dst) || !PageAligned(src)) @@ -1391,43 +1633,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size); } - public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, KMemoryPermission permission) - { - if (!PageAligned(src)) - { - return KernelResult.InvalidAddress; - } - - if (!PageAligned(size) || size == 0) - { - return KernelResult.InvalidSize; - } - - if (permission != KMemoryPermission.None && - permission != KMemoryPermission.Read && - permission != KMemoryPermission.ReadAndWrite && - permission != KMemoryPermission.ReadAndExecute) - { - return KernelResult.InvalidPermission; - } - - KProcess currentProcess = KernelStatic.GetCurrentProcess(); - - KProcess targetProcess = currentProcess.HandleTable.GetObject(handle); - - if (targetProcess == null) - { - return KernelResult.InvalidHandle; - } - - if (targetProcess.MemoryManager.OutsideAddrSpace(src, size)) - { - return KernelResult.InvalidMemState; - } - - return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission); - } - private static bool PageAligned(ulong address) { return (address & (KPageTableBase.PageSize - 1)) == 0; diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs index bf4eee79..27ff8ef7 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs @@ -143,6 +143,26 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.CreateTransferMemory(out handle, address, size, permission); } + public KernelResult CreateCodeMemory32([R(1)] uint address, [R(2)] uint size, [R(1)] out int handle) + { + return _syscall.CreateCodeMemory(address, size, out handle); + } + + public KernelResult ControlCodeMemory32( + [R(0)] int handle, + [R(1)] CodeMemoryOperation op, + [R(2)] uint addressLow, + [R(3)] uint addressHigh, + [R(4)] uint sizeLow, + [R(5)] uint sizeHigh, + [R(6)] KMemoryPermission permission) + { + ulong address = addressLow | ((ulong)addressHigh << 32); + ulong size = sizeLow | ((ulong)sizeHigh << 32); + + return _syscall.ControlCodeMemory(handle, op, address, size, permission); + } + public KernelResult MapTransferMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size, [R(3)] KMemoryPermission permission) { return _syscall.MapTransferMemory(handle, address, size, permission); @@ -163,6 +183,34 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.UnmapPhysicalMemory(address, size); } + public KernelResult SetProcessMemoryPermission32( + [R(0)] int handle, + [R(1)] uint sizeLow, + [R(2)] uint srcLow, + [R(3)] uint srcHigh, + [R(4)] uint sizeHigh, + [R(5)] KMemoryPermission permission) + { + ulong src = srcLow | ((ulong)srcHigh << 32); + ulong size = sizeLow | ((ulong)sizeHigh << 32); + + return _syscall.SetProcessMemoryPermission(handle, src, size, permission); + } + + public KernelResult MapProcessMemory32([R(0)] uint dst, [R(1)] int handle, [R(2)] uint srcLow, [R(3)] uint srcHigh, [R(4)] uint size) + { + ulong src = srcLow | ((ulong)srcHigh << 32); + + return _syscall.MapProcessMemory(dst, handle, src, size); + } + + public KernelResult UnmapProcessMemory32([R(0)] uint dst, [R(1)] int handle, [R(2)] uint srcLow, [R(3)] uint srcHigh, [R(4)] uint size) + { + ulong src = srcLow | ((ulong)srcHigh << 32); + + return _syscall.UnmapProcessMemory(dst, handle, src, size); + } + public KernelResult MapProcessCodeMemory32([R(0)] int handle, [R(1)] uint srcLow, [R(2)] uint dstLow, [R(3)] uint dstHigh, [R(4)] uint srcHigh, [R(5)] uint sizeLow, [R(6)] uint sizeHigh) { ulong src = srcLow | ((ulong)srcHigh << 32); @@ -181,20 +229,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.UnmapProcessCodeMemory(handle, dst, src, size); } - public KernelResult SetProcessMemoryPermission32( - [R(0)] int handle, - [R(1)] uint sizeLow, - [R(2)] uint srcLow, - [R(3)] uint srcHigh, - [R(4)] uint sizeHigh, - [R(5)] KMemoryPermission permission) - { - ulong src = srcLow | ((ulong)srcHigh << 32); - ulong size = sizeLow | ((ulong)sizeHigh << 32); - - return _syscall.SetProcessMemoryPermission(handle, src, size, permission); - } - // System public void ExitProcess32() diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs index 2af736d8..76e85379 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs @@ -160,6 +160,16 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.CreateTransferMemory(out handle, address, size, permission); } + public KernelResult CreateCodeMemory64([R(1)] ulong address, [R(2)] ulong size, [R(1)] out int handle) + { + return _syscall.CreateCodeMemory(address, size, out handle); + } + + public KernelResult ControlCodeMemory64([R(0)] int handle, [R(1)] CodeMemoryOperation op, [R(2)] ulong address, [R(3)] ulong size, [R(4)] KMemoryPermission permission) + { + return _syscall.ControlCodeMemory(handle, op, address, size, permission); + } + public KernelResult MapTransferMemory64([R(0)] int handle, [R(1)] ulong address, [R(2)] ulong size, [R(3)] KMemoryPermission permission) { return _syscall.MapTransferMemory(handle, address, size, permission); @@ -180,6 +190,21 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.UnmapPhysicalMemory(address, size); } + public KernelResult SetProcessMemoryPermission64([R(0)] int handle, [R(1)] ulong src, [R(2)] ulong size, [R(3)] KMemoryPermission permission) + { + return _syscall.SetProcessMemoryPermission(handle, src, size, permission); + } + + public KernelResult MapProcessMemory64([R(0)] ulong dst, [R(1)] int handle, [R(2)] ulong src, [R(3)] ulong size) + { + return _syscall.MapProcessMemory(dst, handle, src, size); + } + + public KernelResult UnmapProcessMemory64([R(0)] ulong dst, [R(1)] int handle, [R(2)] ulong src, [R(3)] ulong size) + { + return _syscall.UnmapProcessMemory(dst, handle, src, size); + } + public KernelResult MapProcessCodeMemory64([R(0)] int handle, [R(1)] ulong dst, [R(2)] ulong src, [R(3)] ulong size) { return _syscall.MapProcessCodeMemory(handle, dst, src, size); @@ -190,11 +215,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall return _syscall.UnmapProcessCodeMemory(handle, dst, src, size); } - public KernelResult SetProcessMemoryPermission64([R(0)] int handle, [R(1)] ulong src, [R(2)] ulong size, [R(3)] KMemoryPermission permission) - { - return _syscall.SetProcessMemoryPermission(handle, src, size, permission); - } - // System public void ExitProcess64() diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs index 29e7ce16..6e0b7010 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs @@ -78,6 +78,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { 0x43, nameof(Syscall64.ReplyAndReceive64) }, { 0x44, nameof(Syscall64.ReplyAndReceiveWithUserBuffer64) }, { 0x45, nameof(Syscall64.CreateEvent64) }, + { 0x4b, nameof(Syscall64.CreateCodeMemory64) }, + { 0x4c, nameof(Syscall64.ControlCodeMemory64) }, { 0x51, nameof(Syscall64.MapTransferMemory64) }, { 0x52, nameof(Syscall64.UnmapTransferMemory64) }, { 0x65, nameof(Syscall64.GetProcessList64) }, @@ -86,6 +88,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { 0x71, nameof(Syscall64.ManageNamedPort64) }, { 0x72, nameof(Syscall64.ConnectToPort64) }, { 0x73, nameof(Syscall64.SetProcessMemoryPermission64) }, + { 0x74, nameof(Syscall64.MapProcessMemory64) }, + { 0x75, nameof(Syscall64.UnmapProcessMemory64) }, { 0x77, nameof(Syscall64.MapProcessCodeMemory64) }, { 0x78, nameof(Syscall64.UnmapProcessCodeMemory64) }, { 0x7B, nameof(Syscall64.TerminateProcess64) }, @@ -152,6 +156,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { 0x41, nameof(Syscall32.AcceptSession32) }, { 0x43, nameof(Syscall32.ReplyAndReceive32) }, { 0x45, nameof(Syscall32.CreateEvent32) }, + { 0x4b, nameof(Syscall32.CreateCodeMemory32) }, + { 0x4c, nameof(Syscall32.ControlCodeMemory32) }, { 0x51, nameof(Syscall32.MapTransferMemory32) }, { 0x52, nameof(Syscall32.UnmapTransferMemory32) }, { 0x5F, nameof(Syscall32.FlushProcessDataCache32) }, @@ -161,6 +167,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { 0x71, nameof(Syscall32.ManageNamedPort32) }, { 0x72, nameof(Syscall32.ConnectToPort32) }, { 0x73, nameof(Syscall32.SetProcessMemoryPermission32) }, + { 0x74, nameof(Syscall32.MapProcessMemory32) }, + { 0x75, nameof(Syscall32.UnmapProcessMemory32) }, { 0x77, nameof(Syscall32.MapProcessCodeMemory32) }, { 0x78, nameof(Syscall32.UnmapProcessCodeMemory32) }, { 0x7B, nameof(Syscall32.TerminateProcess32) },