|
@@ -42,7 +42,7 @@ namespace Ryujinx.Cpu.Jit
|
|
|
private readonly ulong _addressSpaceSize;
|
|
private readonly ulong _addressSpaceSize;
|
|
|
|
|
|
|
|
private readonly MemoryBlock _backingMemory;
|
|
private readonly MemoryBlock _backingMemory;
|
|
|
- private readonly PageTable<ulong> _pageTable;
|
|
|
|
|
|
|
+ private readonly MappingTree _mappingTree;
|
|
|
|
|
|
|
|
private readonly MemoryEhMeilleure _memoryEh;
|
|
private readonly MemoryEhMeilleure _memoryEh;
|
|
|
|
|
|
|
@@ -68,7 +68,6 @@ namespace Ryujinx.Cpu.Jit
|
|
|
public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize, bool unsafeMode, InvalidAccessHandler invalidAccessHandler = null)
|
|
public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize, bool unsafeMode, InvalidAccessHandler invalidAccessHandler = null)
|
|
|
{
|
|
{
|
|
|
_backingMemory = backingMemory;
|
|
_backingMemory = backingMemory;
|
|
|
- _pageTable = new PageTable<ulong>();
|
|
|
|
|
_invalidAccessHandler = invalidAccessHandler;
|
|
_invalidAccessHandler = invalidAccessHandler;
|
|
|
_unsafeMode = unsafeMode;
|
|
_unsafeMode = unsafeMode;
|
|
|
_addressSpaceSize = addressSpaceSize;
|
|
_addressSpaceSize = addressSpaceSize;
|
|
@@ -84,6 +83,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
|
|
|
|
|
AddressSpaceBits = asBits;
|
|
AddressSpaceBits = asBits;
|
|
|
|
|
|
|
|
|
|
+ _mappingTree = new MappingTree(asSize);
|
|
|
|
|
+
|
|
|
_pageBitmap = new ulong[1 << (AddressSpaceBits - (PageBits + PageToPteShift))];
|
|
_pageBitmap = new ulong[1 << (AddressSpaceBits - (PageBits + PageToPteShift))];
|
|
|
|
|
|
|
|
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
|
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
|
@@ -150,9 +151,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
AssertValidAddressAndSize(va, size);
|
|
AssertValidAddressAndSize(va, size);
|
|
|
|
|
|
|
|
_addressSpace.MapView(_backingMemory, pa, va, size);
|
|
_addressSpace.MapView(_backingMemory, pa, va, size);
|
|
|
- _addressSpaceMirror.MapView(_backingMemory, pa, va, size);
|
|
|
|
|
AddMapping(va, size);
|
|
AddMapping(va, size);
|
|
|
- PtMap(va, pa, size);
|
|
|
|
|
|
|
+ _mappingTree.Map(va, pa, size);
|
|
|
|
|
|
|
|
Tracking.Map(va, size);
|
|
Tracking.Map(va, size);
|
|
|
}
|
|
}
|
|
@@ -166,34 +166,11 @@ namespace Ryujinx.Cpu.Jit
|
|
|
Tracking.Unmap(va, size);
|
|
Tracking.Unmap(va, size);
|
|
|
|
|
|
|
|
RemoveMapping(va, size);
|
|
RemoveMapping(va, size);
|
|
|
- PtUnmap(va, size);
|
|
|
|
|
|
|
+ _mappingTree.Unmap(va, size);
|
|
|
_addressSpace.UnmapView(_backingMemory, va, size);
|
|
_addressSpace.UnmapView(_backingMemory, va, size);
|
|
|
_addressSpaceMirror.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/>
|
|
/// <inheritdoc/>
|
|
|
public T Read<T>(ulong va) where T : unmanaged
|
|
public T Read<T>(ulong va) where T : unmanaged
|
|
|
{
|
|
{
|
|
@@ -201,7 +178,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
{
|
|
{
|
|
|
AssertMapped(va, (ulong)Unsafe.SizeOf<T>());
|
|
AssertMapped(va, (ulong)Unsafe.SizeOf<T>());
|
|
|
|
|
|
|
|
- return _addressSpaceMirror.Read<T>(va);
|
|
|
|
|
|
|
+ (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)Unsafe.SizeOf<T>());
|
|
|
|
|
+ return block.Read<T>(offset);
|
|
|
}
|
|
}
|
|
|
catch (InvalidMemoryRegionException)
|
|
catch (InvalidMemoryRegionException)
|
|
|
{
|
|
{
|
|
@@ -241,7 +219,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
{
|
|
{
|
|
|
AssertMapped(va, (ulong)data.Length);
|
|
AssertMapped(va, (ulong)data.Length);
|
|
|
|
|
|
|
|
- _addressSpaceMirror.Read(va, data);
|
|
|
|
|
|
|
+ (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)data.Length);
|
|
|
|
|
+ block.Read(offset, data);
|
|
|
}
|
|
}
|
|
|
catch (InvalidMemoryRegionException)
|
|
catch (InvalidMemoryRegionException)
|
|
|
{
|
|
{
|
|
@@ -260,7 +239,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
{
|
|
{
|
|
|
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), write: true);
|
|
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), write: true);
|
|
|
|
|
|
|
|
- _addressSpaceMirror.Write(va, value);
|
|
|
|
|
|
|
+ (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)Unsafe.SizeOf<T>());
|
|
|
|
|
+ block.Write(offset, value);
|
|
|
}
|
|
}
|
|
|
catch (InvalidMemoryRegionException)
|
|
catch (InvalidMemoryRegionException)
|
|
|
{
|
|
{
|
|
@@ -274,10 +254,12 @@ namespace Ryujinx.Cpu.Jit
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
|
public void Write(ulong va, ReadOnlySpan<byte> data)
|
|
public void Write(ulong va, ReadOnlySpan<byte> data)
|
|
|
{
|
|
{
|
|
|
- try {
|
|
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
SignalMemoryTracking(va, (ulong)data.Length, write: true);
|
|
SignalMemoryTracking(va, (ulong)data.Length, write: true);
|
|
|
|
|
|
|
|
- _addressSpaceMirror.Write(va, data);
|
|
|
|
|
|
|
+ (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)data.Length);
|
|
|
|
|
+ block.Write(offset, data);
|
|
|
}
|
|
}
|
|
|
catch (InvalidMemoryRegionException)
|
|
catch (InvalidMemoryRegionException)
|
|
|
{
|
|
{
|
|
@@ -295,7 +277,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
{
|
|
{
|
|
|
AssertMapped(va, (ulong)data.Length);
|
|
AssertMapped(va, (ulong)data.Length);
|
|
|
|
|
|
|
|
- _addressSpaceMirror.Write(va, data);
|
|
|
|
|
|
|
+ (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)data.Length);
|
|
|
|
|
+ block.Write(offset, data);
|
|
|
}
|
|
}
|
|
|
catch (InvalidMemoryRegionException)
|
|
catch (InvalidMemoryRegionException)
|
|
|
{
|
|
{
|
|
@@ -318,7 +301,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
AssertMapped(va, (ulong)size);
|
|
AssertMapped(va, (ulong)size);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return _addressSpaceMirror.GetSpan(va, size);
|
|
|
|
|
|
|
+ (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)size);
|
|
|
|
|
+ return block.GetSpan(offset, size);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
@@ -333,7 +317,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
AssertMapped(va, (ulong)size);
|
|
AssertMapped(va, (ulong)size);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return _addressSpaceMirror.GetWritableRegion(va, size);
|
|
|
|
|
|
|
+ (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)size);
|
|
|
|
|
+ return block.GetWritableRegion(offset, size);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
@@ -341,7 +326,8 @@ namespace Ryujinx.Cpu.Jit
|
|
|
{
|
|
{
|
|
|
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), true);
|
|
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), true);
|
|
|
|
|
|
|
|
- return ref _addressSpaceMirror.GetRef<T>(va);
|
|
|
|
|
|
|
+ (MemoryBlock block, ulong offset) = GetContiguousBlock(va, (ulong)Unsafe.SizeOf<T>());
|
|
|
|
|
+ return ref block.GetRef<T>(offset);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
@@ -428,51 +414,7 @@ namespace Ryujinx.Cpu.Jit
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
|
public IEnumerable<MemoryRange> GetPhysicalRegions(ulong va, ulong size)
|
|
public IEnumerable<MemoryRange> GetPhysicalRegions(ulong va, ulong 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);
|
|
|
|
|
|
|
+ return _mappingTree.GetPhysicalRegions(va, size);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
@@ -684,6 +626,11 @@ namespace Ryujinx.Cpu.Jit
|
|
|
return new CpuSmartMultiRegionHandle(Tracking.BeginSmartGranularTracking(address, size, granularity));
|
|
return new CpuSmartMultiRegionHandle(Tracking.BeginSmartGranularTracking(address, size, granularity));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private (MemoryBlock, ulong) GetContiguousBlock(ulong va, ulong size)
|
|
|
|
|
+ {
|
|
|
|
|
+ return _mappingTree.GetContiguousBlock(_backingMemory, _addressSpaceMirror, va, size);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Adds the given address mapping to the page table.
|
|
/// Adds the given address mapping to the page table.
|
|
|
/// </summary>
|
|
/// </summary>
|