mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-13 14:19:12 +00:00
Merge branch 'master' into features/crash-verification-ex
This commit is contained in:
commit
0ab80a9861
10 changed files with 187 additions and 111 deletions
|
@ -5,7 +5,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu
|
namespace Ryujinx.Cpu
|
||||||
{
|
{
|
||||||
class AddressSpace : IDisposable
|
public class AddressSpace : IDisposable
|
||||||
{
|
{
|
||||||
private const ulong PageSize = 0x1000;
|
private const ulong PageSize = 0x1000;
|
||||||
|
|
||||||
|
@ -154,7 +154,9 @@ namespace Ryujinx.Cpu
|
||||||
public MemoryBlock Base { get; }
|
public MemoryBlock Base { get; }
|
||||||
public MemoryBlock Mirror { get; }
|
public MemoryBlock Mirror { get; }
|
||||||
|
|
||||||
public AddressSpace(MemoryBlock backingMemory, ulong asSize, bool supports4KBPages)
|
public ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
|
public AddressSpace(MemoryBlock backingMemory, MemoryBlock baseMemory, MemoryBlock mirrorMemory, ulong addressSpaceSize, bool supports4KBPages)
|
||||||
{
|
{
|
||||||
if (!supports4KBPages)
|
if (!supports4KBPages)
|
||||||
{
|
{
|
||||||
|
@ -163,17 +165,48 @@ namespace Ryujinx.Cpu
|
||||||
_privateTree = new IntrusiveRedBlackTree<PrivateMapping>();
|
_privateTree = new IntrusiveRedBlackTree<PrivateMapping>();
|
||||||
_treeLock = new object();
|
_treeLock = new object();
|
||||||
|
|
||||||
_mappingTree.Add(new Mapping(0UL, asSize, MappingType.None));
|
_mappingTree.Add(new Mapping(0UL, addressSpaceSize, MappingType.None));
|
||||||
_privateTree.Add(new PrivateMapping(0UL, asSize, default));
|
_privateTree.Add(new PrivateMapping(0UL, addressSpaceSize, default));
|
||||||
}
|
}
|
||||||
|
|
||||||
_backingMemory = backingMemory;
|
_backingMemory = backingMemory;
|
||||||
_supports4KBPages = supports4KBPages;
|
_supports4KBPages = supports4KBPages;
|
||||||
|
|
||||||
|
Base = baseMemory;
|
||||||
|
Mirror = mirrorMemory;
|
||||||
|
AddressSpaceSize = addressSpaceSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryCreate(MemoryBlock backingMemory, ulong asSize, bool supports4KBPages, out AddressSpace addressSpace)
|
||||||
|
{
|
||||||
|
addressSpace = null;
|
||||||
|
|
||||||
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible;
|
||||||
|
|
||||||
Base = new MemoryBlock(asSize, asFlags);
|
ulong minAddressSpaceSize = Math.Min(asSize, 1UL << 36);
|
||||||
Mirror = new MemoryBlock(asSize, asFlags);
|
|
||||||
|
// Attempt to create the address space with expected size or try to reduce it until it succeed.
|
||||||
|
for (ulong addressSpaceSize = asSize; addressSpaceSize >= minAddressSpaceSize; addressSpaceSize >>= 1)
|
||||||
|
{
|
||||||
|
MemoryBlock baseMemory = null;
|
||||||
|
MemoryBlock mirrorMemory = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
baseMemory = new MemoryBlock(addressSpaceSize, asFlags);
|
||||||
|
mirrorMemory = new MemoryBlock(addressSpaceSize, asFlags);
|
||||||
|
addressSpace = new AddressSpace(backingMemory, baseMemory, mirrorMemory, addressSpaceSize, supports4KBPages);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (OutOfMemoryException)
|
||||||
|
{
|
||||||
|
baseMemory?.Dispose();
|
||||||
|
mirrorMemory?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return addressSpace != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
|
public void Map(ulong va, ulong pa, ulong size, MemoryMapFlags flags)
|
||||||
|
|
|
@ -38,7 +38,8 @@ namespace Ryujinx.Cpu.Jit
|
||||||
private readonly bool _unsafeMode;
|
private readonly bool _unsafeMode;
|
||||||
|
|
||||||
private readonly AddressSpace _addressSpace;
|
private readonly AddressSpace _addressSpace;
|
||||||
private readonly ulong _addressSpaceSize;
|
|
||||||
|
public ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
private readonly PageTable<ulong> _pageTable;
|
private readonly PageTable<ulong> _pageTable;
|
||||||
|
|
||||||
|
@ -62,21 +63,21 @@ namespace Ryujinx.Cpu.Jit
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the host mapped memory manager.
|
/// Creates a new instance of the host mapped memory manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="backingMemory">Physical backing memory where virtual memory will be mapped to</param>
|
/// <param name="addressSpace">Address space instance to use</param>
|
||||||
/// <param name="addressSpaceSize">Size of the address space</param>
|
|
||||||
/// <param name="unsafeMode">True if unmanaged access should not be masked (unsafe), false otherwise.</param>
|
/// <param name="unsafeMode">True if unmanaged access should not be masked (unsafe), false otherwise.</param>
|
||||||
/// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param>
|
/// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param>
|
||||||
public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize, bool unsafeMode, InvalidAccessHandler invalidAccessHandler = null)
|
public MemoryManagerHostMapped(AddressSpace addressSpace, bool unsafeMode, InvalidAccessHandler invalidAccessHandler)
|
||||||
{
|
{
|
||||||
|
_addressSpace = addressSpace;
|
||||||
_pageTable = new PageTable<ulong>();
|
_pageTable = new PageTable<ulong>();
|
||||||
_invalidAccessHandler = invalidAccessHandler;
|
_invalidAccessHandler = invalidAccessHandler;
|
||||||
_unsafeMode = unsafeMode;
|
_unsafeMode = unsafeMode;
|
||||||
_addressSpaceSize = addressSpaceSize;
|
AddressSpaceSize = addressSpace.AddressSpaceSize;
|
||||||
|
|
||||||
ulong asSize = PageSize;
|
ulong asSize = PageSize;
|
||||||
int asBits = PageBits;
|
int asBits = PageBits;
|
||||||
|
|
||||||
while (asSize < addressSpaceSize)
|
while (asSize < AddressSpaceSize)
|
||||||
{
|
{
|
||||||
asSize <<= 1;
|
asSize <<= 1;
|
||||||
asBits++;
|
asBits++;
|
||||||
|
@ -86,8 +87,6 @@ namespace Ryujinx.Cpu.Jit
|
||||||
|
|
||||||
_pageBitmap = new ulong[1 << (AddressSpaceBits - (PageBits + PageToPteShift))];
|
_pageBitmap = new ulong[1 << (AddressSpaceBits - (PageBits + PageToPteShift))];
|
||||||
|
|
||||||
_addressSpace = new AddressSpace(backingMemory, asSize, Supports4KBPages);
|
|
||||||
|
|
||||||
Tracking = new MemoryTracking(this, (int)MemoryBlock.GetPageSize(), invalidAccessHandler);
|
Tracking = new MemoryTracking(this, (int)MemoryBlock.GetPageSize(), invalidAccessHandler);
|
||||||
_memoryEh = new MemoryEhMeilleure(_addressSpace.Base, _addressSpace.Mirror, Tracking);
|
_memoryEh = new MemoryEhMeilleure(_addressSpace.Base, _addressSpace.Mirror, Tracking);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +98,7 @@ namespace Ryujinx.Cpu.Jit
|
||||||
/// <returns>True if the virtual address is part of the addressable space</returns>
|
/// <returns>True if the virtual address is part of the addressable space</returns>
|
||||||
private bool ValidateAddress(ulong va)
|
private bool ValidateAddress(ulong va)
|
||||||
{
|
{
|
||||||
return va < _addressSpaceSize;
|
return va < AddressSpaceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -111,7 +110,7 @@ namespace Ryujinx.Cpu.Jit
|
||||||
private bool ValidateAddressAndSize(ulong va, ulong size)
|
private bool ValidateAddressAndSize(ulong va, ulong size)
|
||||||
{
|
{
|
||||||
ulong endVa = va + size;
|
ulong endVa = va + size;
|
||||||
return endVa >= va && endVa >= size && endVa <= _addressSpaceSize;
|
return endVa >= va && endVa >= size && endVa <= AddressSpaceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -25,7 +25,15 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
public IVirtualMemoryManager AddressSpace => _memoryManager;
|
public IVirtualMemoryManager AddressSpace => _memoryManager;
|
||||||
|
|
||||||
public ArmProcessContext(ulong pid, ICpuEngine cpuEngine, GpuContext gpuContext, T memoryManager, bool for64Bit)
|
public ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
|
public ArmProcessContext(
|
||||||
|
ulong pid,
|
||||||
|
ICpuEngine cpuEngine,
|
||||||
|
GpuContext gpuContext,
|
||||||
|
T memoryManager,
|
||||||
|
ulong addressSpaceSize,
|
||||||
|
bool for64Bit)
|
||||||
{
|
{
|
||||||
if (memoryManager is IRefCounted rc)
|
if (memoryManager is IRefCounted rc)
|
||||||
{
|
{
|
||||||
|
@ -38,6 +46,8 @@ namespace Ryujinx.HLE.HOS
|
||||||
_gpuContext = gpuContext;
|
_gpuContext = gpuContext;
|
||||||
_cpuContext = cpuEngine.CreateCpuContext(memoryManager, for64Bit);
|
_cpuContext = cpuEngine.CreateCpuContext(memoryManager, for64Bit);
|
||||||
_memoryManager = memoryManager;
|
_memoryManager = memoryManager;
|
||||||
|
|
||||||
|
AddressSpaceSize = addressSpaceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
using Ryujinx.Cpu.AppleHv;
|
using Ryujinx.Cpu.AppleHv;
|
||||||
using Ryujinx.Cpu.Jit;
|
using Ryujinx.Cpu.Jit;
|
||||||
|
@ -49,7 +50,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
{
|
{
|
||||||
var cpuEngine = new HvEngine(_tickSource);
|
var cpuEngine = new HvEngine(_tickSource);
|
||||||
var memoryManager = new HvMemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
var memoryManager = new HvMemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
||||||
processContext = new ArmProcessContext<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, for64Bit);
|
processContext = new ArmProcessContext<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -57,23 +58,41 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
|
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
|
||||||
{
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Cpu, "Host system doesn't support views, falling back to software page table");
|
||||||
|
|
||||||
mode = MemoryManagerMode.SoftwarePageTable;
|
mode = MemoryManagerMode.SoftwarePageTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cpuEngine = new JitEngine(_tickSource);
|
var cpuEngine = new JitEngine(_tickSource);
|
||||||
|
|
||||||
|
AddressSpace addressSpace = null;
|
||||||
|
|
||||||
|
if (mode == MemoryManagerMode.HostMapped || mode == MemoryManagerMode.HostMappedUnsafe)
|
||||||
|
{
|
||||||
|
if (!AddressSpace.TryCreate(context.Memory, addressSpaceSize, MemoryBlock.GetPageSize() == MemoryManagerHostMapped.PageSize, out addressSpace))
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Cpu, "Address space creation failed, falling back to software page table");
|
||||||
|
|
||||||
|
mode = MemoryManagerMode.SoftwarePageTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case MemoryManagerMode.SoftwarePageTable:
|
case MemoryManagerMode.SoftwarePageTable:
|
||||||
var memoryManager = new MemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
var memoryManager = new MemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler);
|
||||||
processContext = new ArmProcessContext<MemoryManager>(pid, cpuEngine, _gpu, memoryManager, for64Bit);
|
processContext = new ArmProcessContext<MemoryManager>(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MemoryManagerMode.HostMapped:
|
case MemoryManagerMode.HostMapped:
|
||||||
case MemoryManagerMode.HostMappedUnsafe:
|
case MemoryManagerMode.HostMappedUnsafe:
|
||||||
bool unsafeMode = mode == MemoryManagerMode.HostMappedUnsafe;
|
if (addressSpaceSize != addressSpace.AddressSpaceSize)
|
||||||
var memoryManagerHostMapped = new MemoryManagerHostMapped(context.Memory, addressSpaceSize, unsafeMode, invalidAccessHandler);
|
{
|
||||||
processContext = new ArmProcessContext<MemoryManagerHostMapped>(pid, cpuEngine, _gpu, memoryManagerHostMapped, for64Bit);
|
Logger.Warning?.Print(LogClass.Emulation, $"Allocated address space (0x{addressSpace.AddressSpaceSize:X}) is smaller than guest application requirements (0x{addressSpaceSize:X})");
|
||||||
|
}
|
||||||
|
|
||||||
|
var memoryManagerHostMapped = new MemoryManagerHostMapped(addressSpace, mode == MemoryManagerMode.HostMappedUnsafe, invalidAccessHandler);
|
||||||
|
processContext = new ArmProcessContext<MemoryManagerHostMapped>(pid, cpuEngine, _gpu, memoryManagerHostMapped, addressSpace.AddressSpaceSize, for64Bit);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
protected override bool Supports4KBPages => _cpuMemory.Supports4KBPages;
|
protected override bool Supports4KBPages => _cpuMemory.Supports4KBPages;
|
||||||
|
|
||||||
public KPageTable(KernelContext context, IVirtualMemoryManager cpuMemory) : base(context)
|
public KPageTable(KernelContext context, IVirtualMemoryManager cpuMemory, ulong reservedAddressSpaceSize) : base(context, reservedAddressSpaceSize)
|
||||||
{
|
{
|
||||||
_cpuMemory = cpuMemory;
|
_cpuMemory = cpuMemory;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
0x40000000
|
0x40000000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private const ulong RegionAlignment = 0x200000;
|
||||||
|
|
||||||
public const int PageSize = 0x1000;
|
public const int PageSize = 0x1000;
|
||||||
|
|
||||||
private const int KMemoryBlockSize = 0x40;
|
private const int KMemoryBlockSize = 0x40;
|
||||||
|
@ -53,6 +55,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
public ulong TlsIoRegionStart { get; private set; }
|
public ulong TlsIoRegionStart { get; private set; }
|
||||||
public ulong TlsIoRegionEnd { get; private set; }
|
public ulong TlsIoRegionEnd { get; private set; }
|
||||||
|
|
||||||
|
public ulong AslrRegionStart { get; private set; }
|
||||||
|
public ulong AslrRegionEnd { get; private set; }
|
||||||
|
|
||||||
private ulong _heapCapacity;
|
private ulong _heapCapacity;
|
||||||
|
|
||||||
public ulong PhysicalMemoryUsage { get; private set; }
|
public ulong PhysicalMemoryUsage { get; private set; }
|
||||||
|
@ -61,10 +66,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
private MemoryRegion _memRegion;
|
private MemoryRegion _memRegion;
|
||||||
|
|
||||||
private bool _aslrDisabled;
|
private bool _allocateFromBack;
|
||||||
|
|
||||||
public int AddrSpaceWidth { get; private set; }
|
|
||||||
|
|
||||||
private bool _isKernel;
|
private bool _isKernel;
|
||||||
|
|
||||||
private bool _aslrEnabled;
|
private bool _aslrEnabled;
|
||||||
|
@ -78,7 +80,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
private MemoryFillValue _heapFillValue;
|
private MemoryFillValue _heapFillValue;
|
||||||
private MemoryFillValue _ipcFillValue;
|
private MemoryFillValue _ipcFillValue;
|
||||||
|
|
||||||
public KPageTableBase(KernelContext context)
|
private ulong _reservedAddressSpaceSize;
|
||||||
|
|
||||||
|
public KPageTableBase(KernelContext context, ulong reservedAddressSpaceSize)
|
||||||
{
|
{
|
||||||
Context = context;
|
Context = context;
|
||||||
|
|
||||||
|
@ -88,6 +92,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
_heapFillValue = MemoryFillValue.Zero;
|
_heapFillValue = MemoryFillValue.Zero;
|
||||||
_ipcFillValue = MemoryFillValue.Zero;
|
_ipcFillValue = MemoryFillValue.Zero;
|
||||||
|
|
||||||
|
_reservedAddressSpaceSize = reservedAddressSpaceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly int[] AddrSpaceSizes = new int[] { 32, 36, 32, 39 };
|
private static readonly int[] AddrSpaceSizes = new int[] { 32, 36, 32, 39 };
|
||||||
|
@ -95,7 +101,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
public Result InitializeForProcess(
|
public Result InitializeForProcess(
|
||||||
AddressSpaceType addrSpaceType,
|
AddressSpaceType addrSpaceType,
|
||||||
bool aslrEnabled,
|
bool aslrEnabled,
|
||||||
bool aslrDisabled,
|
bool fromBack,
|
||||||
MemoryRegion memRegion,
|
MemoryRegion memRegion,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
|
@ -114,7 +120,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
Result result = CreateUserAddressSpace(
|
Result result = CreateUserAddressSpace(
|
||||||
addrSpaceType,
|
addrSpaceType,
|
||||||
aslrEnabled,
|
aslrEnabled,
|
||||||
aslrDisabled,
|
fromBack,
|
||||||
addrSpaceBase,
|
addrSpaceBase,
|
||||||
addrSpaceSize,
|
addrSpaceSize,
|
||||||
memRegion,
|
memRegion,
|
||||||
|
@ -130,7 +136,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Region
|
private struct Region
|
||||||
{
|
{
|
||||||
public ulong Start;
|
public ulong Start;
|
||||||
public ulong End;
|
public ulong End;
|
||||||
|
@ -141,7 +147,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
private Result CreateUserAddressSpace(
|
private Result CreateUserAddressSpace(
|
||||||
AddressSpaceType addrSpaceType,
|
AddressSpaceType addrSpaceType,
|
||||||
bool aslrEnabled,
|
bool aslrEnabled,
|
||||||
bool aslrDisabled,
|
bool fromBack,
|
||||||
ulong addrSpaceStart,
|
ulong addrSpaceStart,
|
||||||
ulong addrSpaceEnd,
|
ulong addrSpaceEnd,
|
||||||
MemoryRegion memRegion,
|
MemoryRegion memRegion,
|
||||||
|
@ -159,7 +165,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
ulong codeRegionSize;
|
ulong codeRegionSize;
|
||||||
ulong stackAndTlsIoStart;
|
ulong stackAndTlsIoStart;
|
||||||
ulong stackAndTlsIoEnd;
|
ulong stackAndTlsIoEnd;
|
||||||
ulong baseAddress;
|
|
||||||
|
|
||||||
switch (addrSpaceType)
|
switch (addrSpaceType)
|
||||||
{
|
{
|
||||||
|
@ -170,10 +175,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
tlsIoRegion.Size = 0;
|
tlsIoRegion.Size = 0;
|
||||||
CodeRegionStart = 0x200000;
|
CodeRegionStart = 0x200000;
|
||||||
codeRegionSize = 0x3fe00000;
|
codeRegionSize = 0x3fe00000;
|
||||||
|
AslrRegionStart = 0x200000;
|
||||||
|
AslrRegionEnd = AslrRegionStart + 0xffe00000;
|
||||||
stackAndTlsIoStart = 0x200000;
|
stackAndTlsIoStart = 0x200000;
|
||||||
stackAndTlsIoEnd = 0x40000000;
|
stackAndTlsIoEnd = 0x40000000;
|
||||||
baseAddress = 0x200000;
|
|
||||||
AddrSpaceWidth = 32;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AddressSpaceType.Addr36Bits:
|
case AddressSpaceType.Addr36Bits:
|
||||||
|
@ -183,10 +188,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
tlsIoRegion.Size = 0;
|
tlsIoRegion.Size = 0;
|
||||||
CodeRegionStart = 0x8000000;
|
CodeRegionStart = 0x8000000;
|
||||||
codeRegionSize = 0x78000000;
|
codeRegionSize = 0x78000000;
|
||||||
|
AslrRegionStart = 0x8000000;
|
||||||
|
AslrRegionEnd = AslrRegionStart + 0xff8000000;
|
||||||
stackAndTlsIoStart = 0x8000000;
|
stackAndTlsIoStart = 0x8000000;
|
||||||
stackAndTlsIoEnd = 0x80000000;
|
stackAndTlsIoEnd = 0x80000000;
|
||||||
baseAddress = 0x8000000;
|
|
||||||
AddrSpaceWidth = 36;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AddressSpaceType.Addr32BitsNoMap:
|
case AddressSpaceType.Addr32BitsNoMap:
|
||||||
|
@ -196,23 +201,42 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
tlsIoRegion.Size = 0;
|
tlsIoRegion.Size = 0;
|
||||||
CodeRegionStart = 0x200000;
|
CodeRegionStart = 0x200000;
|
||||||
codeRegionSize = 0x3fe00000;
|
codeRegionSize = 0x3fe00000;
|
||||||
|
AslrRegionStart = 0x200000;
|
||||||
|
AslrRegionEnd = AslrRegionStart + 0xffe00000;
|
||||||
stackAndTlsIoStart = 0x200000;
|
stackAndTlsIoStart = 0x200000;
|
||||||
stackAndTlsIoEnd = 0x40000000;
|
stackAndTlsIoEnd = 0x40000000;
|
||||||
baseAddress = 0x200000;
|
|
||||||
AddrSpaceWidth = 32;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AddressSpaceType.Addr39Bits:
|
case AddressSpaceType.Addr39Bits:
|
||||||
aliasRegion.Size = 0x1000000000;
|
if (_reservedAddressSpaceSize < addrSpaceEnd)
|
||||||
heapRegion.Size = 0x180000000;
|
{
|
||||||
stackRegion.Size = 0x80000000;
|
int addressSpaceWidth = (int)ulong.Log2(_reservedAddressSpaceSize);
|
||||||
tlsIoRegion.Size = 0x1000000000;
|
|
||||||
CodeRegionStart = BitUtils.AlignDown<ulong>(address, 0x200000);
|
aliasRegion.Size = 1UL << (addressSpaceWidth - 3);
|
||||||
codeRegionSize = BitUtils.AlignUp<ulong>(endAddr, 0x200000) - CodeRegionStart;
|
heapRegion.Size = 0x180000000;
|
||||||
stackAndTlsIoStart = 0;
|
stackRegion.Size = 1UL << (addressSpaceWidth - 8);
|
||||||
stackAndTlsIoEnd = 0;
|
tlsIoRegion.Size = 1UL << (addressSpaceWidth - 3);
|
||||||
baseAddress = 0x8000000;
|
CodeRegionStart = BitUtils.AlignDown<ulong>(address, RegionAlignment);
|
||||||
AddrSpaceWidth = 39;
|
codeRegionSize = BitUtils.AlignUp<ulong>(endAddr, RegionAlignment) - CodeRegionStart;
|
||||||
|
stackAndTlsIoStart = 0;
|
||||||
|
stackAndTlsIoEnd = 0;
|
||||||
|
AslrRegionStart = 0x8000000;
|
||||||
|
addrSpaceEnd = 1UL << addressSpaceWidth;
|
||||||
|
AslrRegionEnd = addrSpaceEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aliasRegion.Size = 0x1000000000;
|
||||||
|
heapRegion.Size = 0x180000000;
|
||||||
|
stackRegion.Size = 0x80000000;
|
||||||
|
tlsIoRegion.Size = 0x1000000000;
|
||||||
|
CodeRegionStart = BitUtils.AlignDown(address, RegionAlignment);
|
||||||
|
codeRegionSize = BitUtils.AlignUp(endAddr, RegionAlignment) - CodeRegionStart;
|
||||||
|
AslrRegionStart = 0x8000000;
|
||||||
|
AslrRegionEnd = AslrRegionStart + 0x7ff8000000;
|
||||||
|
stackAndTlsIoStart = 0;
|
||||||
|
stackAndTlsIoEnd = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: throw new ArgumentException(nameof(addrSpaceType));
|
default: throw new ArgumentException(nameof(addrSpaceType));
|
||||||
|
@ -223,11 +247,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
ulong mapBaseAddress;
|
ulong mapBaseAddress;
|
||||||
ulong mapAvailableSize;
|
ulong mapAvailableSize;
|
||||||
|
|
||||||
if (CodeRegionStart - baseAddress >= addrSpaceEnd - CodeRegionEnd)
|
if (CodeRegionStart - AslrRegionStart >= addrSpaceEnd - CodeRegionEnd)
|
||||||
{
|
{
|
||||||
// Has more space before the start of the code region.
|
// Has more space before the start of the code region.
|
||||||
mapBaseAddress = baseAddress;
|
mapBaseAddress = AslrRegionStart;
|
||||||
mapAvailableSize = CodeRegionStart - baseAddress;
|
mapAvailableSize = CodeRegionStart - AslrRegionStart;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -254,14 +278,14 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
if (aslrEnabled)
|
if (aslrEnabled)
|
||||||
{
|
{
|
||||||
aliasRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset >> 21) << 21;
|
aliasRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset / RegionAlignment) * RegionAlignment;
|
||||||
heapRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset >> 21) << 21;
|
heapRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset / RegionAlignment) * RegionAlignment;
|
||||||
stackRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset >> 21) << 21;
|
stackRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset / RegionAlignment) * RegionAlignment;
|
||||||
tlsIoRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset >> 21) << 21;
|
tlsIoRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset / RegionAlignment) * RegionAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regions are sorted based on ASLR offset.
|
// Regions are sorted based on ASLR offset.
|
||||||
// When ASLR is disabled, the order is Map, Heap, NewMap and TlsIo.
|
// When ASLR is disabled, the order is Alias, Heap, Stack and TlsIo.
|
||||||
aliasRegion.Start = mapBaseAddress + aliasRegion.AslrOffset;
|
aliasRegion.Start = mapBaseAddress + aliasRegion.AslrOffset;
|
||||||
aliasRegion.End = aliasRegion.Start + aliasRegion.Size;
|
aliasRegion.End = aliasRegion.Start + aliasRegion.Size;
|
||||||
heapRegion.Start = mapBaseAddress + heapRegion.AslrOffset;
|
heapRegion.Start = mapBaseAddress + heapRegion.AslrOffset;
|
||||||
|
@ -271,12 +295,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
tlsIoRegion.Start = mapBaseAddress + tlsIoRegion.AslrOffset;
|
tlsIoRegion.Start = mapBaseAddress + tlsIoRegion.AslrOffset;
|
||||||
tlsIoRegion.End = tlsIoRegion.Start + tlsIoRegion.Size;
|
tlsIoRegion.End = tlsIoRegion.Start + tlsIoRegion.Size;
|
||||||
|
|
||||||
SortRegion(heapRegion, aliasRegion);
|
SortRegion(ref aliasRegion, ref heapRegion, true);
|
||||||
|
|
||||||
if (stackRegion.Size != 0)
|
if (stackRegion.Size != 0)
|
||||||
{
|
{
|
||||||
SortRegion(stackRegion, aliasRegion);
|
stackRegion.Start = mapBaseAddress + stackRegion.AslrOffset;
|
||||||
SortRegion(stackRegion, heapRegion);
|
stackRegion.End = stackRegion.Start + stackRegion.Size;
|
||||||
|
|
||||||
|
SortRegion(ref aliasRegion, ref stackRegion);
|
||||||
|
SortRegion(ref heapRegion, ref stackRegion);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -286,9 +313,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
if (tlsIoRegion.Size != 0)
|
if (tlsIoRegion.Size != 0)
|
||||||
{
|
{
|
||||||
SortRegion(tlsIoRegion, aliasRegion);
|
tlsIoRegion.Start = mapBaseAddress + tlsIoRegion.AslrOffset;
|
||||||
SortRegion(tlsIoRegion, heapRegion);
|
tlsIoRegion.End = tlsIoRegion.Start + tlsIoRegion.Size;
|
||||||
SortRegion(tlsIoRegion, stackRegion);
|
|
||||||
|
SortRegion(ref aliasRegion, ref tlsIoRegion);
|
||||||
|
SortRegion(ref heapRegion, ref tlsIoRegion);
|
||||||
|
|
||||||
|
if (stackRegion.Size != 0)
|
||||||
|
{
|
||||||
|
SortRegion(ref stackRegion, ref tlsIoRegion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -312,11 +346,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
PhysicalMemoryUsage = 0;
|
PhysicalMemoryUsage = 0;
|
||||||
|
|
||||||
_memRegion = memRegion;
|
_memRegion = memRegion;
|
||||||
_aslrDisabled = aslrDisabled;
|
_allocateFromBack = fromBack;
|
||||||
|
|
||||||
return _blockManager.Initialize(addrSpaceStart, addrSpaceEnd, slabManager);
|
return _blockManager.Initialize(addrSpaceStart, addrSpaceEnd, slabManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void SortRegion(ref Region lhs, ref Region rhs, bool checkForEquality = false)
|
||||||
|
{
|
||||||
|
bool res = checkForEquality ? lhs.AslrOffset <= rhs.AslrOffset : lhs.AslrOffset < rhs.AslrOffset;
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
rhs.Start += lhs.Size;
|
||||||
|
rhs.End += lhs.Size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lhs.Start += rhs.Size;
|
||||||
|
lhs.End += rhs.Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ulong GetRandomValue(ulong min, ulong max)
|
private ulong GetRandomValue(ulong min, ulong max)
|
||||||
{
|
{
|
||||||
return (ulong)GetRandomValue((long)min, (long)max);
|
return (ulong)GetRandomValue((long)min, (long)max);
|
||||||
|
@ -332,20 +382,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
return _randomNumberGenerator.GenRandomNumber(min, max);
|
return _randomNumberGenerator.GenRandomNumber(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SortRegion(Region lhs, Region rhs)
|
|
||||||
{
|
|
||||||
if (lhs.AslrOffset < rhs.AslrOffset)
|
|
||||||
{
|
|
||||||
rhs.Start += lhs.Size;
|
|
||||||
rhs.End += lhs.Size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lhs.Start += rhs.Size;
|
|
||||||
lhs.End += rhs.Size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result MapPages(ulong address, KPageList pageList, MemoryState state, KMemoryPermission permission)
|
public Result MapPages(ulong address, KPageList pageList, MemoryState state, KMemoryPermission permission)
|
||||||
{
|
{
|
||||||
ulong pagesCount = pageList.GetPagesCount();
|
ulong pagesCount = pageList.GetPagesCount();
|
||||||
|
@ -1827,7 +1863,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
// If not, allocate a new page and copy the unaligned chunck.
|
// If not, allocate a new page and copy the unaligned chunck.
|
||||||
if (addressTruncated < addressRounded)
|
if (addressTruncated < addressRounded)
|
||||||
{
|
{
|
||||||
dstFirstPagePa = GetMemoryRegionManager().AllocatePagesContiguous(Context, 1, _aslrDisabled);
|
dstFirstPagePa = GetMemoryRegionManager().AllocatePagesContiguous(Context, 1, _allocateFromBack);
|
||||||
|
|
||||||
if (dstFirstPagePa == 0)
|
if (dstFirstPagePa == 0)
|
||||||
{
|
{
|
||||||
|
@ -1841,7 +1877,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
// If not, allocate a new page and copy the unaligned chunck.
|
// If not, allocate a new page and copy the unaligned chunck.
|
||||||
if (endAddrTruncated < endAddrRounded && (addressTruncated == addressRounded || addressTruncated < endAddrTruncated))
|
if (endAddrTruncated < endAddrRounded && (addressTruncated == addressRounded || addressTruncated < endAddrTruncated))
|
||||||
{
|
{
|
||||||
dstLastPagePa = GetMemoryRegionManager().AllocatePagesContiguous(Context, 1, _aslrDisabled);
|
dstLastPagePa = GetMemoryRegionManager().AllocatePagesContiguous(Context, 1, _allocateFromBack);
|
||||||
|
|
||||||
if (dstLastPagePa == 0)
|
if (dstLastPagePa == 0)
|
||||||
{
|
{
|
||||||
|
@ -2799,38 +2835,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
|
||||||
|
|
||||||
public ulong GetAddrSpaceBaseAddr()
|
public ulong GetAddrSpaceBaseAddr()
|
||||||
{
|
{
|
||||||
if (AddrSpaceWidth == 36 || AddrSpaceWidth == 39)
|
return AslrRegionStart;
|
||||||
{
|
|
||||||
return 0x8000000;
|
|
||||||
}
|
|
||||||
else if (AddrSpaceWidth == 32)
|
|
||||||
{
|
|
||||||
return 0x200000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Invalid address space width!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong GetAddrSpaceSize()
|
public ulong GetAddrSpaceSize()
|
||||||
{
|
{
|
||||||
if (AddrSpaceWidth == 36)
|
return AslrRegionEnd - AslrRegionStart;
|
||||||
{
|
|
||||||
return 0xff8000000;
|
|
||||||
}
|
|
||||||
else if (AddrSpaceWidth == 39)
|
|
||||||
{
|
|
||||||
return 0x7ff8000000;
|
|
||||||
}
|
|
||||||
else if (AddrSpaceWidth == 32)
|
|
||||||
{
|
|
||||||
return 0xffe00000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Invalid address space width!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong GetDramAddressFromPa(ulong pa)
|
private static ulong GetDramAddressFromPa(ulong pa)
|
||||||
|
|
|
@ -8,6 +8,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
IVirtualMemoryManager AddressSpace { get; }
|
IVirtualMemoryManager AddressSpace { get; }
|
||||||
|
|
||||||
|
ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks);
|
IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks);
|
||||||
void Execute(IExecutionContext context, ulong codeAddress);
|
void Execute(IExecutionContext context, ulong codeAddress);
|
||||||
void InvalidateCacheRegion(ulong address, ulong size);
|
void InvalidateCacheRegion(ulong address, ulong size);
|
||||||
|
|
|
@ -1082,7 +1082,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
|
|
||||||
Context = _contextFactory.Create(KernelContext, Pid, 1UL << addrSpaceBits, InvalidAccessHandler, for64Bit);
|
Context = _contextFactory.Create(KernelContext, Pid, 1UL << addrSpaceBits, InvalidAccessHandler, for64Bit);
|
||||||
|
|
||||||
MemoryManager = new KPageTable(KernelContext, CpuMemory);
|
MemoryManager = new KPageTable(KernelContext, CpuMemory, Context.AddressSpaceSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool InvalidAccessHandler(ulong va)
|
private bool InvalidAccessHandler(ulong va)
|
||||||
|
|
|
@ -8,9 +8,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
public IVirtualMemoryManager AddressSpace { get; }
|
public IVirtualMemoryManager AddressSpace { get; }
|
||||||
|
|
||||||
public ProcessContext(IVirtualMemoryManager asManager)
|
public ulong AddressSpaceSize { get; }
|
||||||
|
|
||||||
|
public ProcessContext(IVirtualMemoryManager asManager, ulong addressSpaceSize)
|
||||||
{
|
{
|
||||||
AddressSpace = asManager;
|
AddressSpace = asManager;
|
||||||
|
AddressSpaceSize = addressSpaceSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks)
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
|
public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler, bool for64Bit)
|
||||||
{
|
{
|
||||||
return new ProcessContext(new AddressSpaceManager(context.Memory, addressSpaceSize));
|
return new ProcessContext(new AddressSpaceManager(context.Memory, addressSpaceSize), addressSpaceSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue