More flexible memory manager (#307)

* Keep track mapped buffers with fixed offsets

* Started rewriting the memory manager

* Initial support for MapPhysicalMemory and UnmapPhysicalMemory, other tweaks

* MapPhysicalMemory/UnmapPhysicalMemory support, other tweaks

* Rebased

* Optimize the map/unmap physical memory svcs

* Integrate shared font support

* Fix address space reserve alignment

* Some fixes related to gpu memory mapping

* Some cleanup

* Only try uploading const buffers that are really used

* Check if memory region is contiguous

* Rebased

* Add missing count increment on IsRegionModified

* Check for reads/writes outside of the address space, optimize translation with a tail call
This commit is contained in:
gdkchan 2018-08-15 15:59:51 -03:00 committed by GitHub
parent 76d95dee05
commit c393cdf8e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 3289 additions and 1852 deletions

View file

@ -0,0 +1,10 @@
namespace Ryujinx.HLE.OsHle.Handles
{
enum AddressSpaceType
{
Addr32Bits = 0,
Addr36Bits = 1,
Addr36BitsNoMap = 2,
Addr39Bits = 3
}
}

View file

@ -1,44 +0,0 @@
using ChocolArm64.Memory;
using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.OsHle.Handles
{
class HSharedMem
{
private List<(AMemory, long, long)> Positions;
public EventHandler<EventArgs> MemoryMapped;
public EventHandler<EventArgs> MemoryUnmapped;
public HSharedMem()
{
Positions = new List<(AMemory, long, long)>();
}
public void AddVirtualPosition(AMemory Memory, long Position, long Size)
{
lock (Positions)
{
Positions.Add((Memory, Position, Size));
MemoryMapped?.Invoke(this, EventArgs.Empty);
}
}
public void RemoveVirtualPosition(AMemory Memory, long Position, long Size)
{
lock (Positions)
{
Positions.Remove((Memory, Position, Size));
MemoryUnmapped?.Invoke(this, EventArgs.Empty);
}
}
public (AMemory, long, long)[] GetVirtualPositions()
{
return Positions.ToArray();
}
}
}

View file

@ -1,21 +0,0 @@
using ChocolArm64.Memory;
namespace Ryujinx.HLE.OsHle.Handles
{
class HTransferMem
{
public AMemory Memory { get; private set; }
public AMemoryPerm Perm { get; private set; }
public long Position { get; private set; }
public long Size { get; private set; }
public HTransferMem(AMemory Memory, AMemoryPerm Perm, long Position, long Size)
{
this.Memory = Memory;
this.Perm = Perm;
this.Position = Position;
this.Size = Size;
}
}
}

View file

@ -0,0 +1,43 @@
namespace Ryujinx.HLE.OsHle.Handles
{
class KMemoryBlock
{
public long BasePosition { get; set; }
public long PagesCount { get; set; }
public MemoryState State { get; set; }
public MemoryPermission Permission { get; set; }
public MemoryAttribute Attribute { get; set; }
public int IpcRefCount { get; set; }
public int DeviceRefCount { get; set; }
public KMemoryBlock(
long BasePosition,
long PagesCount,
MemoryState State,
MemoryPermission Permission,
MemoryAttribute Attribute)
{
this.BasePosition = BasePosition;
this.PagesCount = PagesCount;
this.State = State;
this.Attribute = Attribute;
this.Permission = Permission;
}
public KMemoryInfo GetInfo()
{
long Size = PagesCount * KMemoryManager.PageSize;
return new KMemoryInfo(
BasePosition,
Size,
State,
Permission,
Attribute,
IpcRefCount,
DeviceRefCount);
}
}
}

View file

@ -0,0 +1,33 @@
namespace Ryujinx.HLE.OsHle.Handles
{
class KMemoryInfo
{
public long Position { get; private set; }
public long Size { get; private set; }
public MemoryState State { get; private set; }
public MemoryPermission Permission { get; private set; }
public MemoryAttribute Attribute { get; private set; }
public int IpcRefCount { get; private set; }
public int DeviceRefCount { get; private set; }
public KMemoryInfo(
long Position,
long Size,
MemoryState State,
MemoryPermission Permission,
MemoryAttribute Attribute,
int IpcRefCount,
int DeviceRefCount)
{
this.Position = Position;
this.Size = Size;
this.State = State;
this.Attribute = Attribute;
this.Permission = Permission;
this.IpcRefCount = IpcRefCount;
this.DeviceRefCount = DeviceRefCount;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,14 @@
namespace Ryujinx.HLE.OsHle.Handles
{
class KSharedMemory
{
public long PA { get; private set; }
public long Size { get; private set; }
public KSharedMemory(long PA, long Size)
{
this.PA = PA;
this.Size = Size;
}
}
}

View file

@ -0,0 +1,60 @@
using System;
namespace Ryujinx.HLE.OsHle.Handles
{
class KTlsPageManager
{
private const int TlsEntrySize = 0x200;
private long PagePosition;
private int UsedSlots;
private bool[] Slots;
public bool IsEmpty => UsedSlots == 0;
public bool IsFull => UsedSlots == Slots.Length;
public KTlsPageManager(long PagePosition)
{
this.PagePosition = PagePosition;
Slots = new bool[KMemoryManager.PageSize / TlsEntrySize];
}
public bool TryGetFreeTlsAddr(out long Position)
{
Position = PagePosition;
for (int Index = 0; Index < Slots.Length; Index++)
{
if (!Slots[Index])
{
Slots[Index] = true;
UsedSlots++;
return true;
}
Position += TlsEntrySize;
}
Position = 0;
return false;
}
public void FreeTlsSlot(int Slot)
{
if ((uint)Slot > Slots.Length)
{
throw new ArgumentOutOfRangeException(nameof(Slot));
}
Slots[Slot] = false;
UsedSlots--;
}
}
}

View file

@ -0,0 +1,14 @@
namespace Ryujinx.HLE.OsHle.Handles
{
class KTransferMemory
{
public long Position { get; private set; }
public long Size { get; private set; }
public KTransferMemory(long Position, long Size)
{
this.Position = Position;
this.Size = Size;
}
}
}

View file

@ -0,0 +1,22 @@
using System;
namespace Ryujinx.HLE.OsHle.Handles
{
[Flags]
enum MemoryAttribute : byte
{
None = 0,
Mask = 0xff,
Borrowed = 1 << 0,
IpcMapped = 1 << 1,
DeviceMapped = 1 << 2,
Uncached = 1 << 3,
IpcAndDeviceMapped = IpcMapped | DeviceMapped,
BorrowedAndIpcMapped = Borrowed | IpcMapped,
DeviceMappedAndUncached = DeviceMapped | Uncached
}
}

View file

@ -0,0 +1,18 @@
using System;
namespace Ryujinx.HLE.OsHle.Handles
{
[Flags]
enum MemoryPermission : byte
{
None = 0,
Mask = 0xff,
Read = 1 << 0,
Write = 1 << 1,
Execute = 1 << 2,
ReadAndWrite = Read | Write,
ReadAndExecute = Read | Execute
}
}

View file

@ -0,0 +1,49 @@
using System;
namespace Ryujinx.HLE.OsHle
{
[Flags]
enum MemoryState : uint
{
Unmapped = 0x00000000,
Io = 0x00002001,
Normal = 0x00042002,
CodeStatic = 0x00DC7E03,
CodeMutable = 0x03FEBD04,
Heap = 0x037EBD05,
SharedMemory = 0x00402006,
ModCodeStatic = 0x00DD7E08,
ModCodeMutable = 0x03FFBD09,
IpcBuffer0 = 0x005C3C0A,
MappedMemory = 0x005C3C0B,
ThreadLocal = 0x0040200C,
TransferMemoryIsolated = 0x015C3C0D,
TransferMemory = 0x005C380E,
ProcessMemory = 0x0040380F,
Reserved = 0x00000010,
IpcBuffer1 = 0x005C3811,
IpcBuffer3 = 0x004C2812,
KernelStack = 0x00002013,
CodeReadOnly = 0x00402214,
CodeWritable = 0x00402015,
Mask = 0xffffffff,
PermissionChangeAllowed = 1 << 8,
ForceReadWritableByDebugSyscalls = 1 << 9,
IpcSendAllowedType0 = 1 << 10,
IpcSendAllowedType3 = 1 << 11,
IpcSendAllowedType1 = 1 << 12,
ProcessPermissionChangeAllowed = 1 << 14,
MapAllowed = 1 << 15,
UnmapProcessCodeMemoryAllowed = 1 << 16,
TransferMemoryAllowed = 1 << 17,
QueryPhysicalAddressAllowed = 1 << 18,
MapDeviceAllowed = 1 << 19,
MapDeviceAlignedAllowed = 1 << 20,
IpcBufferAllowed = 1 << 21,
IsPoolAllocated = 1 << 22,
MapProcessAllowed = 1 << 23,
AttributeChangeAllowed = 1 << 24,
CodeMemoryAllowed = 1 << 25
}
}