/ src / Ryujinx.Cpu / Jit / HostTracked / AddressSpacePartitionMultiAllocation.cs
AddressSpacePartitionMultiAllocation.cs
  1  using Ryujinx.Memory;
  2  using System;
  3  using System.Diagnostics;
  4  
  5  namespace Ryujinx.Cpu.Jit.HostTracked
  6  {
  7      class AddressSpacePartitionMultiAllocation : IDisposable
  8      {
  9          private readonly AddressSpacePartitionAllocation _baseMemory;
 10          private AddressSpacePartitionAllocation _baseMemoryRo;
 11          private AddressSpacePartitionAllocation _baseMemoryNone;
 12  
 13          public AddressSpacePartitionMultiAllocation(AddressSpacePartitionAllocation baseMemory)
 14          {
 15              _baseMemory = baseMemory;
 16          }
 17  
 18          public void MapView(MemoryBlock srcBlock, ulong srcOffset, ulong dstOffset, ulong size)
 19          {
 20              _baseMemory.MapView(srcBlock, srcOffset, dstOffset, size);
 21  
 22              if (_baseMemoryRo.IsValid)
 23              {
 24                  _baseMemoryRo.MapView(srcBlock, srcOffset, dstOffset, size);
 25                  _baseMemoryRo.Reprotect(dstOffset, size, MemoryPermission.Read, false);
 26              }
 27          }
 28  
 29          public void LateMapView(MemoryBlock srcBlock, ulong srcOffset, ulong dstOffset, ulong size)
 30          {
 31              _baseMemoryRo.MapView(srcBlock, srcOffset, dstOffset, size);
 32              _baseMemoryRo.Reprotect(dstOffset, size, MemoryPermission.Read, false);
 33          }
 34  
 35          public void UnmapView(MemoryBlock srcBlock, ulong offset, ulong size)
 36          {
 37              _baseMemory.UnmapView(srcBlock, offset, size);
 38  
 39              if (_baseMemoryRo.IsValid)
 40              {
 41                  _baseMemoryRo.UnmapView(srcBlock, offset, size);
 42              }
 43          }
 44  
 45          public void Reprotect(ulong offset, ulong size, MemoryPermission permission, bool throwOnFail)
 46          {
 47              _baseMemory.Reprotect(offset, size, permission, throwOnFail);
 48          }
 49  
 50          public IntPtr GetPointer(ulong offset, ulong size)
 51          {
 52              return _baseMemory.GetPointer(offset, size);
 53          }
 54  
 55          public bool LazyInitMirrorForProtection(AddressSpacePartitioned addressSpace, ulong blockAddress, ulong blockSize, MemoryPermission permission)
 56          {
 57              if (permission == MemoryPermission.None && !_baseMemoryNone.IsValid)
 58              {
 59                  _baseMemoryNone = addressSpace.CreateAsPartitionAllocation(blockAddress, blockSize);
 60              }
 61              else if (permission == MemoryPermission.Read && !_baseMemoryRo.IsValid)
 62              {
 63                  _baseMemoryRo = addressSpace.CreateAsPartitionAllocation(blockAddress, blockSize);
 64  
 65                  return true;
 66              }
 67  
 68              return false;
 69          }
 70  
 71          public IntPtr GetPointerForProtection(ulong offset, ulong size, MemoryPermission permission)
 72          {
 73              AddressSpacePartitionAllocation allocation = permission switch
 74              {
 75                  MemoryPermission.ReadAndWrite => _baseMemory,
 76                  MemoryPermission.Read => _baseMemoryRo,
 77                  MemoryPermission.None => _baseMemoryNone,
 78                  _ => throw new ArgumentException($"Invalid protection \"{permission}\"."),
 79              };
 80  
 81              Debug.Assert(allocation.IsValid);
 82  
 83              return allocation.GetPointer(offset, size);
 84          }
 85  
 86          public void Dispose()
 87          {
 88              _baseMemory.Dispose();
 89  
 90              if (_baseMemoryRo.IsValid)
 91              {
 92                  _baseMemoryRo.Dispose();
 93              }
 94  
 95              if (_baseMemoryNone.IsValid)
 96              {
 97                  _baseMemoryNone.Dispose();
 98              }
 99          }
100      }
101  }