From 22fa2f77c6bfb03216e44650cc4ec4ad794f63a8 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 27 Feb 2018 20:45:07 -0300 Subject: [PATCH] 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 --- Memory/AMemory.cs | 4 +- Memory/AMemoryAlloc.cs | 35 ------- Memory/AMemoryMapInfo.cs | 2 +- Memory/AMemoryMgr.cs | 198 ++++++++++++++------------------------- 4 files changed, 73 insertions(+), 166 deletions(-) delete mode 100644 Memory/AMemoryAlloc.cs diff --git a/Memory/AMemory.cs b/Memory/AMemory.cs index f2abffb..0d202fe 100644 --- a/Memory/AMemory.cs +++ b/Memory/AMemory.cs @@ -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(); diff --git a/Memory/AMemoryAlloc.cs b/Memory/AMemoryAlloc.cs deleted file mode 100644 index b11e779..0000000 --- a/Memory/AMemoryAlloc.cs +++ /dev/null @@ -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; - } - } -} \ No newline at end of file diff --git a/Memory/AMemoryMapInfo.cs b/Memory/AMemoryMapInfo.cs index 44b2cc0..02dd305 100644 --- a/Memory/AMemoryMapInfo.cs +++ b/Memory/AMemoryMapInfo.cs @@ -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; } diff --git a/Memory/AMemoryMgr.cs b/Memory/AMemoryMgr.cs index c8869e0..bc36445 100644 --- a/Memory/AMemoryMgr.cs +++ b/Memory/AMemoryMgr.cs @@ -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;