diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KCodeMemory.cs new file mode 100644 index 000000000000..2df93d789ac7 --- /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 518a0f09668a..94e8fb6a1e3d 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -1095,6 +1095,77 @@ public KernelResult Unmap(ulong dst, ulong src, ulong size) } } + 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 @@ private static void RestoreIpcMappingPermissions(KMemoryBlock block, KMemoryPerm 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 @@ public KernelResult BorrowTransferMemory(KPageList pageList, ulong address, ulon 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 @@ public KernelResult UnborrowTransferMemory(ulong address, ulong size, KPageList 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 000000000000..511ee99af945 --- /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 3c6e2586da35..0c111bc44946 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -1317,9 +1317,11 @@ public KernelResult UnmapPhysicalMemory(ulong address, ulong size) return process.MemoryManager.UnmapPhysicalMemory(address, size); } - public KernelResult MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) + public KernelResult CreateCodeMemory(ulong address, ulong size, out int handle) { - if (!PageAligned(dst) || !PageAligned(src)) + handle = 0; + + if (!PageAligned(address)) { return KernelResult.InvalidAddress; } @@ -1329,6 +1331,124 @@ public KernelResult MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong 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); @@ -1338,23 +1458,108 @@ public KernelResult MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong return KernelResult.InvalidHandle; } - if (targetProcess.MemoryManager.OutsideAddrSpace(dst, size) || - targetProcess.MemoryManager.OutsideAddrSpace(src, size) || - targetProcess.MemoryManager.InsideAliasRegion(dst, size) || - targetProcess.MemoryManager.InsideHeapRegion(dst, size)) + 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; } - if (size + dst <= dst || size + src <= src) + KProcess dstProcess = KernelStatic.GetCurrentProcess(); + KProcess srcProcess = dstProcess.HandleTable.GetObject(handle); + + if (srcProcess == null) { - return KernelResult.InvalidMemState; + return KernelResult.InvalidHandle; } - return targetProcess.MemoryManager.MapProcessCodeMemory(dst, src, size); + 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 UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) + 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)) { @@ -1388,12 +1593,12 @@ public KernelResult UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulo return KernelResult.InvalidMemState; } - return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size); + return targetProcess.MemoryManager.MapProcessCodeMemory(dst, src, size); } - public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, KMemoryPermission permission) + public KernelResult UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) { - if (!PageAligned(src)) + if (!PageAligned(dst) || !PageAligned(src)) { return KernelResult.InvalidAddress; } @@ -1403,14 +1608,6 @@ public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size 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); @@ -1420,12 +1617,20 @@ public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size return KernelResult.InvalidHandle; } - if (targetProcess.MemoryManager.OutsideAddrSpace(src, size)) + if (targetProcess.MemoryManager.OutsideAddrSpace(dst, size) || + targetProcess.MemoryManager.OutsideAddrSpace(src, size) || + targetProcess.MemoryManager.InsideAliasRegion(dst, size) || + targetProcess.MemoryManager.InsideHeapRegion(dst, size)) + { + return KernelResult.InvalidMemRange; + } + + if (size + dst <= dst || size + src <= src) { return KernelResult.InvalidMemState; } - return targetProcess.MemoryManager.SetProcessMemoryPermission(src, size, permission); + return targetProcess.MemoryManager.UnmapProcessCodeMemory(dst, src, size); } private static bool PageAligned(ulong address) diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs index bf4eee79781a..27ff8ef7f20a 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs @@ -143,6 +143,26 @@ public KernelResult CreateTransferMemory32( 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,36 +183,50 @@ public KernelResult UnmapPhysicalMemory32([R(0)] uint address, [R(1)] uint size) return _syscall.UnmapPhysicalMemory(address, 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) + 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 dst = dstLow | ((ulong)dstHigh << 32); ulong size = sizeLow | ((ulong)sizeHigh << 32); - return _syscall.MapProcessCodeMemory(handle, dst, src, size); + return _syscall.SetProcessMemoryPermission(handle, src, size, permission); } - public KernelResult UnmapProcessCodeMemory32([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) + 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); ulong dst = dstLow | ((ulong)dstHigh << 32); ulong size = sizeLow | ((ulong)sizeHigh << 32); - return _syscall.UnmapProcessCodeMemory(handle, dst, src, size); + return _syscall.MapProcessCodeMemory(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) + public KernelResult UnmapProcessCodeMemory32([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); + ulong dst = dstLow | ((ulong)dstHigh << 32); ulong size = sizeLow | ((ulong)sizeHigh << 32); - return _syscall.SetProcessMemoryPermission(handle, src, size, permission); + return _syscall.UnmapProcessCodeMemory(handle, dst, src, size); } // System diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs index 2af736d8afd7..76e853799f37 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs @@ -160,6 +160,16 @@ public KernelResult CreateTransferMemory64( 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 @@ public KernelResult UnmapPhysicalMemory64([R(0)] ulong address, [R(1)] ulong siz 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 @@ public KernelResult UnmapProcessCodeMemory64([R(0)] int handle, [R(1)] ulong dst 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 29e7ce160d9d..6e0b7010014c 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs @@ -78,6 +78,8 @@ static SyscallTable() { 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 @@ static SyscallTable() { 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 @@ static SyscallTable() { 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 @@ static SyscallTable() { 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) },