Simplified bridges a lot

This commit is contained in:
Gabriel A 2024-03-14 21:02:56 -03:00
parent 8126ab074d
commit 89e67ce832
3 changed files with 27 additions and 180 deletions

View file

@ -208,9 +208,6 @@ namespace Ryujinx.Cpu.Jit
private ulong _cachedFirstPagePa;
private ulong _cachedLastPagePa;
private MemoryBlock _firstPageMemoryForUnmap;
private MemoryBlock _lastPageMemoryForUnmap;
private bool _hasBridgeAtEnd;
private MemoryPermission _lastPageProtection;
public ulong Address { get; }
public ulong Size { get; }
@ -233,7 +230,6 @@ namespace Ryujinx.Cpu.Jit
_cachedFirstPagePa = ulong.MaxValue;
_cachedLastPagePa = ulong.MaxValue;
_lastPageProtection = MemoryPermission.ReadAndWrite;
Address = address;
Size = size;
@ -297,20 +293,6 @@ namespace Ryujinx.Cpu.Jit
Debug.Assert(va + size <= EndAddress);
_baseMemory.Reprotect(va - Address, size, protection, false);
if (va + size > EndAddress - _hostPageSize)
{
// Protections at the last page also applies to the bridge, if we have one.
// (This is because last page access is always done on the bridge, not on our base mapping,
// for the cases where access crosses a page boundary and reaches the non-contiguous next mapping).
if (_hasBridgeAtEnd)
{
_baseMemory.Reprotect(Size, _hostPageSize, protection, false);
}
_lastPageProtection = protection;
}
}
public void Reprotect(
@ -325,26 +307,6 @@ namespace Ryujinx.Cpu.Jit
LateMap();
}
ulong lastPageAddress = EndAddress - GuestPageSize;
if (va + size > lastPageAddress)
{
// Protections at the last page also applies to the bridge, if we have one.
// (This is because last page access is always done on the bridge, not on our base mapping,
// for the cases where access crosses a page boundary and reaches the non-contiguous next mapping).
if (_hasBridgeAtEnd)
{
IntPtr ptPtr = _baseMemory.GetPointerForProtection(Size, _hostPageSize, protection);
updatePtCallback(lastPageAddress, ptPtr + (IntPtr)(_hostPageSize - GuestPageSize), GuestPageSize);
}
_lastPageProtection = protection;
size = lastPageAddress - va;
}
updatePtCallback(va, _baseMemory.GetPointerForProtection(va - Address, size, protection), size);
}
@ -353,72 +315,32 @@ namespace Ryujinx.Cpu.Jit
Debug.Assert(va >= Address);
Debug.Assert(va + size <= EndAddress);
if (va >= EndAddress - GuestPageSize && _hasBridgeAtEnd)
{
return _baseMemory.GetPointer(Size + (_hostPageSize - GuestPageSize), size);
}
return _baseMemory.GetPointer(va - Address, size);
}
public void InsertBridgeAtEnd(AddressSpacePartition partitionAfter, Action<ulong, IntPtr, ulong> updatePtCallback, bool useProtectionMirrors)
public void InsertBridgeAtEnd(AddressSpacePartition partitionAfter)
{
ulong firstPagePa = partitionAfter._firstPagePa ?? ulong.MaxValue;
ulong firstPagePa = partitionAfter?._firstPagePa ?? ulong.MaxValue;
ulong lastPagePa = _lastPagePa ?? ulong.MaxValue;
if (firstPagePa != _cachedFirstPagePa || lastPagePa != _cachedLastPagePa)
{
if (partitionAfter._firstPagePa.HasValue && _lastPagePa.HasValue)
if (partitionAfter != null && partitionAfter._firstPagePa.HasValue)
{
(MemoryBlock firstPageMemory, ulong firstPageOffset) = partitionAfter.GetFirstPageMemoryAndOffset();
(MemoryBlock lastPageMemory, ulong lastPageOffset) = GetLastPageMemoryAndOffset();
_baseMemory.MapView(lastPageMemory, lastPageOffset, Size, _hostPageSize);
_baseMemory.MapView(firstPageMemory, firstPageOffset, Size + _hostPageSize, _hostPageSize);
IntPtr ptPtr;
if (useProtectionMirrors)
{
ptPtr = _baseMemory.GetPointerForProtection(Size, _hostPageSize, _lastPageProtection);
}
else
{
_baseMemory.Reprotect(Size, _hostPageSize, _lastPageProtection, false);
ptPtr = _baseMemory.GetPointer(Size, _hostPageSize);
}
updatePtCallback(EndAddress - GuestPageSize, ptPtr + (IntPtr)(_hostPageSize - GuestPageSize), GuestPageSize);
_baseMemory.MapView(firstPageMemory, firstPageOffset, Size, _hostPageSize);
_firstPageMemoryForUnmap = firstPageMemory;
_lastPageMemoryForUnmap = lastPageMemory;
_hasBridgeAtEnd = true;
}
else
{
IntPtr ptPtr = useProtectionMirrors
? _baseMemory.GetPointerForProtection(Size - _hostPageSize, _hostPageSize, _lastPageProtection)
: _baseMemory.GetPointer(Size - _hostPageSize, _hostPageSize);
updatePtCallback(EndAddress - GuestPageSize, ptPtr + (IntPtr)(_hostPageSize - GuestPageSize), GuestPageSize);
MemoryBlock firstPageMemoryForUnmap = _firstPageMemoryForUnmap;
MemoryBlock lastPageMemoryForUnmap = _lastPageMemoryForUnmap;
if (firstPageMemoryForUnmap != null)
{
_baseMemory.UnmapView(firstPageMemoryForUnmap, Size + _hostPageSize, _hostPageSize);
_baseMemory.UnmapView(firstPageMemoryForUnmap, Size, _hostPageSize);
_firstPageMemoryForUnmap = null;
}
if (lastPageMemoryForUnmap != null)
{
_baseMemory.UnmapView(lastPageMemoryForUnmap, Size, _hostPageSize);
_lastPageMemoryForUnmap = null;
}
_hasBridgeAtEnd = false;
}
_cachedFirstPagePa = firstPagePa;
@ -426,35 +348,6 @@ namespace Ryujinx.Cpu.Jit
}
}
public void RemoveBridgeFromEnd(Action<ulong, IntPtr, ulong> updatePtCallback, bool useProtectionMirrors)
{
IntPtr ptPtr = useProtectionMirrors
? _baseMemory.GetPointerForProtection(Size - _hostPageSize, _hostPageSize, _lastPageProtection)
: _baseMemory.GetPointer(Size - _hostPageSize, _hostPageSize);
updatePtCallback(EndAddress - GuestPageSize, ptPtr + (IntPtr)(_hostPageSize - GuestPageSize), GuestPageSize);
MemoryBlock firstPageMemoryForUnmap = _firstPageMemoryForUnmap;
MemoryBlock lastPageMemoryForUnmap = _lastPageMemoryForUnmap;
if (firstPageMemoryForUnmap != null)
{
_baseMemory.UnmapView(firstPageMemoryForUnmap, Size + _hostPageSize, _hostPageSize);
_firstPageMemoryForUnmap = null;
}
if (lastPageMemoryForUnmap != null)
{
_baseMemory.UnmapView(lastPageMemoryForUnmap, Size, _hostPageSize);
_lastPageMemoryForUnmap = null;
}
_cachedFirstPagePa = ulong.MaxValue;
_cachedLastPagePa = ulong.MaxValue;
_hasBridgeAtEnd = false;
}
private (MemoryBlock, ulong) GetFirstPageMemoryAndOffset()
{
_treeLock.EnterReadLock();
@ -476,29 +369,6 @@ namespace Ryujinx.Cpu.Jit
return (_backingMemory, _firstPagePa.Value);
}
private (MemoryBlock, ulong) GetLastPageMemoryAndOffset()
{
_treeLock.EnterReadLock();
try
{
ulong pageAddress = EndAddress - _hostPageSize;
PrivateMapping map = _privateTree.GetNode(pageAddress);
if (map != null && map.PrivateAllocation.IsValid)
{
return (map.PrivateAllocation.Memory, map.PrivateAllocation.Offset + (pageAddress - map.Address));
}
}
finally
{
_treeLock.ExitReadLock();
}
return (_backingMemory, _lastPagePa.Value & ~(_hostPageSize - 1));
}
public PrivateRange GetPrivateAllocation(ulong va)
{
_treeLock.EnterReadLock();

View file

@ -23,9 +23,9 @@ namespace Ryujinx.Cpu.Jit
_allocation = allocation;
}
public void RegisterMapping(ulong va, ulong endVa, int bridgeSize)
public void RegisterMapping(ulong va, ulong endVa)
{
_allocation.Block.AddMapping(_allocation.Offset, _allocation.Size, va, endVa, bridgeSize);
_allocation.Block.AddMapping(_allocation.Offset, _allocation.Size, va, endVa);
}
public void MapView(MemoryBlock srcBlock, ulong srcOffset, ulong dstOffset, ulong size)
@ -72,15 +72,13 @@ namespace Ryujinx.Cpu.Jit
public ulong EndAddress => Address + Size;
public ulong Va { get; }
public ulong EndVa { get; }
public int BridgeSize { get; }
public Mapping(ulong address, ulong size, ulong va, ulong endVa, int bridgeSize)
public Mapping(ulong address, ulong size, ulong va, ulong endVa)
{
Address = address;
Size = size;
Va = va;
EndVa = endVa;
BridgeSize = bridgeSize;
}
public int CompareTo(Mapping other)
@ -128,9 +126,9 @@ namespace Ryujinx.Cpu.Jit
_lock = locker;
}
public void AddMapping(ulong offset, ulong size, ulong va, ulong endVa, int bridgeSize)
public void AddMapping(ulong offset, ulong size, ulong va, ulong endVa)
{
_mappingTree.Add(new(offset, size, va, endVa, bridgeSize));
_mappingTree.Add(new(offset, size, va, endVa));
}
public void RemoveMapping(ulong offset, ulong size)
@ -154,11 +152,6 @@ namespace Ryujinx.Cpu.Jit
address -= map.Address;
if (address >= (map.EndVa - map.Va))
{
address -= (ulong)(map.BridgeSize / 2);
}
ulong addressAligned = BitUtils.AlignDown(address, AddressSpacePartition.GuestPageSize);
ulong endAddressAligned = BitUtils.AlignUp(address + size, AddressSpacePartition.GuestPageSize);
ulong sizeAligned = endAddressAligned - addressAligned;
@ -193,18 +186,10 @@ namespace Ryujinx.Cpu.Jit
_lock = locker;
}
public AddressSpacePartitionAllocation Allocate(ulong va, ulong size, int bridgeSize)
{
AddressSpacePartitionAllocation allocation = new(this, Allocate(size + (ulong)bridgeSize, MemoryBlock.GetPageSize(), CreateBlock));
allocation.RegisterMapping(va, va + size, bridgeSize);
return allocation;
}
public AddressSpacePartitionAllocation AllocatePage(ulong va, ulong size)
public AddressSpacePartitionAllocation Allocate(ulong va, ulong size)
{
AddressSpacePartitionAllocation allocation = new(this, Allocate(size, MemoryBlock.GetPageSize(), CreateBlock));
allocation.RegisterMapping(va, va + size, 0);
allocation.RegisterMapping(va, va + size);
return allocation;
}

View file

@ -49,7 +49,7 @@ namespace Ryujinx.Cpu.Jit
va += currentSize;
pa += currentSize;
InsertBridgeIfNeeded(partitionIndex);
InsertOrRemoveBridgeIfNeeded(partitionIndex);
}
}
}
@ -80,7 +80,7 @@ namespace Ryujinx.Cpu.Jit
va += clampedEndVa - clampedVa;
RemoveBridgeIfNeeded(partitionIndex);
InsertOrRemoveBridgeIfNeeded(partitionIndex);
if (partition.IsEmpty())
{
@ -181,33 +181,27 @@ namespace Ryujinx.Cpu.Jit
return false;
}
private void InsertBridgeIfNeeded(int partitionIndex)
private void InsertOrRemoveBridgeIfNeeded(int partitionIndex)
{
if (partitionIndex > 0 && _partitions[partitionIndex - 1].EndAddress == _partitions[partitionIndex].Address)
if (partitionIndex > 0)
{
_partitions[partitionIndex - 1].InsertBridgeAtEnd(_partitions[partitionIndex], _updatePtCallback, _useProtectionMirrors);
if (_partitions[partitionIndex - 1].EndAddress == _partitions[partitionIndex].Address)
{
_partitions[partitionIndex - 1].InsertBridgeAtEnd(_partitions[partitionIndex]);
}
else
{
_partitions[partitionIndex - 1].InsertBridgeAtEnd(null);
}
}
if (partitionIndex + 1 < _partitions.Count && _partitions[partitionIndex].EndAddress == _partitions[partitionIndex + 1].Address)
{
_partitions[partitionIndex].InsertBridgeAtEnd(_partitions[partitionIndex + 1], _updatePtCallback, _useProtectionMirrors);
}
}
private void RemoveBridgeIfNeeded(int partitionIndex)
{
if (partitionIndex > 0 && _partitions[partitionIndex - 1].EndAddress == _partitions[partitionIndex].Address)
{
_partitions[partitionIndex - 1].InsertBridgeAtEnd(_partitions[partitionIndex], _updatePtCallback, _useProtectionMirrors);
}
if (partitionIndex + 1 < _partitions.Count && _partitions[partitionIndex].EndAddress == _partitions[partitionIndex + 1].Address)
{
_partitions[partitionIndex].InsertBridgeAtEnd(_partitions[partitionIndex + 1], _updatePtCallback, _useProtectionMirrors);
_partitions[partitionIndex].InsertBridgeAtEnd(_partitions[partitionIndex + 1]);
}
else
{
_partitions[partitionIndex].RemoveBridgeFromEnd(_updatePtCallback, _useProtectionMirrors);
_partitions[partitionIndex].InsertBridgeAtEnd(null);
}
}
@ -360,9 +354,7 @@ namespace Ryujinx.Cpu.Jit
public AddressSpacePartitionAllocation CreateAsPartitionAllocation(ulong va, ulong size)
{
ulong bridgeSize = MemoryBlock.GetPageSize() * 2;
return _asAllocator.Allocate(va, size, (int)bridgeSize);
return _asAllocator.Allocate(va, size + MemoryBlock.GetPageSize());
}
protected virtual void Dispose(bool disposing)