Fixes to memory management

This commit is contained in:
gdkchan 2018-02-09 21:13:18 -03:00
parent ccc9ce1908
commit 7f4a190665
6 changed files with 51 additions and 72 deletions

View file

@ -5,7 +5,7 @@ namespace ChocolArm64.Exceptions
{ {
public class VmmAccessViolationException : Exception public class VmmAccessViolationException : Exception
{ {
private const string ExMsg = "Value at address 0x{0:x16} could not be \"{1}\"!"; private const string ExMsg = "Address 0x{0:x16} does not have \"{1}\" permission!";
public VmmAccessViolationException() { } public VmmAccessViolationException() { }

View file

@ -5,14 +5,16 @@ namespace ChocolArm64.Memory
public long Position { get; private set; } public long Position { get; private set; }
public long Size { get; private set; } public long Size { get; private set; }
public int Type { get; private set; } public int Type { get; private set; }
public int Attr { get; private set; }
public AMemoryPerm Perm { get; private set; } public AMemoryPerm Perm { get; private set; }
public AMemoryMapInfo(long Position, long Size, int Type, AMemoryPerm Perm) public AMemoryMapInfo(long Position, long Size, int Type, int Attr, AMemoryPerm Perm)
{ {
this.Position = Position; this.Position = Position;
this.Size = Size; this.Size = Size;
this.Type = Type; this.Type = Type;
this.Attr = Attr;
this.Perm = Perm; this.Perm = Perm;
} }
} }

View file

@ -1,5 +1,3 @@
using System.Runtime.CompilerServices;
namespace ChocolArm64.Memory namespace ChocolArm64.Memory
{ {
public class AMemoryMgr public class AMemoryMgr
@ -27,24 +25,23 @@ namespace ChocolArm64.Memory
private enum PTMap private enum PTMap
{ {
Unmapped, Unmapped,
Physical, Mapped
Mirror
} }
private struct PTEntry private struct PTEntry
{ {
public long Position;
public int Type;
public PTMap Map; public PTMap Map;
public AMemoryPerm Perm; public AMemoryPerm Perm;
public PTEntry(long Position, int Type, PTMap Map, AMemoryPerm Perm) public int Type;
public int Attr;
public PTEntry(PTMap Map, AMemoryPerm Perm, int Type, int Attr)
{ {
this.Position = Position; this.Map = Map;
this.Type = Type; this.Perm = Perm;
this.Map = Map; this.Type = Type;
this.Perm = Perm; this.Attr = Attr;
} }
} }
@ -53,7 +50,7 @@ namespace ChocolArm64.Memory
private bool IsHeapInitialized; private bool IsHeapInitialized;
public long HeapAddr { get; private set; } public long HeapAddr { get; private set; }
public int HeapSize { get; private set; } public long HeapSize { get; private set; }
public AMemoryMgr(AMemoryAlloc Allocator) public AMemoryMgr(AMemoryAlloc Allocator)
{ {
@ -101,10 +98,10 @@ namespace ChocolArm64.Memory
return false; return false;
} }
public void SetHeapSize(int Size, int Type) public void SetHeapSize(long Size, int Type)
{ {
//TODO: Return error when theres no enough space to allocate heap. //TODO: Return error when theres no enough space to allocate heap.
Size = (int)AMemoryHelper.PageRoundUp(Size); Size = AMemoryHelper.PageRoundUp(Size);
long Position = HeapAddr; long Position = HeapAddr;
@ -132,40 +129,13 @@ namespace ChocolArm64.Memory
HeapSize = Size; HeapSize = Size;
} }
public bool MapPhys(long Src, long Dst, long Size, int Type, AMemoryPerm Perm)
{
Src = AMemoryHelper.PageRoundDown(Src);
Dst = AMemoryHelper.PageRoundDown(Dst);
Size = AMemoryHelper.PageRoundUp(Size);
if (Dst < 0 || Dst + Size >= RamSize)
{
return false;
}
long PagesCount = Size / PageSize;
while (PagesCount-- > 0)
{
SetPTEntry(Src, new PTEntry(Dst, Type, PTMap.Physical, Perm));
Src += PageSize;
Dst += PageSize;
}
return true;
}
public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm) public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm)
{ {
while (Size > 0) while (Size > 0)
{ {
if (!IsMapped(Position)) if (!IsMapped(Position))
{ {
long PhysPos = Allocator.Alloc(PageSize); SetPTEntry(Position, new PTEntry(PTMap.Mapped, Perm, Type, 0));
SetPTEntry(Position, new PTEntry(PhysPos, Type, PTMap.Physical, Perm));
} }
long CPgSize = PageSize - (Position & PageMask); long CPgSize = PageSize - (Position & PageMask);
@ -186,13 +156,19 @@ namespace ChocolArm64.Memory
while (PagesCount-- > 0) while (PagesCount-- > 0)
{ {
PTEntry Entry = GetPTEntry(Src); PTEntry SrcEntry = GetPTEntry(Src);
PTEntry DstEntry = GetPTEntry(Dst);
Entry.Type = Type; DstEntry.Map = PTMap.Mapped;
Entry.Map = PTMap.Mirror; DstEntry.Type = Type;
Entry.Position = Dst; DstEntry.Perm = SrcEntry.Perm;
SetPTEntry(Src, Entry); SrcEntry.Perm = AMemoryPerm.None;
SrcEntry.Attr |= 1;
SetPTEntry(Src, SrcEntry);
SetPTEntry(Dst, DstEntry);
Src += PageSize; Src += PageSize;
Dst += PageSize; Dst += PageSize;
@ -229,9 +205,10 @@ namespace ChocolArm64.Memory
{ {
PTEntry Entry = GetPTEntry(Pos); PTEntry Entry = GetPTEntry(Pos);
return Entry.Type == BaseEntry.Type && return Entry.Map == BaseEntry.Map &&
Entry.Map == BaseEntry.Map && Entry.Perm == BaseEntry.Perm &&
Entry.Perm == BaseEntry.Perm; Entry.Type == BaseEntry.Type &&
Entry.Attr == BaseEntry.Attr;
} }
long Start = Position; long Start = Position;
@ -249,7 +226,12 @@ namespace ChocolArm64.Memory
long Size = End - Start; long Size = End - Start;
return new AMemoryMapInfo(Start, Size, BaseEntry.Type, BaseEntry.Perm); return new AMemoryMapInfo(
Start,
Size,
BaseEntry.Type,
BaseEntry.Attr,
BaseEntry.Perm);
} }
public bool HasPermission(long Position, AMemoryPerm Perm) public bool HasPermission(long Position, AMemoryPerm Perm)
@ -257,7 +239,6 @@ namespace ChocolArm64.Memory
return GetPTEntry(Position).Perm.HasFlag(Perm); return GetPTEntry(Position).Perm.HasFlag(Perm);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsMapped(long Position) public bool IsMapped(long Position)
{ {
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0) if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
@ -276,7 +257,6 @@ namespace ChocolArm64.Memory
return PageTable[L0][L1].Map != PTMap.Unmapped; return PageTable[L0][L1].Map != PTMap.Unmapped;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private PTEntry GetPTEntry(long Position) private PTEntry GetPTEntry(long Position)
{ {
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
@ -290,7 +270,6 @@ namespace ChocolArm64.Memory
return PageTable[L0][L1]; return PageTable[L0][L1];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SetPTEntry(long Position, PTEntry Entry) private void SetPTEntry(long Position, PTEntry Entry)
{ {
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;

View file

@ -1,5 +1,3 @@
using System.Runtime.CompilerServices;
namespace Ryujinx.Gpu namespace Ryujinx.Gpu
{ {
class NsGpuMemoryMgr class NsGpuMemoryMgr
@ -16,7 +14,7 @@ namespace Ryujinx.Gpu
private const int PTLvl0Mask = PTLvl0Size - 1; private const int PTLvl0Mask = PTLvl0Size - 1;
private const int PTLvl1Mask = PTLvl1Size - 1; private const int PTLvl1Mask = PTLvl1Size - 1;
private const int PageMask = PageSize - 1; private const int PageMask = PageSize - 1;
private const int PTLvl0Bit = PTPageBits + PTLvl0Bits; private const int PTLvl0Bit = PTPageBits + PTLvl0Bits;
private const int PTLvl1Bit = PTPageBits; private const int PTLvl1Bit = PTPageBits;
@ -107,6 +105,11 @@ namespace Ryujinx.Gpu
long Position = 0; long Position = 0;
long FreeSize = 0; long FreeSize = 0;
if (Align < 1)
{
Align = 1;
}
Align = (Align + PageMask) & ~PageMask; Align = (Align + PageMask) & ~PageMask;
while (Position + FreeSize < AddrSize) while (Position + FreeSize < AddrSize)
@ -149,7 +152,6 @@ namespace Ryujinx.Gpu
return BasePos + (Position & PageMask); return BasePos + (Position & PageMask);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool HasPTAddr(long Position) private bool HasPTAddr(long Position)
{ {
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0) if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
@ -168,7 +170,6 @@ namespace Ryujinx.Gpu
return PageTable[L0][L1] != PteUnmapped; return PageTable[L0][L1] != PteUnmapped;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private long GetPTAddr(long Position) private long GetPTAddr(long Position)
{ {
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
@ -182,7 +183,6 @@ namespace Ryujinx.Gpu
return PageTable[L0][L1]; return PageTable[L0][L1];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SetPTAddr(long Position, long TgtAddr) private void SetPTAddr(long Position, long TgtAddr)
{ {
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;

View file

@ -18,7 +18,7 @@ namespace Ryujinx.OsHle
BaseAddress = MapInfo.Position; BaseAddress = MapInfo.Position;
Size = MapInfo.Size; Size = MapInfo.Size;
MemType = MapInfo.Type; MemType = MapInfo.Type;
MemAttr = 0; MemAttr = MapInfo.Attr;
MemPerm = (int)MapInfo.Perm; MemPerm = (int)MapInfo.Perm;
IpcRefCount = 0; IpcRefCount = 0;
DeviceRefCount = 0; DeviceRefCount = 0;

View file

@ -8,7 +8,7 @@ namespace Ryujinx.OsHle.Svc
{ {
private static void SvcSetHeapSize(Switch Ns, ARegisters Registers, AMemory Memory) private static void SvcSetHeapSize(Switch Ns, ARegisters Registers, AMemory Memory)
{ {
int Size = (int)Registers.X1; uint Size = (uint)Registers.X1;
Memory.Manager.SetHeapSize(Size, (int)MemoryType.Heap); Memory.Manager.SetHeapSize(Size, (int)MemoryType.Heap);
@ -30,8 +30,8 @@ namespace Ryujinx.OsHle.Svc
private static void SvcMapMemory(Switch Ns, ARegisters Registers, AMemory Memory) private static void SvcMapMemory(Switch Ns, ARegisters Registers, AMemory Memory)
{ {
long Src = (long)Registers.X0; long Dst = (long)Registers.X0;
long Dst = (long)Registers.X1; long Src = (long)Registers.X1;
long Size = (long)Registers.X2; long Size = (long)Registers.X2;
Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory); Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory);
@ -79,11 +79,9 @@ namespace Ryujinx.OsHle.Svc
HndData.VirtPos = Src; HndData.VirtPos = Src;
if (Memory.Manager.MapPhys(Src, Dst, Size, Memory.Manager.MapPhys(Position, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
(int)MemoryType.SharedMemory, (AMemoryPerm)Perm))
{ Registers.X0 = (int)SvcResult.Success;
Registers.X0 = (int)SvcResult.Success;
}
} }
//TODO: Error codes. //TODO: Error codes.