From 5ea7d77981df75f4eede220bf25926af177ef808 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 7 Feb 2021 20:54:49 -0300 Subject: [PATCH] Fix inter-process data copy on non-contiguous physical regions (#1988) --- .../HOS/Kernel/Memory/KMemoryManager.cs | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs index 5a8e8e3b20..5b6df53baf 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KMemoryManager.cs @@ -1506,15 +1506,33 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory { KProcess currentProcess = KernelStatic.GetCurrentProcess(); - serverAddress = currentProcess.MemoryManager.GetDramAddressFromVa(serverAddress); + while (size > 0) + { + ulong copySize = Math.Min(PageSize - (serverAddress & (PageSize - 1)), PageSize - (clientAddress & (PageSize - 1))); - if (toServer) - { - _context.Memory.Copy(serverAddress, GetDramAddressFromVa(clientAddress), size); - } - else - { - _context.Memory.Copy(GetDramAddressFromVa(clientAddress), serverAddress, size); + if (copySize > size) + { + copySize = size; + } + + ulong serverDramAddr = currentProcess.MemoryManager.GetDramAddressFromVa(serverAddress); + ulong clientDramAddr = GetDramAddressFromVa(clientAddress); + + if (serverDramAddr != clientDramAddr) + { + if (toServer) + { + _context.Memory.Copy(serverDramAddr, clientDramAddr, copySize); + } + else + { + _context.Memory.Copy(clientDramAddr, serverDramAddr, copySize); + } + } + + serverAddress += copySize; + clientAddress += copySize; + size -= copySize; } return KernelResult.Success;