From 649d372f7da8559f8b6d74ca44af64ba7d7853c4 Mon Sep 17 00:00:00 2001 From: Mary Date: Tue, 20 Jun 2023 17:33:54 +0200 Subject: [PATCH] misc: Implement address space size workarounds (#5191) * misc: Implement address space size workarounds This adds code to support userland with less than 39 bits of address space available by testing reserving multiple sizes and reducing guess address space when needed. This is required for ARM64 support when the kernel is configured to use 63..39 bits for kernel space.(meaning only 38 bits is available to userland) * Address comments * Fix 32 bits address space support and address more comments --- src/Ryujinx.Cpu/AddressSpace.cs | 45 ++++- .../Jit/MemoryManagerHostMapped.cs | 19 +- src/Ryujinx.HLE/HOS/ArmProcessContext.cs | 12 +- .../HOS/ArmProcessContextFactory.cs | 29 ++- .../HOS/Kernel/Memory/KPageTable.cs | 2 +- .../HOS/Kernel/Memory/KPageTableBase.cs | 180 +++++++++--------- .../HOS/Kernel/Process/IProcessContext.cs | 2 + .../HOS/Kernel/Process/KProcess.cs | 2 +- .../HOS/Kernel/Process/ProcessContext.cs | 5 +- .../Kernel/Process/ProcessContextFactory.cs | 2 +- 10 files changed, 187 insertions(+), 111 deletions(-) diff --git a/src/Ryujinx.Cpu/AddressSpace.cs b/src/Ryujinx.Cpu/AddressSpace.cs index 9dc32426cd89..0e27b158239b 100644 --- a/src/Ryujinx.Cpu/AddressSpace.cs +++ b/src/Ryujinx.Cpu/AddressSpace.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Cpu { - class AddressSpace : IDisposable + public class AddressSpace : IDisposable { private const ulong PageSize = 0x1000; @@ -154,7 +154,9 @@ public int CompareTo(PrivateMapping other) public MemoryBlock Base { 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) { @@ -163,17 +165,48 @@ public AddressSpace(MemoryBlock backingMemory, ulong asSize, bool supports4KBPag _privateTree = new IntrusiveRedBlackTree(); _treeLock = new object(); - _mappingTree.Add(new Mapping(0UL, asSize, MappingType.None)); - _privateTree.Add(new PrivateMapping(0UL, asSize, default)); + _mappingTree.Add(new Mapping(0UL, addressSpaceSize, MappingType.None)); + _privateTree.Add(new PrivateMapping(0UL, addressSpaceSize, default)); } _backingMemory = backingMemory; _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; - Base = new MemoryBlock(asSize, asFlags); - Mirror = new MemoryBlock(asSize, asFlags); + ulong minAddressSpaceSize = Math.Min(asSize, 1UL << 36); + + // 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) diff --git a/src/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs b/src/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs index 363f9000d706..3686eb088243 100644 --- a/src/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs +++ b/src/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs @@ -38,7 +38,8 @@ private enum HostMappedPtBits : ulong private readonly bool _unsafeMode; private readonly AddressSpace _addressSpace; - private readonly ulong _addressSpaceSize; + + public ulong AddressSpaceSize { get; } private readonly PageTable _pageTable; @@ -62,21 +63,21 @@ private enum HostMappedPtBits : ulong /// /// Creates a new instance of the host mapped memory manager. /// - /// Physical backing memory where virtual memory will be mapped to - /// Size of the address space + /// Address space instance to use /// True if unmanaged access should not be masked (unsafe), false otherwise. /// Optional function to handle invalid memory accesses - public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize, bool unsafeMode, InvalidAccessHandler invalidAccessHandler = null) + public MemoryManagerHostMapped(AddressSpace addressSpace, bool unsafeMode, InvalidAccessHandler invalidAccessHandler) { + _addressSpace = addressSpace; _pageTable = new PageTable(); _invalidAccessHandler = invalidAccessHandler; _unsafeMode = unsafeMode; - _addressSpaceSize = addressSpaceSize; + AddressSpaceSize = addressSpace.AddressSpaceSize; ulong asSize = PageSize; int asBits = PageBits; - while (asSize < addressSpaceSize) + while (asSize < AddressSpaceSize) { asSize <<= 1; asBits++; @@ -86,8 +87,6 @@ public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize _pageBitmap = new ulong[1 << (AddressSpaceBits - (PageBits + PageToPteShift))]; - _addressSpace = new AddressSpace(backingMemory, asSize, Supports4KBPages); - Tracking = new MemoryTracking(this, (int)MemoryBlock.GetPageSize(), invalidAccessHandler); _memoryEh = new MemoryEhMeilleure(_addressSpace.Base, _addressSpace.Mirror, Tracking); } @@ -99,7 +98,7 @@ public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize /// True if the virtual address is part of the addressable space private bool ValidateAddress(ulong va) { - return va < _addressSpaceSize; + return va < AddressSpaceSize; } /// @@ -111,7 +110,7 @@ private bool ValidateAddress(ulong va) private bool ValidateAddressAndSize(ulong va, ulong size) { ulong endVa = va + size; - return endVa >= va && endVa >= size && endVa <= _addressSpaceSize; + return endVa >= va && endVa >= size && endVa <= AddressSpaceSize; } /// diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContext.cs b/src/Ryujinx.HLE/HOS/ArmProcessContext.cs index 6338edc1e66f..99b355286865 100644 --- a/src/Ryujinx.HLE/HOS/ArmProcessContext.cs +++ b/src/Ryujinx.HLE/HOS/ArmProcessContext.cs @@ -25,7 +25,15 @@ class ArmProcessContext : IArmProcessContext where T : class, IVirtualMemoryM 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) { @@ -38,6 +46,8 @@ public ArmProcessContext(ulong pid, ICpuEngine cpuEngine, GpuContext gpuContext, _gpuContext = gpuContext; _cpuContext = cpuEngine.CreateCpuContext(memoryManager, for64Bit); _memoryManager = memoryManager; + + AddressSpaceSize = addressSpaceSize; } public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks) diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs index 1b0d66ac6245..140b10a26aaf 100644 --- a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs +++ b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs @@ -1,4 +1,5 @@ using Ryujinx.Common.Configuration; +using Ryujinx.Common.Logging; using Ryujinx.Cpu; using Ryujinx.Cpu.AppleHv; using Ryujinx.Cpu.Jit; @@ -49,7 +50,7 @@ public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpa { var cpuEngine = new HvEngine(_tickSource); var memoryManager = new HvMemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler); - processContext = new ArmProcessContext(pid, cpuEngine, _gpu, memoryManager, for64Bit); + processContext = new ArmProcessContext(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit); } else { @@ -57,23 +58,41 @@ public IProcessContext Create(KernelContext context, ulong pid, ulong addressSpa 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; } 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) { case MemoryManagerMode.SoftwarePageTable: var memoryManager = new MemoryManager(context.Memory, addressSpaceSize, invalidAccessHandler); - processContext = new ArmProcessContext(pid, cpuEngine, _gpu, memoryManager, for64Bit); + processContext = new ArmProcessContext(pid, cpuEngine, _gpu, memoryManager, addressSpaceSize, for64Bit); break; case MemoryManagerMode.HostMapped: case MemoryManagerMode.HostMappedUnsafe: - bool unsafeMode = mode == MemoryManagerMode.HostMappedUnsafe; - var memoryManagerHostMapped = new MemoryManagerHostMapped(context.Memory, addressSpaceSize, unsafeMode, invalidAccessHandler); - processContext = new ArmProcessContext(pid, cpuEngine, _gpu, memoryManagerHostMapped, for64Bit); + if (addressSpaceSize != addressSpace.AddressSpaceSize) + { + 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(pid, cpuEngine, _gpu, memoryManagerHostMapped, addressSpace.AddressSpaceSize, for64Bit); break; default: diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs index 28e9f90aa6d2..119034c16325 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs @@ -13,7 +13,7 @@ class KPageTable : KPageTableBase 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; } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs index 614eb52713ca..6746a0a7a557 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -22,6 +22,8 @@ abstract class KPageTableBase 0x40000000 }; + private const ulong RegionAlignment = 0x200000; + public const int PageSize = 0x1000; private const int KMemoryBlockSize = 0x40; @@ -53,6 +55,9 @@ abstract class KPageTableBase public ulong TlsIoRegionStart { get; private set; } public ulong TlsIoRegionEnd { get; private set; } + public ulong AslrRegionStart { get; private set; } + public ulong AslrRegionEnd { get; private set; } + private ulong _heapCapacity; public ulong PhysicalMemoryUsage { get; private set; } @@ -61,10 +66,7 @@ abstract class KPageTableBase private MemoryRegion _memRegion; - private bool _aslrDisabled; - - public int AddrSpaceWidth { get; private set; } - + private bool _allocateFromBack; private bool _isKernel; private bool _aslrEnabled; @@ -78,7 +80,9 @@ abstract class KPageTableBase private MemoryFillValue _heapFillValue; private MemoryFillValue _ipcFillValue; - public KPageTableBase(KernelContext context) + private ulong _reservedAddressSpaceSize; + + public KPageTableBase(KernelContext context, ulong reservedAddressSpaceSize) { Context = context; @@ -88,6 +92,8 @@ public KPageTableBase(KernelContext context) _heapFillValue = MemoryFillValue.Zero; _ipcFillValue = MemoryFillValue.Zero; + + _reservedAddressSpaceSize = reservedAddressSpaceSize; } private static readonly int[] AddrSpaceSizes = new int[] { 32, 36, 32, 39 }; @@ -95,7 +101,7 @@ public KPageTableBase(KernelContext context) public Result InitializeForProcess( AddressSpaceType addrSpaceType, bool aslrEnabled, - bool aslrDisabled, + bool fromBack, MemoryRegion memRegion, ulong address, ulong size, @@ -114,7 +120,7 @@ public Result InitializeForProcess( Result result = CreateUserAddressSpace( addrSpaceType, aslrEnabled, - aslrDisabled, + fromBack, addrSpaceBase, addrSpaceSize, memRegion, @@ -130,7 +136,7 @@ public Result InitializeForProcess( return result; } - private class Region + private struct Region { public ulong Start; public ulong End; @@ -141,7 +147,7 @@ private class Region private Result CreateUserAddressSpace( AddressSpaceType addrSpaceType, bool aslrEnabled, - bool aslrDisabled, + bool fromBack, ulong addrSpaceStart, ulong addrSpaceEnd, MemoryRegion memRegion, @@ -159,7 +165,6 @@ private Result CreateUserAddressSpace( ulong codeRegionSize; ulong stackAndTlsIoStart; ulong stackAndTlsIoEnd; - ulong baseAddress; switch (addrSpaceType) { @@ -170,10 +175,10 @@ private Result CreateUserAddressSpace( tlsIoRegion.Size = 0; CodeRegionStart = 0x200000; codeRegionSize = 0x3fe00000; + AslrRegionStart = 0x200000; + AslrRegionEnd = AslrRegionStart + 0xffe00000; stackAndTlsIoStart = 0x200000; stackAndTlsIoEnd = 0x40000000; - baseAddress = 0x200000; - AddrSpaceWidth = 32; break; case AddressSpaceType.Addr36Bits: @@ -183,10 +188,10 @@ private Result CreateUserAddressSpace( tlsIoRegion.Size = 0; CodeRegionStart = 0x8000000; codeRegionSize = 0x78000000; + AslrRegionStart = 0x8000000; + AslrRegionEnd = AslrRegionStart + 0xff8000000; stackAndTlsIoStart = 0x8000000; stackAndTlsIoEnd = 0x80000000; - baseAddress = 0x8000000; - AddrSpaceWidth = 36; break; case AddressSpaceType.Addr32BitsNoMap: @@ -196,23 +201,42 @@ private Result CreateUserAddressSpace( tlsIoRegion.Size = 0; CodeRegionStart = 0x200000; codeRegionSize = 0x3fe00000; + AslrRegionStart = 0x200000; + AslrRegionEnd = AslrRegionStart + 0xffe00000; stackAndTlsIoStart = 0x200000; stackAndTlsIoEnd = 0x40000000; - baseAddress = 0x200000; - AddrSpaceWidth = 32; break; case AddressSpaceType.Addr39Bits: - aliasRegion.Size = 0x1000000000; - heapRegion.Size = 0x180000000; - stackRegion.Size = 0x80000000; - tlsIoRegion.Size = 0x1000000000; - CodeRegionStart = BitUtils.AlignDown(address, 0x200000); - codeRegionSize = BitUtils.AlignUp(endAddr, 0x200000) - CodeRegionStart; - stackAndTlsIoStart = 0; - stackAndTlsIoEnd = 0; - baseAddress = 0x8000000; - AddrSpaceWidth = 39; + if (_reservedAddressSpaceSize < addrSpaceEnd) + { + int addressSpaceWidth = (int)ulong.Log2(_reservedAddressSpaceSize); + + aliasRegion.Size = 1UL << (addressSpaceWidth - 3); + heapRegion.Size = 0x180000000; + stackRegion.Size = 1UL << (addressSpaceWidth - 8); + tlsIoRegion.Size = 1UL << (addressSpaceWidth - 3); + CodeRegionStart = BitUtils.AlignDown(address, RegionAlignment); + codeRegionSize = BitUtils.AlignUp(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; default: throw new ArgumentException(nameof(addrSpaceType)); @@ -223,11 +247,11 @@ private Result CreateUserAddressSpace( ulong mapBaseAddress; ulong mapAvailableSize; - if (CodeRegionStart - baseAddress >= addrSpaceEnd - CodeRegionEnd) + if (CodeRegionStart - AslrRegionStart >= addrSpaceEnd - CodeRegionEnd) { // Has more space before the start of the code region. - mapBaseAddress = baseAddress; - mapAvailableSize = CodeRegionStart - baseAddress; + mapBaseAddress = AslrRegionStart; + mapAvailableSize = CodeRegionStart - AslrRegionStart; } else { @@ -254,14 +278,14 @@ private Result CreateUserAddressSpace( if (aslrEnabled) { - aliasRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset >> 21) << 21; - heapRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset >> 21) << 21; - stackRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset >> 21) << 21; - tlsIoRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset >> 21) << 21; + aliasRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset / RegionAlignment) * RegionAlignment; + heapRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset / RegionAlignment) * RegionAlignment; + stackRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset / RegionAlignment) * RegionAlignment; + tlsIoRegion.AslrOffset = GetRandomValue(0, aslrMaxOffset / RegionAlignment) * RegionAlignment; } // 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.End = aliasRegion.Start + aliasRegion.Size; heapRegion.Start = mapBaseAddress + heapRegion.AslrOffset; @@ -271,12 +295,15 @@ private Result CreateUserAddressSpace( tlsIoRegion.Start = mapBaseAddress + tlsIoRegion.AslrOffset; tlsIoRegion.End = tlsIoRegion.Start + tlsIoRegion.Size; - SortRegion(heapRegion, aliasRegion); + SortRegion(ref aliasRegion, ref heapRegion, true); if (stackRegion.Size != 0) { - SortRegion(stackRegion, aliasRegion); - SortRegion(stackRegion, heapRegion); + stackRegion.Start = mapBaseAddress + stackRegion.AslrOffset; + stackRegion.End = stackRegion.Start + stackRegion.Size; + + SortRegion(ref aliasRegion, ref stackRegion); + SortRegion(ref heapRegion, ref stackRegion); } else { @@ -286,9 +313,16 @@ private Result CreateUserAddressSpace( if (tlsIoRegion.Size != 0) { - SortRegion(tlsIoRegion, aliasRegion); - SortRegion(tlsIoRegion, heapRegion); - SortRegion(tlsIoRegion, stackRegion); + tlsIoRegion.Start = mapBaseAddress + tlsIoRegion.AslrOffset; + tlsIoRegion.End = tlsIoRegion.Start + tlsIoRegion.Size; + + SortRegion(ref aliasRegion, ref tlsIoRegion); + SortRegion(ref heapRegion, ref tlsIoRegion); + + if (stackRegion.Size != 0) + { + SortRegion(ref stackRegion, ref tlsIoRegion); + } } else { @@ -312,11 +346,27 @@ private Result CreateUserAddressSpace( PhysicalMemoryUsage = 0; _memRegion = memRegion; - _aslrDisabled = aslrDisabled; + _allocateFromBack = fromBack; 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) { return (ulong)GetRandomValue((long)min, (long)max); @@ -332,20 +382,6 @@ private long GetRandomValue(long min, long 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) { ulong pagesCount = pageList.GetPagesCount(); @@ -1827,7 +1863,7 @@ void CleanUpForError() // If not, allocate a new page and copy the unaligned chunck. if (addressTruncated < addressRounded) { - dstFirstPagePa = GetMemoryRegionManager().AllocatePagesContiguous(Context, 1, _aslrDisabled); + dstFirstPagePa = GetMemoryRegionManager().AllocatePagesContiguous(Context, 1, _allocateFromBack); if (dstFirstPagePa == 0) { @@ -1841,7 +1877,7 @@ void CleanUpForError() // If not, allocate a new page and copy the unaligned chunck. if (endAddrTruncated < endAddrRounded && (addressTruncated == addressRounded || addressTruncated < endAddrTruncated)) { - dstLastPagePa = GetMemoryRegionManager().AllocatePagesContiguous(Context, 1, _aslrDisabled); + dstLastPagePa = GetMemoryRegionManager().AllocatePagesContiguous(Context, 1, _allocateFromBack); if (dstLastPagePa == 0) { @@ -2799,38 +2835,12 @@ private ulong GetSize(MemoryState state) public ulong GetAddrSpaceBaseAddr() { - if (AddrSpaceWidth == 36 || AddrSpaceWidth == 39) - { - return 0x8000000; - } - else if (AddrSpaceWidth == 32) - { - return 0x200000; - } - else - { - throw new InvalidOperationException("Invalid address space width!"); - } + return AslrRegionStart; } public ulong GetAddrSpaceSize() { - if (AddrSpaceWidth == 36) - { - return 0xff8000000; - } - else if (AddrSpaceWidth == 39) - { - return 0x7ff8000000; - } - else if (AddrSpaceWidth == 32) - { - return 0xffe00000; - } - else - { - throw new InvalidOperationException("Invalid address space width!"); - } + return AslrRegionEnd - AslrRegionStart; } private static ulong GetDramAddressFromPa(ulong pa) diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs index c8063a62aa04..bdfef9d7ad44 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs @@ -8,6 +8,8 @@ interface IProcessContext : IDisposable { IVirtualMemoryManager AddressSpace { get; } + ulong AddressSpaceSize { get; } + IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks); void Execute(IExecutionContext context, ulong codeAddress); void InvalidateCacheRegion(ulong address, ulong size); diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index 510c99ea30b4..c284243aef1c 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -1082,7 +1082,7 @@ private void InitializeMemoryManager(ProcessCreationFlags flags) 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) diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs index 872968309297..cab5c60827ea 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs @@ -8,9 +8,12 @@ class ProcessContext : IProcessContext { public IVirtualMemoryManager AddressSpace { get; } - public ProcessContext(IVirtualMemoryManager asManager) + public ulong AddressSpaceSize { get; } + + public ProcessContext(IVirtualMemoryManager asManager, ulong addressSpaceSize) { AddressSpace = asManager; + AddressSpaceSize = addressSpaceSize; } public IExecutionContext CreateExecutionContext(ExceptionCallbacks exceptionCallbacks) diff --git a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs index 1c5798b40ef7..60dd5abf167f 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs @@ -6,7 +6,7 @@ class ProcessContextFactory : IProcessContextFactory { 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); } } }