diff options
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs')
| -rw-r--r-- | Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs b/Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs new file mode 100644 index 00000000..cd22b65f --- /dev/null +++ b/Ryujinx.HLE/HOS/Kernel/Memory/SharedMemoryStorage.cs @@ -0,0 +1,103 @@ +using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.Memory; +using Ryujinx.Memory.Range; +using System; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Kernel.Memory +{ + class SharedMemoryStorage + { + private readonly KernelContext _context; + private readonly KPageList _pageList; + private readonly ulong _size; + + private IVirtualMemoryManager _borrowerMemory; + private ulong _borrowerVa; + + public SharedMemoryStorage(KernelContext context, KPageList pageList) + { + _context = context; + _pageList = pageList; + _size = pageList.GetPagesCount() * KPageTableBase.PageSize; + + foreach (KPageNode pageNode in pageList) + { + ulong address = pageNode.Address - DramMemoryMap.DramBase; + ulong size = pageNode.PagesCount * KPageTableBase.PageSize; + context.Memory.Commit(address, size); + } + } + + public void Borrow(KProcess dstProcess, ulong va) + { + ulong currentOffset = 0; + + foreach (KPageNode pageNode in _pageList) + { + ulong address = pageNode.Address - DramMemoryMap.DramBase; + ulong size = pageNode.PagesCount * KPageTableBase.PageSize; + + dstProcess.CpuMemory.Write(va + currentOffset, _context.Memory.GetSpan(address + currentOffset, (int)size)); + + currentOffset += size; + } + + _borrowerMemory = dstProcess.CpuMemory; + _borrowerVa = va; + } + + public void ZeroFill() + { + for (ulong offset = 0; offset < _size; offset += sizeof(ulong)) + { + GetRef<ulong>(offset) = 0; + } + } + + public ref T GetRef<T>(ulong offset) where T : unmanaged + { + if (_borrowerMemory == null) + { + if (_pageList.Nodes.Count == 1) + { + ulong address = _pageList.Nodes.First.Value.Address - DramMemoryMap.DramBase; + return ref _context.Memory.GetRef<T>(address + offset); + } + + throw new NotImplementedException("Non-contiguous shared memory is not yet supported."); + } + else + { + return ref _borrowerMemory.GetRef<T>(_borrowerVa + offset); + } + } + + public IEnumerable<HostMemoryRange> GetRanges() + { + if (_borrowerMemory == null) + { + var ranges = new List<HostMemoryRange>(); + + foreach (KPageNode pageNode in _pageList) + { + ulong address = pageNode.Address - DramMemoryMap.DramBase; + ulong size = pageNode.PagesCount * KPageTableBase.PageSize; + + ranges.Add(new HostMemoryRange(_context.Memory.GetPointer(address, size), size)); + } + + return ranges; + } + else + { + return _borrowerMemory.GetPhysicalRegions(_borrowerVa, _size); + } + } + + public KPageList GetPageList() + { + return _pageList; + } + } +} |
