mirror of
https://github.com/Ryujinx/ChocolArm64.git
synced 2024-12-22 19:15:38 +00:00
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
1cb0bbe585
commit
22fa2f77c6
|
@ -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>();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
|
|
|
@ -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…
Reference in a new issue