Merge aa44e70b32
into 7124d679fd
This commit is contained in:
commit
cbedc2d380
14 changed files with 150 additions and 54 deletions
|
@ -10,7 +10,7 @@ namespace ARMeilleure.Memory
|
||||||
|
|
||||||
MemoryManagerType Type { get; }
|
MemoryManagerType Type { get; }
|
||||||
|
|
||||||
event Action<ulong, ulong> UnmapEvent;
|
event Action<ulong, ulong, bool> UnmapEvent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads data from CPU mapped memory.
|
/// Reads data from CPU mapped memory.
|
||||||
|
|
|
@ -496,7 +496,7 @@ namespace ARMeilleure.Translation
|
||||||
context.MarkLabel(lblExit);
|
context.MarkLabel(lblExit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InvalidateJitCacheRegion(ulong address, ulong size)
|
public void InvalidateJitCacheRegion(ulong address, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
ulong[] overlapAddresses = Array.Empty<ulong>();
|
ulong[] overlapAddresses = Array.Empty<ulong>();
|
||||||
|
|
||||||
|
@ -508,6 +508,11 @@ namespace ARMeilleure.Translation
|
||||||
ClearRejitQueue(allowRequeue: true);
|
ClearRejitQueue(allowRequeue: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (clearRejitQueueOnly)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int index = 0; index < overlapsCount; index++)
|
for (int index = 0; index < overlapsCount; index++)
|
||||||
{
|
{
|
||||||
ulong overlapAddress = overlapAddresses[index];
|
ulong overlapAddress = overlapAddresses[index];
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
|
|
||||||
public MemoryTracking Tracking { get; }
|
public MemoryTracking Tracking { get; }
|
||||||
|
|
||||||
public event Action<ulong, ulong> UnmapEvent;
|
public event Action<ulong, ulong, bool> UnmapEvent;
|
||||||
|
|
||||||
protected override ulong AddressSpaceSize { get; }
|
protected override ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
|
@ -103,11 +103,11 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Unmap(ulong va, ulong size)
|
public void Unmap(ulong va, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
AssertValidAddressAndSize(va, size);
|
AssertValidAddressAndSize(va, size);
|
||||||
|
|
||||||
UnmapEvent?.Invoke(va, size);
|
UnmapEvent?.Invoke(va, size, clearRejitQueueOnly);
|
||||||
Tracking.Unmap(va, size);
|
Tracking.Unmap(va, size);
|
||||||
|
|
||||||
_pages.RemoveMapping(va, size);
|
_pages.RemoveMapping(va, size);
|
||||||
|
|
|
@ -23,9 +23,9 @@ namespace Ryujinx.Cpu.Jit
|
||||||
memory.UnmapEvent += UnmapHandler;
|
memory.UnmapEvent += UnmapHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UnmapHandler(ulong address, ulong size)
|
private void UnmapHandler(ulong address, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
_translator.InvalidateJitCacheRegion(address, size);
|
_translator.InvalidateJitCacheRegion(address, size, clearRejitQueueOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace Ryujinx.Cpu.Jit
|
||||||
|
|
||||||
public MemoryTracking Tracking { get; }
|
public MemoryTracking Tracking { get; }
|
||||||
|
|
||||||
public event Action<ulong, ulong> UnmapEvent;
|
public event Action<ulong, ulong, bool> UnmapEvent;
|
||||||
|
|
||||||
protected override ulong AddressSpaceSize { get; }
|
protected override ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ namespace Ryujinx.Cpu.Jit
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Unmap(ulong va, ulong size)
|
public void Unmap(ulong va, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
// If size is 0, there's nothing to unmap, just exit early.
|
// If size is 0, there's nothing to unmap, just exit early.
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
|
@ -114,7 +114,7 @@ namespace Ryujinx.Cpu.Jit
|
||||||
|
|
||||||
AssertValidAddressAndSize(va, size);
|
AssertValidAddressAndSize(va, size);
|
||||||
|
|
||||||
UnmapEvent?.Invoke(va, size);
|
UnmapEvent?.Invoke(va, size, clearRejitQueueOnly);
|
||||||
Tracking.Unmap(va, size);
|
Tracking.Unmap(va, size);
|
||||||
_pages.RemoveMapping(va, size);
|
_pages.RemoveMapping(va, size);
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Ryujinx.Cpu.Jit
|
||||||
|
|
||||||
public MemoryTracking Tracking { get; }
|
public MemoryTracking Tracking { get; }
|
||||||
|
|
||||||
public event Action<ulong, ulong> UnmapEvent;
|
public event Action<ulong, ulong, bool> UnmapEvent;
|
||||||
|
|
||||||
protected override ulong AddressSpaceSize { get; }
|
protected override ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
|
@ -103,11 +103,11 @@ namespace Ryujinx.Cpu.Jit
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Unmap(ulong va, ulong size)
|
public void Unmap(ulong va, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
AssertValidAddressAndSize(va, size);
|
AssertValidAddressAndSize(va, size);
|
||||||
|
|
||||||
UnmapEvent?.Invoke(va, size);
|
UnmapEvent?.Invoke(va, size, clearRejitQueueOnly);
|
||||||
Tracking.Unmap(va, size);
|
Tracking.Unmap(va, size);
|
||||||
|
|
||||||
_pages.RemoveMapping(va, size);
|
_pages.RemoveMapping(va, size);
|
||||||
|
|
|
@ -203,7 +203,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override Result Unmap(ulong address, ulong pagesCount)
|
protected override Result Unmap(ulong address, ulong pagesCount, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
KPageList pagesToClose = new();
|
KPageList pagesToClose = new();
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_cpuMemory.Unmap(address, pagesCount * PageSize);
|
_cpuMemory.Unmap(address, pagesCount * PageSize, clearRejitQueueOnly);
|
||||||
|
|
||||||
pagesToClose.DecrementPagesReferenceCount(Context.MemoryManager);
|
pagesToClose.DecrementPagesReferenceCount(Context.MemoryManager);
|
||||||
|
|
||||||
|
|
|
@ -648,7 +648,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result UnmapProcessCodeMemory(ulong dst, ulong src, ulong size)
|
public Result UnmapProcessCodeMemory(ulong dst, ulong src, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
lock (_blockManager)
|
lock (_blockManager)
|
||||||
{
|
{
|
||||||
|
@ -694,7 +694,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
{
|
{
|
||||||
ulong pagesCount = size / PageSize;
|
ulong pagesCount = size / PageSize;
|
||||||
|
|
||||||
Result result = Unmap(dst, pagesCount);
|
Result result = Unmap(dst, pagesCount, clearRejitQueueOnly);
|
||||||
|
|
||||||
if (result != Result.Success)
|
if (result != Result.Success)
|
||||||
{
|
{
|
||||||
|
@ -3032,7 +3032,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
/// <param name="address">Virtual address of the region to unmap</param>
|
/// <param name="address">Virtual address of the region to unmap</param>
|
||||||
/// <param name="pagesCount">Number of pages to unmap</param>
|
/// <param name="pagesCount">Number of pages to unmap</param>
|
||||||
/// <returns>Result of the unmapping operation</returns>
|
/// <returns>Result of the unmapping operation</returns>
|
||||||
protected abstract Result Unmap(ulong address, ulong pagesCount);
|
protected abstract Result Unmap(ulong address, ulong pagesCount, bool clearRejitQueueOnly = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes the permissions of a given virtual memory region.
|
/// Changes the permissions of a given virtual memory region.
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
[Service("ro:1")] // 7.0.0+
|
[Service("ro:1")] // 7.0.0+
|
||||||
class IRoInterface : DisposableIpcService
|
class IRoInterface : DisposableIpcService
|
||||||
{
|
{
|
||||||
|
private const bool EnableOpt = true;
|
||||||
|
|
||||||
private const int MaxNrr = 0x40;
|
private const int MaxNrr = 0x40;
|
||||||
private const int MaxNro = 0x40;
|
private const int MaxNro = 0x40;
|
||||||
private const int MaxMapRetries = 0x200;
|
private const int MaxMapRetries = 0x200;
|
||||||
|
@ -28,6 +30,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
|
|
||||||
private readonly List<NrrInfo> _nrrInfos;
|
private readonly List<NrrInfo> _nrrInfos;
|
||||||
private readonly List<NroInfo> _nroInfos;
|
private readonly List<NroInfo> _nroInfos;
|
||||||
|
private readonly List<NroInfo> _nroInfosUnloaded;
|
||||||
|
|
||||||
private KProcess _owner;
|
private KProcess _owner;
|
||||||
private IVirtualMemoryManager _ownerMm;
|
private IVirtualMemoryManager _ownerMm;
|
||||||
|
@ -36,6 +39,8 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
{
|
{
|
||||||
_nrrInfos = new List<NrrInfo>(MaxNrr);
|
_nrrInfos = new List<NrrInfo>(MaxNrr);
|
||||||
_nroInfos = new List<NroInfo>(MaxNro);
|
_nroInfos = new List<NroInfo>(MaxNro);
|
||||||
|
_nroInfosUnloaded = new List<NroInfo>(MaxNro);
|
||||||
|
|
||||||
_owner = null;
|
_owner = null;
|
||||||
_ownerMm = null;
|
_ownerMm = null;
|
||||||
}
|
}
|
||||||
|
@ -198,17 +203,18 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultCode MapNro(KProcess process, NroInfo info, out ulong nroMappedAddress)
|
private ResultCode MapNro(KProcess process, NroInfo info, MapType mapType, out ulong nroMappedAddress)
|
||||||
{
|
{
|
||||||
KPageTableBase memMgr = process.MemoryManager;
|
KPageTableBase memMgr = process.MemoryManager;
|
||||||
|
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
|
int maxMapRetries = mapType != MapType.Within ? MaxMapRetries : 1;
|
||||||
|
|
||||||
nroMappedAddress = 0;
|
nroMappedAddress = 0;
|
||||||
|
|
||||||
while (retryCount++ < MaxMapRetries)
|
while (retryCount++ < maxMapRetries)
|
||||||
{
|
{
|
||||||
ResultCode result = MapCodeMemoryInProcess(process, info.NroAddress, info.NroSize, out nroMappedAddress);
|
ResultCode result = MapCodeMemoryInProcess(process, info, mapType, out nroMappedAddress);
|
||||||
|
|
||||||
if (result != ResultCode.Success)
|
if (result != ResultCode.Success)
|
||||||
{
|
{
|
||||||
|
@ -262,31 +268,73 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultCode MapCodeMemoryInProcess(KProcess process, ulong baseAddress, ulong size, out ulong targetAddress)
|
private static bool NotOverlapsWith(ulong newAddress, ulong newSize, ulong oldAddress, ulong oldSize)
|
||||||
|
{
|
||||||
|
return newAddress + newSize <= oldAddress || oldAddress + oldSize <= newAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultCode MapCodeMemoryInProcess(KProcess process, NroInfo info, MapType mapType, out ulong targetAddress)
|
||||||
{
|
{
|
||||||
KPageTableBase memMgr = process.MemoryManager;
|
KPageTableBase memMgr = process.MemoryManager;
|
||||||
|
|
||||||
|
int retryCount = 0;
|
||||||
|
int maxMapRetries = mapType != MapType.Within ? MaxMapRetries : 1;
|
||||||
|
|
||||||
targetAddress = 0;
|
targetAddress = 0;
|
||||||
|
|
||||||
int retryCount;
|
while (retryCount++ < maxMapRetries)
|
||||||
|
{
|
||||||
ulong addressSpacePageLimit = (memMgr.GetAddrSpaceSize() - size) >> 12;
|
if (mapType == MapType.Default)
|
||||||
|
|
||||||
for (retryCount = 0; retryCount < MaxMapRetries; retryCount++)
|
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
ulong addressSpacePageLimit = (memMgr.GetAddrSpaceSize() - info.NroSize) >> 12;
|
||||||
ulong randomOffset = (ulong)(uint)Random.Shared.Next(0, (int)addressSpacePageLimit) << 12;
|
ulong randomOffset = (ulong)(uint)Random.Shared.Next(0, (int)addressSpacePageLimit) << 12;
|
||||||
|
|
||||||
targetAddress = memMgr.GetAddrSpaceBaseAddr() + randomOffset;
|
targetAddress = memMgr.GetAddrSpaceBaseAddr() + randomOffset;
|
||||||
|
|
||||||
if (memMgr.InsideAddrSpace(targetAddress, size) && !memMgr.InsideHeapRegion(targetAddress, size) && !memMgr.InsideAliasRegion(targetAddress, size))
|
if (memMgr.InsideAddrSpace(targetAddress, info.NroSize) &&
|
||||||
|
!memMgr.InsideHeapRegion(targetAddress, info.NroSize) &&
|
||||||
|
!memMgr.InsideAliasRegion(targetAddress, info.NroSize))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mapType == MapType.Between)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ulong addressSpacePageLimit = (memMgr.GetAddrSpaceSize() - info.NroSize) >> 12;
|
||||||
|
ulong randomOffset = (ulong)(uint)Random.Shared.Next(0, (int)addressSpacePageLimit) << 12;
|
||||||
|
|
||||||
|
targetAddress = memMgr.GetAddrSpaceBaseAddr() + randomOffset;
|
||||||
|
|
||||||
|
if (memMgr.InsideAddrSpace(targetAddress, info.NroSize) &&
|
||||||
|
!memMgr.InsideHeapRegion(targetAddress, info.NroSize) &&
|
||||||
|
!memMgr.InsideAliasRegion(targetAddress, info.NroSize))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result result = memMgr.MapProcessCodeMemory(targetAddress, baseAddress, size);
|
ulong targetAddressTmp = targetAddress; // CS1628.
|
||||||
|
if (_nroInfosUnloaded.TrueForAll((infoU) => NotOverlapsWith(targetAddressTmp, info.NroSize + info.BssSize, infoU.NroMappedAddress, infoU.NroSize + infoU.BssSize)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (mapType == MapType.Within) */
|
||||||
|
{
|
||||||
|
NroInfo infoU = _nroInfosUnloaded.Find((infoU) => infoU.Hash.SequenceEqual(info.Hash));
|
||||||
|
|
||||||
|
targetAddress = infoU.NroMappedAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result result = memMgr.MapProcessCodeMemory(targetAddress, info.NroAddress, info.NroSize);
|
||||||
|
|
||||||
if (result == KernelResult.InvalidMemState)
|
if (result == KernelResult.InvalidMemState)
|
||||||
{
|
{
|
||||||
|
@ -297,7 +345,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
return (ResultCode)result.ErrorCode;
|
return (ResultCode)result.ErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CanAddGuardRegionsInProcess(process, targetAddress, size))
|
if (!CanAddGuardRegionsInProcess(process, targetAddress, info.NroSize))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -305,14 +353,9 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retryCount == MaxMapRetries)
|
|
||||||
{
|
|
||||||
return ResultCode.InsufficientAddressSpace;
|
return ResultCode.InsufficientAddressSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultCode.Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Result SetNroMemoryPermissions(KProcess process, IExecutable relocatableObject, ulong baseAddress)
|
private Result SetNroMemoryPermissions(KProcess process, IExecutable relocatableObject, ulong baseAddress)
|
||||||
{
|
{
|
||||||
ulong textStart = baseAddress + relocatableObject.TextOffset;
|
ulong textStart = baseAddress + relocatableObject.TextOffset;
|
||||||
|
@ -369,16 +412,20 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
{
|
{
|
||||||
if (info.NroMappedAddress == nroMappedAddress)
|
if (info.NroMappedAddress == nroMappedAddress)
|
||||||
{
|
{
|
||||||
|
if (EnableOpt)
|
||||||
|
{
|
||||||
|
_nroInfosUnloaded.Add(info);
|
||||||
|
}
|
||||||
_nroInfos.Remove(info);
|
_nroInfos.Remove(info);
|
||||||
|
|
||||||
return UnmapNroFromInfo(info);
|
return UnmapNroFromInfo(info, clearRejitQueueOnly: EnableOpt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultCode.NotLoaded;
|
return ResultCode.NotLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultCode UnmapNroFromInfo(NroInfo info)
|
private ResultCode UnmapNroFromInfo(NroInfo info, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
ulong textSize = (ulong)info.Executable.Text.Length;
|
ulong textSize = (ulong)info.Executable.Text.Length;
|
||||||
ulong roSize = (ulong)info.Executable.Ro.Length;
|
ulong roSize = (ulong)info.Executable.Ro.Length;
|
||||||
|
@ -392,7 +439,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
||||||
info.NroMappedAddress + textSize + roSize + dataSize,
|
info.NroMappedAddress + textSize + roSize + dataSize,
|
||||||
info.Executable.BssAddress,
|
info.Executable.BssAddress,
|
||||||
bssSize);
|
bssSize, clearRejitQueueOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == Result.Success)
|
if (result == Result.Success)
|
||||||
|
@ -400,14 +447,14 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
||||||
info.NroMappedAddress + textSize + roSize,
|
info.NroMappedAddress + textSize + roSize,
|
||||||
info.Executable.SourceAddress + textSize + roSize,
|
info.Executable.SourceAddress + textSize + roSize,
|
||||||
dataSize);
|
dataSize, clearRejitQueueOnly);
|
||||||
|
|
||||||
if (result == Result.Success)
|
if (result == Result.Success)
|
||||||
{
|
{
|
||||||
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
result = _owner.MemoryManager.UnmapProcessCodeMemory(
|
||||||
info.NroMappedAddress,
|
info.NroMappedAddress,
|
||||||
info.Executable.SourceAddress,
|
info.Executable.SourceAddress,
|
||||||
textSize + roSize);
|
textSize + roSize, clearRejitQueueOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,6 +471,8 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
return ResultCode.InvalidProcess;
|
return ResultCode.InvalidProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum MapType { Default, Between, Within }
|
||||||
|
|
||||||
[CommandCmif(0)]
|
[CommandCmif(0)]
|
||||||
// LoadNro(u64, u64, u64, u64, u64, pid) -> u64
|
// LoadNro(u64, u64, u64, u64, u64, pid) -> u64
|
||||||
public ResultCode LoadNro(ServiceCtx context)
|
public ResultCode LoadNro(ServiceCtx context)
|
||||||
|
@ -447,7 +496,48 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
result = MapNro(_owner, info, out nroMappedAddress);
|
MapType mapType = MapType.Default;
|
||||||
|
|
||||||
|
if (_nroInfosUnloaded.Count != 0)
|
||||||
|
{
|
||||||
|
mapType = _nroInfosUnloaded.Exists((infoU) => infoU.Hash.SequenceEqual(info.Hash)) // One/zero match.
|
||||||
|
? MapType.Within
|
||||||
|
: MapType.Between;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = MapNro(_owner, info, mapType, out nroMappedAddress);
|
||||||
|
|
||||||
|
if (mapType == MapType.Between)
|
||||||
|
{
|
||||||
|
if (result != ResultCode.Success)
|
||||||
|
{
|
||||||
|
_nroInfosUnloaded.Clear();
|
||||||
|
|
||||||
|
mapType = MapType.Default;
|
||||||
|
|
||||||
|
result = MapNro(_owner, info, mapType, out nroMappedAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mapType == MapType.Within)
|
||||||
|
{
|
||||||
|
_nroInfosUnloaded.RemoveAll((infoU) => infoU.Hash.SequenceEqual(info.Hash)); // One match.
|
||||||
|
|
||||||
|
if (result != ResultCode.Success)
|
||||||
|
{
|
||||||
|
mapType = MapType.Between;
|
||||||
|
|
||||||
|
result = MapNro(_owner, info, mapType, out nroMappedAddress);
|
||||||
|
|
||||||
|
if (result != ResultCode.Success)
|
||||||
|
{
|
||||||
|
_nroInfosUnloaded.Clear();
|
||||||
|
|
||||||
|
mapType = MapType.Default;
|
||||||
|
|
||||||
|
result = MapNro(_owner, info, mapType, out nroMappedAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
|
@ -589,6 +679,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro
|
||||||
}
|
}
|
||||||
|
|
||||||
_nroInfos.Clear();
|
_nroInfos.Clear();
|
||||||
|
_nroInfosUnloaded.Clear();
|
||||||
|
|
||||||
if (_ownerMm is IRefCounted rc)
|
if (_ownerMm is IRefCounted rc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace Ryujinx.Memory
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Unmap(ulong va, ulong size)
|
public void Unmap(ulong va, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
AssertValidAddressAndSize(va, size);
|
AssertValidAddressAndSize(va, size);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace Ryujinx.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="va">Virtual address of the range to be unmapped</param>
|
/// <param name="va">Virtual address of the range to be unmapped</param>
|
||||||
/// <param name="size">Size of the range to be unmapped</param>
|
/// <param name="size">Size of the range to be unmapped</param>
|
||||||
void Unmap(ulong va, ulong size);
|
void Unmap(ulong va, ulong size, bool clearRejitQueueOnly = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads data from CPU mapped memory.
|
/// Reads data from CPU mapped memory.
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace Ryujinx.Tests.Memory
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unmap(ulong va, ulong size)
|
public void Unmap(ulong va, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ namespace Ryujinx.Tests.Cpu
|
||||||
memory.UnmapEvent += UnmapHandler;
|
memory.UnmapEvent += UnmapHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UnmapHandler(ulong address, ulong size)
|
private void UnmapHandler(ulong address, ulong size, bool clearRejitQueueOnly = false)
|
||||||
{
|
{
|
||||||
_translator.InvalidateJitCacheRegion(address, size);
|
_translator.InvalidateJitCacheRegion(address, size, clearRejitQueueOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExecutionContext CreateExecutionContext()
|
public static ExecutionContext CreateExecutionContext()
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Tests.Memory
|
||||||
public MemoryManagerType Type => MemoryManagerType.HostMappedUnsafe;
|
public MemoryManagerType Type => MemoryManagerType.HostMappedUnsafe;
|
||||||
|
|
||||||
#pragma warning disable CS0067 // The event is never used
|
#pragma warning disable CS0067 // The event is never used
|
||||||
public event Action<ulong, ulong> UnmapEvent;
|
public event Action<ulong, ulong, bool> UnmapEvent;
|
||||||
#pragma warning restore CS0067
|
#pragma warning restore CS0067
|
||||||
|
|
||||||
public ref T GetRef<T>(ulong va) where T : unmanaged
|
public ref T GetRef<T>(ulong va) where T : unmanaged
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue