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 }