diff options
Diffstat (limited to 'Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs')
-rw-r--r-- | Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs | 108 |
1 files changed, 81 insertions, 27 deletions
diff --git a/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs b/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs index a183f95e..8994e9c0 100644 --- a/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs +++ b/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs @@ -42,7 +42,7 @@ namespace Ryujinx.Cpu.Jit private readonly ulong _addressSpaceSize; private readonly MemoryBlock _backingMemory; - private readonly MappingTree _mappingTree; + private readonly PageTable<ulong> _pageTable; private readonly MemoryEhMeilleure _memoryEh; @@ -68,6 +68,7 @@ namespace Ryujinx.Cpu.Jit public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize, bool unsafeMode, InvalidAccessHandler invalidAccessHandler = null) { _backingMemory = backingMemory; + _pageTable = new PageTable<ulong>(); _invalidAccessHandler = invalidAccessHandler; _unsafeMode = unsafeMode; _addressSpaceSize = addressSpaceSize; @@ -83,8 +84,6 @@ namespace Ryujinx.Cpu.Jit AddressSpaceBits = asBits; - _mappingTree = new MappingTree(asSize); - _pageBitmap = new ulong[1 << (AddressSpaceBits - (PageBits + PageToPteShift))]; MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible; @@ -151,8 +150,9 @@ namespace Ryujinx.Cpu.Jit AssertValidAddressAndSize(va, size); _addressSpace.MapView(_backingMemory, pa, va, size); + _addressSpaceMirror.MapView(_backingMemory, pa, va, size); AddMapping(va, size); - _mappingTree.Map(va, pa, size); + PtMap(va, pa, size); Tracking.Map(va, size); } @@ -166,11 +166,34 @@ namespace Ryujinx.Cpu.Jit Tracking.Unmap(va, size); RemoveMapping(va, size); - _mappingTree.Unmap(va, size); + PtUnmap(va, size); _addressSpace.UnmapView(_backingMemory, va, size); _addressSpaceMirror.UnmapView(_backingMemory, va, size); } + private void PtMap(ulong va, ulong pa, ulong size) + { + while (size != 0) + { + _pageTable.Map(va, pa); + + va += PageSize; + pa += PageSize; + size -= PageSize; + } + } + + private void PtUnmap(ulong va, ulong size) + { + while (size != 0) + { + _pageTable.Unmap(va); + + va += PageSize; + size -= PageSize; + } + } + /// <inheritdoc/> public T Read<T>(ulong va) where T : unmanaged { @@ -178,8 +201,7 @@ namespace Ryujinx.Cpu.Jit { AssertMapped(va, (ulong)Unsafe.SizeOf<T>()); - (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)Unsafe.SizeOf<T>()); - return block.Read<T>(offset); + return _addressSpaceMirror.Read<T>(va); } catch (InvalidMemoryRegionException) { @@ -219,8 +241,7 @@ namespace Ryujinx.Cpu.Jit { AssertMapped(va, (ulong)data.Length); - (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)data.Length); - block.Read(offset, data); + _addressSpaceMirror.Read(va, data); } catch (InvalidMemoryRegionException) { @@ -239,8 +260,7 @@ namespace Ryujinx.Cpu.Jit { SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), write: true); - (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)Unsafe.SizeOf<T>()); - block.Write(offset, value); + _addressSpaceMirror.Write(va, value); } catch (InvalidMemoryRegionException) { @@ -258,8 +278,7 @@ namespace Ryujinx.Cpu.Jit { SignalMemoryTracking(va, (ulong)data.Length, write: true); - (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)data.Length); - block.Write(offset, data); + _addressSpaceMirror.Write(va, data); } catch (InvalidMemoryRegionException) { @@ -277,8 +296,7 @@ namespace Ryujinx.Cpu.Jit { AssertMapped(va, (ulong)data.Length); - (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)data.Length); - block.Write(offset, data); + _addressSpaceMirror.Write(va, data); } catch (InvalidMemoryRegionException) { @@ -301,8 +319,7 @@ namespace Ryujinx.Cpu.Jit AssertMapped(va, (ulong)size); } - (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)size); - return block.GetSpan(offset, size); + return _addressSpaceMirror.GetSpan(va, size); } /// <inheritdoc/> @@ -317,8 +334,7 @@ namespace Ryujinx.Cpu.Jit AssertMapped(va, (ulong)size); } - (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)size); - return block.GetWritableRegion(offset, size); + return _addressSpaceMirror.GetWritableRegion(va, size); } /// <inheritdoc/> @@ -326,8 +342,7 @@ namespace Ryujinx.Cpu.Jit { SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), true); - (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)Unsafe.SizeOf<T>()); - return ref block.GetRef<T>(offset); + return ref _addressSpaceMirror.GetRef<T>(va); } /// <inheritdoc/> @@ -414,7 +429,51 @@ namespace Ryujinx.Cpu.Jit /// <inheritdoc/> public IEnumerable<MemoryRange> GetPhysicalRegions(ulong va, ulong size) { - return _mappingTree.GetPhysicalRegions(va, size); + int pages = GetPagesCount(va, (uint)size, out va); + + var regions = new List<MemoryRange>(); + + ulong regionStart = GetPhysicalAddressChecked(va); + ulong regionSize = PageSize; + + for (int page = 0; page < pages - 1; page++) + { + if (!ValidateAddress(va + PageSize)) + { + return null; + } + + ulong newPa = GetPhysicalAddressChecked(va + PageSize); + + if (GetPhysicalAddressChecked(va) + PageSize != newPa) + { + regions.Add(new MemoryRange(regionStart, regionSize)); + regionStart = newPa; + regionSize = 0; + } + + va += PageSize; + regionSize += PageSize; + } + + regions.Add(new MemoryRange(regionStart, regionSize)); + + return regions; + } + + private ulong GetPhysicalAddressChecked(ulong va) + { + if (!IsMapped(va)) + { + ThrowInvalidMemoryRegionException($"Not mapped: va=0x{va:X16}"); + } + + return GetPhysicalAddressInternal(va); + } + + private ulong GetPhysicalAddressInternal(ulong va) + { + return _pageTable.Read(va) + (va & PageMask); } /// <inheritdoc/> @@ -626,11 +685,6 @@ namespace Ryujinx.Cpu.Jit return new CpuSmartMultiRegionHandle(Tracking.BeginSmartGranularTracking(address, size, granularity)); } - private (MemoryBlock, ulong) GetContiguousBlock(ulong va, ulong size) - { - return _mappingTree.GetContiguousBlock(_backingMemory, _addressSpaceMirror, va, size); - } - /// <summary> /// Adds the given address mapping to the page table. /// </summary> |