diff options
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs')
-rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs index c75d8e69..3051d998 100644 --- a/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs +++ b/Ryujinx.HLE/HOS/Kernel/Memory/KTransferMemory.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.Memory.Range; @@ -15,6 +16,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory private readonly List<HostMemoryRange> _ranges; + private readonly SharedMemoryStorage _storage; + public ulong Address { get; private set; } public ulong Size { get; private set; } @@ -28,6 +31,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory _ranges = new List<HostMemoryRange>(); } + public KTransferMemory(KernelContext context, SharedMemoryStorage storage) : base(context) + { + _storage = storage; + Permission = KMemoryPermission.ReadAndWrite; + + _hasBeenInitialized = true; + _isMapped = false; + } + public KernelResult Initialize(ulong address, ulong size, KMemoryPermission permission) { KProcess creator = KernelStatic.GetCurrentProcess(); @@ -52,6 +64,83 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return result; } + public KernelResult MapIntoProcess( + KPageTableBase memoryManager, + ulong address, + ulong size, + KProcess process, + KMemoryPermission permission) + { + if (_storage == null) + { + throw new NotImplementedException(); + } + + ulong pagesCountRounded = BitUtils.DivRoundUp(size, KPageTableBase.PageSize); + + var pageList = _storage.GetPageList(); + if (pageList.GetPagesCount() != pagesCountRounded) + { + return KernelResult.InvalidSize; + } + + if (permission != Permission || _isMapped) + { + return KernelResult.InvalidState; + } + + MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory; + + KernelResult result = memoryManager.MapPages(address, pageList, state, KMemoryPermission.ReadAndWrite); + + if (result == KernelResult.Success) + { + _isMapped = true; + + if (!memoryManager.SupportsMemoryAliasing) + { + _storage.Borrow(process, address); + } + } + + return result; + } + + public KernelResult UnmapFromProcess( + KPageTableBase memoryManager, + ulong address, + ulong size, + KProcess process) + { + if (_storage == null) + { + throw new NotImplementedException(); + } + + ulong pagesCountRounded = BitUtils.DivRoundUp(size, KPageTableBase.PageSize); + + var pageList = _storage.GetPageList(); + ulong pagesCount = pageList.GetPagesCount(); + + if (pagesCount != pagesCountRounded) + { + return KernelResult.InvalidSize; + } + + var ranges = _storage.GetRanges(); + + MemoryState state = Permission == KMemoryPermission.None ? MemoryState.TransferMemoryIsolated : MemoryState.TransferMemory; + + KernelResult result = memoryManager.UnmapPages(address, pagesCount, ranges, state); + + if (result == KernelResult.Success) + { + _isMapped = false; + } + + return result; + } + protected override void Destroy() { if (_hasBeenInitialized) |