diff options
Diffstat (limited to 'src/Ryujinx.Cpu/AddressSpace.cs')
-rw-r--r-- | src/Ryujinx.Cpu/AddressSpace.cs | 45 |
1 files changed, 39 insertions, 6 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) |