aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs')
-rw-r--r--Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs108
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>