Change SvcGetInfo 5 to return actual heap size, remove AMemoryAlloc since it is no longer needed with direct memory access, move some memory management logic out of AMemoryMgr, change default virtual filesystem path to AppData

This commit is contained in:
gdkchan 2018-02-27 20:45:07 -03:00
parent 1cb0bbe585
commit 22fa2f77c6
4 changed files with 73 additions and 166 deletions

View File

@ -41,9 +41,9 @@ namespace ChocolArm64.Memory
private byte* RamPtr;
public AMemory(IntPtr Ram, AMemoryAlloc Allocator)
public AMemory(IntPtr Ram)
{
Manager = new AMemoryMgr(Allocator);
Manager = new AMemoryMgr();
Monitors = new Dictionary<int, ExMonitor>();

View File

@ -1,35 +0,0 @@
using ChocolArm64.Exceptions;
namespace ChocolArm64.Memory
{
public class AMemoryAlloc
{
private long PhysPos;
public long Alloc(long Size)
{
long Position = PhysPos;
Size = AMemoryHelper.PageRoundUp(Size);
PhysPos += Size;
if (PhysPos > AMemoryMgr.RamSize || PhysPos < 0)
{
throw new VmmOutOfMemoryException(Size);
}
return Position;
}
public void Free(long Position)
{
//TODO
}
public long GetFreeMem()
{
return AMemoryMgr.RamSize - PhysPos;
}
}
}

View File

@ -1,6 +1,6 @@
namespace ChocolArm64.Memory
{
public struct AMemoryMapInfo
public class AMemoryMapInfo
{
public long Position { get; private set; }
public long Size { get; private set; }

View File

@ -1,3 +1,5 @@
using System;
namespace ChocolArm64.Memory
{
public class AMemoryMgr
@ -5,22 +7,20 @@ namespace ChocolArm64.Memory
public const long AddrSize = RamSize;
public const long RamSize = 4L * 1024 * 1024 * 1024;
private const int PTLvl0Bits = 11;
private const int PTLvl1Bits = 13;
private const int PTPageBits = 12;
private const int PTLvl0Bits = 10;
private const int PTLvl1Bits = 10;
private const int PTPageBits = 12;
private const int PTLvl0Size = 1 << PTLvl0Bits;
private const int PTLvl1Size = 1 << PTLvl1Bits;
public const int PageSize = 1 << PTPageBits;
private const int PTLvl0Size = 1 << PTLvl0Bits;
private const int PTLvl1Size = 1 << PTLvl1Bits;
public const int PageSize = 1 << PTPageBits;
private const int PTLvl0Mask = PTLvl0Size - 1;
private const int PTLvl1Mask = PTLvl1Size - 1;
public const int PageMask = PageSize - 1;
private const int PTLvl0Mask = PTLvl0Size - 1;
private const int PTLvl1Mask = PTLvl1Size - 1;
public const int PageMask = PageSize - 1;
private const int PTLvl0Bit = PTPageBits + PTLvl0Bits;
private const int PTLvl1Bit = PTPageBits;
private AMemoryAlloc Allocator;
private const int PTLvl0Bit = PTPageBits + PTLvl1Bits;
private const int PTLvl1Bit = PTPageBits;
private enum PTMap
{
@ -47,132 +47,24 @@ namespace ChocolArm64.Memory
private PTEntry[][] PageTable;
private bool IsHeapInitialized;
public long HeapAddr { get; private set; }
public long HeapSize { get; private set; }
public AMemoryMgr(AMemoryAlloc Allocator)
public AMemoryMgr()
{
this.Allocator = Allocator;
PageTable = new PTEntry[PTLvl0Size][];
}
public long GetTotalMemorySize()
public void Map(long Position, long Size, int Type, AMemoryPerm Perm)
{
return Allocator.GetFreeMem() + GetUsedMemorySize();
SetPTEntry(Position, Size, new PTEntry(PTMap.Mapped, Perm, Type, 0));
}
public long GetUsedMemorySize()
public void Unmap(long Position, long Size)
{
long Size = 0;
for (int L0 = 0; L0 < PageTable.Length; L0++)
{
if (PageTable[L0] == null)
{
continue;
}
for (int L1 = 0; L1 < PageTable[L0].Length; L1++)
{
Size += PageTable[L0][L1].Map != PTMap.Unmapped ? PageSize : 0;
}
}
return Size;
SetPTEntry(Position, Size, new PTEntry(PTMap.Unmapped, 0, 0, 0));
}
public bool SetHeapAddr(long Position)
public void Unmap(long Position, long Size, int Type)
{
if (!IsHeapInitialized)
{
HeapAddr = Position;
IsHeapInitialized = true;
return true;
}
return false;
}
public void SetHeapSize(long Size, int Type)
{
//TODO: Return error when theres no enough space to allocate heap.
Size = AMemoryHelper.PageRoundUp(Size);
long Position = HeapAddr;
if ((ulong)Size < (ulong)HeapSize)
{
//Try to free now free area if size is smaller than old size.
Position += Size;
while ((ulong)Size < (ulong)HeapSize)
{
Allocator.Free(Position);
Position += PageSize;
}
}
else
{
//Allocate extra needed size.
Position += HeapSize;
Size -= HeapSize;
MapPhys(Position, Size, Type, AMemoryPerm.RW);
}
HeapSize = Size;
}
public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm)
{
while (Size > 0)
{
if (!IsMapped(Position))
{
SetPTEntry(Position, new PTEntry(PTMap.Mapped, Perm, Type, 0));
}
long CPgSize = PageSize - (Position & PageMask);
Position += CPgSize;
Size -= CPgSize;
}
}
public void MapMirror(long Src, long Dst, long Size, int Type)
{
Src = AMemoryHelper.PageRoundDown(Src);
Dst = AMemoryHelper.PageRoundDown(Dst);
Size = AMemoryHelper.PageRoundUp(Size);
long PagesCount = Size / PageSize;
while (PagesCount-- > 0)
{
PTEntry SrcEntry = GetPTEntry(Src);
PTEntry DstEntry = GetPTEntry(Dst);
DstEntry.Map = PTMap.Mapped;
DstEntry.Type = Type;
DstEntry.Perm = SrcEntry.Perm;
SrcEntry.Perm = AMemoryPerm.None;
SrcEntry.Attr |= 1;
SetPTEntry(Src, SrcEntry);
SetPTEntry(Dst, DstEntry);
Src += PageSize;
Dst += PageSize;
}
SetPTEntry(Position, Size, Type, new PTEntry(PTMap.Unmapped, 0, 0, 0));
}
public void Reprotect(long Position, long Size, AMemoryPerm Perm)
@ -197,12 +89,22 @@ namespace ChocolArm64.Memory
public AMemoryMapInfo GetMapInfo(long Position)
{
if (!IsValidPosition(Position))
{
return null;
}
Position = AMemoryHelper.PageRoundDown(Position);
PTEntry BaseEntry = GetPTEntry(Position);
bool IsSameSegment(long Pos)
{
if (!IsValidPosition(Pos))
{
return false;
}
PTEntry Entry = GetPTEntry(Pos);
return Entry.Map == BaseEntry.Map &&
@ -269,6 +171,16 @@ namespace ChocolArm64.Memory
return GetPTEntry(Position).Perm.HasFlag(Perm);
}
public bool IsValidPosition(long Position)
{
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
{
return false;
}
return true;
}
public bool IsMapped(long Position)
{
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
@ -300,8 +212,38 @@ namespace ChocolArm64.Memory
return PageTable[L0][L1];
}
private void SetPTEntry(long Position, long Size, PTEntry Entry)
{
while (Size > 0)
{
SetPTEntry(Position, Entry);
Position += PageSize;
Size -= PageSize;
}
}
private void SetPTEntry(long Position, long Size, int Type, PTEntry Entry)
{
while (Size > 0)
{
if (GetPTEntry(Position).Type == Type)
{
SetPTEntry(Position, Entry);
}
Position += PageSize;
Size -= PageSize;
}
}
private void SetPTEntry(long Position, PTEntry Entry)
{
if (!IsValidPosition(Position))
{
throw new ArgumentOutOfRangeException(nameof(Position));
}
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;