aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Ryujinx.Cpu/AddressSpace.cs45
-rw-r--r--src/Ryujinx.Cpu/Jit/MemoryManagerHostMapped.cs19
-rw-r--r--src/Ryujinx.HLE/HOS/ArmProcessContext.cs12
-rw-r--r--src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs29
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs2
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs180
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Process/IProcessContext.cs2
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs2
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContext.cs5
-rw-r--r--src/Ryujinx.HLE/HOS/Kernel/Process/ProcessContextFactory.cs2
10 files changed, 187 insertions, 111 deletions
diff --git a/src/Ryujinx.Cpu/AddressSpace.cs b/src/Ryujinx.Cpu/AddressSpace.cs
index 9dc32426..0e27b158 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<PrivateMapping>();
_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 363f9000..3686eb08 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<ulong> _pageTable;
@@ -62,21 +63,21 @@ namespace Ryujinx.Cpu.Jit
/// <summary>
/// Creates a new instance of the host mapped memory manager.
/// </summary>
- /// <param name="backingMemory">Physical backing memory where virtual memory will be mapped to</param>
- /// <param name="addressSpaceSize">Size of the address space</param>
+ /// <param name="addressSpace">Address space instance to use</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>
- 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>();
_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
/// <returns>True if the virtual address is part of the addressable space</returns>
private bool ValidateAddress(ulong va)
{
- return va < _addressSpaceSize;
+ return va < AddressSpaceSize;
}
/// <summary>
@@ -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;
}
/// <summary>
diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContext.cs b/src/Ryujinx.HLE/HOS/ArmProcessContext.cs
index 6338edc1..99b35528 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 1b0d66ac..140b10a2 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<HvMemoryManager>(pid, cpuEngine, _gpu, memoryManager, for64Bit);
+ processContext = new ArmProcessContext<HvMemoryManager>(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<MemoryManager>(pid, cpuEngine, _gpu, memoryManager, for64Bit);
+ processContext = new ArmProcessContext<MemoryManager>(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<MemoryManagerHostMapped>(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<MemoryManagerHostMapped>(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 28e9f90a..119034c1 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 614eb527..6746a0a7 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<ulong>(address, 0x200000);
- codeRegionSize = BitUtils.AlignUp<ulong>(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<ulong>(address, RegionAlignment);
+ 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;
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 c8063a62..bdfef9d7 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 510c99ea..c284243a 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 87296830..cab5c608 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 1c5798b4..60dd5abf 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);
}
}
}