diff --git a/src/Ryujinx.Cpu/AddressSpace.cs b/src/Ryujinx.Cpu/AddressSpace.cs index 9dc32426cd..0e27b15823 100644 --- a/src/Ryujinx.Cpu/AddressSpace.cs +++ b/src/Ryujinx.Cpu/AddressSpace.cs @@ -5,7 +5,7 @@ using System; namespace Ryujinx.Cpu { - class AddressSpace : IDisposable + public class AddressSpace : IDisposable { private const ulong PageSize = 0x1000; @@ -154,7 +154,9 @@ namespace Ryujinx.Cpu 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 @@ namespace Ryujinx.Cpu _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 363f9000d7..3686eb0882 100644 --- a/src/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs +++ b/src/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs @@ -38,7 +38,8 @@ namespace Ryujinx.Cpu.Jit private readonly bool _unsafeMode; private readonly AddressSpace _addressSpace; - private readonly ulong _addressSpaceSize; + + public ulong AddressSpaceSize { get; } private readonly PageTable _pageTable; @@ -62,21 +63,21 @@ namespace Ryujinx.Cpu.Jit /// /// 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 @@ namespace Ryujinx.Cpu.Jit _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 @@ namespace Ryujinx.Cpu.Jit /// 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 @@ namespace Ryujinx.Cpu.Jit 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 6338edc1e6..99b3552868 100644 --- a/src/Ryujinx.HLE/HOS/ArmProcessContext.cs +++ b/src/Ryujinx.HLE/HOS/ArmProcessContext.cs @@ -25,7 +25,15 @@ namespace Ryujinx.HLE.HOS 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 @@ namespace Ryujinx.HLE.HOS _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 1b0d66ac62..140b10a26a 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 @@ namespace Ryujinx.HLE.HOS { 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 @@ namespace Ryujinx.HLE.HOS 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 28e9f90aa6..119034c163 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs @@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 614eb52713..6746a0a7a5 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs @@ -22,6 +22,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 0x40000000 }; + private const ulong RegionAlignment = 0x200000; + public const int PageSize = 0x1000; private const int KMemoryBlockSize = 0x40; @@ -53,6 +55,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory _heapFillValue = MemoryFillValue.Zero; _ipcFillValue = MemoryFillValue.Zero; + + _reservedAddressSpaceSize = reservedAddressSpaceSize; } private static readonly int[] AddrSpaceSizes = new int[] { 32, 36, 32, 39 }; @@ -95,7 +101,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory public Result InitializeForProcess( AddressSpaceType addrSpaceType, bool aslrEnabled, - bool aslrDisabled, + bool fromBack, MemoryRegion memRegion, ulong address, ulong size, @@ -114,7 +120,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory Result result = CreateUserAddressSpace( addrSpaceType, aslrEnabled, - aslrDisabled, + fromBack, addrSpaceBase, addrSpaceSize, memRegion, @@ -130,7 +136,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory return result; } - private class Region + private struct Region { public ulong Start; public ulong End; @@ -141,7 +147,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory private Result CreateUserAddressSpace( AddressSpaceType addrSpaceType, bool aslrEnabled, - bool aslrDisabled, + bool fromBack, ulong addrSpaceStart, ulong addrSpaceEnd, MemoryRegion memRegion, @@ -159,7 +165,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory ulong codeRegionSize; ulong stackAndTlsIoStart; ulong stackAndTlsIoEnd; - ulong baseAddress; switch (addrSpaceType) { @@ -170,10 +175,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory // 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory // 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 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory 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 c8063a62aa..bdfef9d7ad 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs @@ -8,6 +8,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { 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 510c99ea30..c284243aef 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -1082,7 +1082,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process 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 8729683092..cab5c60827 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs @@ -8,9 +8,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { 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 1c5798b40e..60dd5abf16 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs @@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process { 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); } } }