Simplified bridges a lot
This commit is contained in:
parent
8126ab074d
commit
89e67ce832
3 changed files with 27 additions and 180 deletions
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue