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:
parent
708761963e
commit
f876bd2a80
17 changed files with 251 additions and 337 deletions
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue