diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-08-15 15:59:51 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-08-15 15:59:51 -0300 |
| commit | c393cdf8e3775bc95850e4d8c8e4c446b286d3b4 (patch) | |
| tree | 25035a244741d2daf3f7d6be8b23153ff061ea15 /ChocolArm64/Memory/AMemory.cs | |
| parent | 76d95dee05e3c51c18e1799f54cc407e0f633b4e (diff) | |
More flexible memory manager (#307)
* Keep track mapped buffers with fixed offsets
* Started rewriting the memory manager
* Initial support for MapPhysicalMemory and UnmapPhysicalMemory, other tweaks
* MapPhysicalMemory/UnmapPhysicalMemory support, other tweaks
* Rebased
* Optimize the map/unmap physical memory svcs
* Integrate shared font support
* Fix address space reserve alignment
* Some fixes related to gpu memory mapping
* Some cleanup
* Only try uploading const buffers that are really used
* Check if memory region is contiguous
* Rebased
* Add missing count increment on IsRegionModified
* Check for reads/writes outside of the address space, optimize translation with a tail call
Diffstat (limited to 'ChocolArm64/Memory/AMemory.cs')
| -rw-r--r-- | ChocolArm64/Memory/AMemory.cs | 588 |
1 files changed, 277 insertions, 311 deletions
diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs index e969cca5..1b4ff6fb 100644 --- a/ChocolArm64/Memory/AMemory.cs +++ b/ChocolArm64/Memory/AMemory.cs @@ -1,6 +1,7 @@ using ChocolArm64.Exceptions; using ChocolArm64.State; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -12,9 +13,22 @@ namespace ChocolArm64.Memory { public unsafe class AMemory : IAMemory, IDisposable { - private const long ErgMask = (4 << AThreadState.ErgSizeLog2) - 1; + private const int PTLvl0Bits = 13; + private const int PTLvl1Bits = 14; + 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 PTLvl0Mask = PTLvl0Size - 1; + private const int PTLvl1Mask = PTLvl1Size - 1; + public const int PageMask = PageSize - 1; - public AMemoryMgr Manager { get; private set; } + private const int PTLvl0Bit = PTPageBits + PTLvl1Bits; + private const int PTLvl1Bit = PTPageBits; + + private const long ErgMask = (4 << AThreadState.ErgSizeLog2) - 1; private class ArmMonitor { @@ -29,32 +43,30 @@ namespace ChocolArm64.Memory private Dictionary<int, ArmMonitor> Monitors; + private ConcurrentDictionary<long, IntPtr> ObservedPages; + public IntPtr Ram { get; private set; } private byte* RamPtr; - private int HostPageSize; + private byte*** PageTable; - public AMemory() + public AMemory(IntPtr Ram) { - Manager = new AMemoryMgr(); - Monitors = new Dictionary<int, ArmMonitor>(); - IntPtr Size = (IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize; + ObservedPages = new ConcurrentDictionary<long, IntPtr>(); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Ram = AMemoryWin32.Allocate(Size); + this.Ram = Ram; - HostPageSize = AMemoryWin32.GetPageSize(Ram, Size); - } - else + RamPtr = (byte*)Ram; + + PageTable = (byte***)Marshal.AllocHGlobal(PTLvl0Size * IntPtr.Size); + + for (int L0 = 0; L0 < PTLvl0Size; L0++) { - Ram = Marshal.AllocHGlobal(Size); + PageTable[L0] = null; } - - RamPtr = (byte*)Ram; } public void RemoveMonitor(AThreadState State) @@ -155,62 +167,6 @@ namespace ChocolArm64.Memory } } - public int GetHostPageSize() - { - return HostPageSize; - } - - public (bool[], long) IsRegionModified(long Position, long Size) - { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return (null, 0); - } - - long EndPos = Position + Size; - - if ((ulong)EndPos < (ulong)Position) - { - return (null, 0); - } - - if ((ulong)EndPos > AMemoryMgr.RamSize) - { - return (null, 0); - } - - IntPtr MemAddress = new IntPtr(RamPtr + Position); - IntPtr MemSize = new IntPtr(Size); - - int HostPageMask = HostPageSize - 1; - - Position &= ~HostPageMask; - - Size = EndPos - Position; - - IntPtr[] Addresses = new IntPtr[(Size + HostPageMask) / HostPageSize]; - - AMemoryWin32.IsRegionModified(MemAddress, MemSize, Addresses, out int Count); - - bool[] Modified = new bool[Addresses.Length]; - - for (int Index = 0; Index < Count; Index++) - { - long VA = Addresses[Index].ToInt64() - Ram.ToInt64(); - - Modified[(VA - Position) / HostPageSize] = true; - } - - return (Modified, Count); - } - - public IntPtr GetHostAddress(long Position, long Size) - { - EnsureRangeIsValid(Position, Size, AMemoryPerm.Read); - - return (IntPtr)(RamPtr + (ulong)Position); - } - public sbyte ReadSByte(long Position) { return (sbyte)ReadByte(Position); @@ -233,33 +189,22 @@ namespace ChocolArm64.Memory public byte ReadByte(long Position) { - EnsureAccessIsValid(Position, AMemoryPerm.Read); - - return ReadByteUnchecked(Position); + return *((byte*)Translate(Position)); } public ushort ReadUInt16(long Position) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); - EnsureAccessIsValid(Position + 1, AMemoryPerm.Read); - - return ReadUInt16Unchecked(Position); + return *((ushort*)Translate(Position)); } public uint ReadUInt32(long Position) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); - EnsureAccessIsValid(Position + 3, AMemoryPerm.Read); - - return ReadUInt32Unchecked(Position); + return *((uint*)Translate(Position)); } public ulong ReadUInt64(long Position) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); - EnsureAccessIsValid(Position + 7, AMemoryPerm.Read); - - return ReadUInt64Unchecked(Position); + return *((ulong*)Translate(Position)); } public Vector128<float> ReadVector8(long Position) @@ -274,6 +219,7 @@ namespace ChocolArm64.Memory } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector128<float> ReadVector16(long Position) { if (Sse2.IsSupported) @@ -286,122 +232,12 @@ namespace ChocolArm64.Memory } } - public Vector128<float> ReadVector32(long Position) - { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); - EnsureAccessIsValid(Position + 3, AMemoryPerm.Read); - - if (Sse.IsSupported) - { - return Sse.LoadScalarVector128((float*)(RamPtr + (uint)Position)); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - public Vector128<float> ReadVector64(long Position) - { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); - EnsureAccessIsValid(Position + 7, AMemoryPerm.Read); - - if (Sse2.IsSupported) - { - return Sse.StaticCast<double, float>(Sse2.LoadScalarVector128((double*)(RamPtr + (uint)Position))); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - public Vector128<float> ReadVector128(long Position) - { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); - EnsureAccessIsValid(Position + 15, AMemoryPerm.Read); - - if (Sse.IsSupported) - { - return Sse.LoadVector128((float*)(RamPtr + (uint)Position)); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - public sbyte ReadSByteUnchecked(long Position) - { - return (sbyte)ReadByteUnchecked(Position); - } - - public short ReadInt16Unchecked(long Position) - { - return (short)ReadUInt16Unchecked(Position); - } - - public int ReadInt32Unchecked(long Position) - { - return (int)ReadUInt32Unchecked(Position); - } - - public long ReadInt64Unchecked(long Position) - { - return (long)ReadUInt64Unchecked(Position); - } - - public byte ReadByteUnchecked(long Position) - { - return *((byte*)(RamPtr + (uint)Position)); - } - - public ushort ReadUInt16Unchecked(long Position) - { - return *((ushort*)(RamPtr + (uint)Position)); - } - - public uint ReadUInt32Unchecked(long Position) - { - return *((uint*)(RamPtr + (uint)Position)); - } - - public ulong ReadUInt64Unchecked(long Position) - { - return *((ulong*)(RamPtr + (uint)Position)); - } - - public Vector128<float> ReadVector8Unchecked(long Position) - { - if (Sse2.IsSupported) - { - return Sse.StaticCast<byte, float>(Sse2.SetVector128(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ReadByte(Position))); - } - else - { - throw new PlatformNotSupportedException(); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128<float> ReadVector16Unchecked(long Position) - { - if (Sse2.IsSupported) - { - return Sse.StaticCast<ushort, float>(Sse2.Insert(Sse2.SetZeroVector128<ushort>(), ReadUInt16Unchecked(Position), 0)); - } - else - { - throw new PlatformNotSupportedException(); - } - } - [MethodImpl(MethodImplOptions.NoInlining)] - public Vector128<float> ReadVector32Unchecked(long Position) + public Vector128<float> ReadVector32(long Position) { if (Sse.IsSupported) { - return Sse.LoadScalarVector128((float*)(RamPtr + (uint)Position)); + return Sse.LoadScalarVector128((float*)Translate(Position)); } else { @@ -410,11 +246,11 @@ namespace ChocolArm64.Memory } [MethodImpl(MethodImplOptions.NoInlining)] - public Vector128<float> ReadVector64Unchecked(long Position) + public Vector128<float> ReadVector64(long Position) { if (Sse2.IsSupported) { - return Sse.StaticCast<double, float>(Sse2.LoadScalarVector128((double*)(RamPtr + (uint)Position))); + return Sse.StaticCast<double, float>(Sse2.LoadScalarVector128((double*)Translate(Position))); } else { @@ -423,11 +259,11 @@ namespace ChocolArm64.Memory } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector128<float> ReadVector128Unchecked(long Position) + public Vector128<float> ReadVector128(long Position) { if (Sse.IsSupported) { - return Sse.LoadVector128((float*)(RamPtr + (uint)Position)); + return Sse.LoadVector128((float*)Translate(Position)); } else { @@ -442,11 +278,11 @@ namespace ChocolArm64.Memory throw new ArgumentOutOfRangeException(nameof(Size)); } - EnsureRangeIsValid(Position, Size, AMemoryPerm.Read); + EnsureRangeIsValid(Position, Size); byte[] Data = new byte[Size]; - Marshal.Copy((IntPtr)(RamPtr + (uint)Position), Data, 0, (int)Size); + Marshal.Copy((IntPtr)Translate(Position), Data, 0, (int)Size); return Data; } @@ -473,35 +309,25 @@ namespace ChocolArm64.Memory public void WriteByte(long Position, byte Value) { - EnsureAccessIsValid(Position, AMemoryPerm.Write); - - WriteByteUnchecked(Position, Value); + *((byte*)TranslateWrite(Position)) = Value; } public void WriteUInt16(long Position, ushort Value) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); - EnsureAccessIsValid(Position + 1, AMemoryPerm.Write); - - WriteUInt16Unchecked(Position, Value); + *((ushort*)TranslateWrite(Position)) = Value; } public void WriteUInt32(long Position, uint Value) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); - EnsureAccessIsValid(Position + 3, AMemoryPerm.Write); - - WriteUInt32Unchecked(Position, Value); + *((uint*)TranslateWrite(Position)) = Value; } public void WriteUInt64(long Position, ulong Value) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); - EnsureAccessIsValid(Position + 7, AMemoryPerm.Write); - - WriteUInt64Unchecked(Position, Value); + *((ulong*)TranslateWrite(Position)) = Value; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector8(long Position, Vector128<float> Value) { if (Sse41.IsSupported) @@ -518,6 +344,7 @@ namespace ChocolArm64.Memory } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector16(long Position, Vector128<float> Value) { if (Sse2.IsSupported) @@ -530,14 +357,12 @@ namespace ChocolArm64.Memory } } + [MethodImpl(MethodImplOptions.NoInlining)] public void WriteVector32(long Position, Vector128<float> Value) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); - EnsureAccessIsValid(Position + 3, AMemoryPerm.Write); - if (Sse.IsSupported) { - Sse.StoreScalar((float*)(RamPtr + (uint)Position), Value); + Sse.StoreScalar((float*)TranslateWrite(Position), Value); } else { @@ -545,14 +370,12 @@ namespace ChocolArm64.Memory } } + [MethodImpl(MethodImplOptions.NoInlining)] public void WriteVector64(long Position, Vector128<float> Value) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); - EnsureAccessIsValid(Position + 7, AMemoryPerm.Write); - if (Sse2.IsSupported) { - Sse2.StoreScalar((double*)(RamPtr + (uint)Position), Sse.StaticCast<float, double>(Value)); + Sse2.StoreScalar((double*)TranslateWrite(Position), Sse.StaticCast<float, double>(Value)); } else { @@ -560,14 +383,12 @@ namespace ChocolArm64.Memory } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector128(long Position, Vector128<float> Value) { - EnsureAccessIsValid(Position + 0, AMemoryPerm.Write); - EnsureAccessIsValid(Position + 15, AMemoryPerm.Write); - if (Sse.IsSupported) { - Sse.Store((float*)(RamPtr + (uint)Position), Value); + Sse.Store((float*)TranslateWrite(Position), Value); } else { @@ -575,147 +396,287 @@ namespace ChocolArm64.Memory } } - public void WriteSByteUnchecked(long Position, sbyte Value) + public void WriteBytes(long Position, byte[] Data) { - WriteByteUnchecked(Position, (byte)Value); - } + EnsureRangeIsValid(Position, (uint)Data.Length); - public void WriteInt16Unchecked(long Position, short Value) - { - WriteUInt16Unchecked(Position, (ushort)Value); + Marshal.Copy(Data, 0, (IntPtr)TranslateWrite(Position), Data.Length); } - public void WriteInt32Unchecked(long Position, int Value) + public void Map(long VA, long PA, long Size) { - WriteUInt32Unchecked(Position, (uint)Value); + SetPTEntries(VA, RamPtr + PA, Size); } - public void WriteInt64Unchecked(long Position, long Value) + public void Unmap(long Position, long Size) { - WriteUInt64Unchecked(Position, (ulong)Value); - } + SetPTEntries(Position, null, Size); - public void WriteByteUnchecked(long Position, byte Value) - { - *((byte*)(RamPtr + (uint)Position)) = Value; + StopObservingRegion(Position, Size); } - public void WriteUInt16Unchecked(long Position, ushort Value) + public bool IsMapped(long Position) { - *((ushort*)(RamPtr + (uint)Position)) = Value; - } + if (!(IsValidPosition(Position))) + { + return false; + } - public void WriteUInt32Unchecked(long Position, uint Value) - { - *((uint*)(RamPtr + (uint)Position)) = Value; + long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; + long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask; + + if (PageTable[L0] == null) + { + return false; + } + + return PageTable[L0][L1] != null || ObservedPages.ContainsKey(Position >> PTPageBits); } - public void WriteUInt64Unchecked(long Position, ulong Value) + public long GetPhysicalAddress(long VirtualAddress) { - *((ulong*)(RamPtr + (uint)Position)) = Value; + byte* Ptr = Translate(VirtualAddress); + + return (long)(Ptr - RamPtr); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector8Unchecked(long Position, Vector128<float> Value) + internal byte* Translate(long Position) { - if (Sse41.IsSupported) + long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; + long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask; + + long Old = Position; + + byte** Lvl1 = PageTable[L0]; + + if ((Position >> (PTLvl0Bit + PTLvl0Bits)) != 0) { - WriteByteUnchecked(Position, Sse41.Extract(Sse.StaticCast<float, byte>(Value), 0)); + goto Unmapped; } - else if (Sse2.IsSupported) + + if (Lvl1 == null) { - WriteByteUnchecked(Position, (byte)Sse2.Extract(Sse.StaticCast<float, ushort>(Value), 0)); + goto Unmapped; } - else + + Position &= PageMask; + + byte* Ptr = Lvl1[L1]; + + if (Ptr == null) { - throw new PlatformNotSupportedException(); + goto Unmapped; } + + return Ptr + Position; + +Unmapped: + return HandleNullPte(Old); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector16Unchecked(long Position, Vector128<float> Value) + private byte* HandleNullPte(long Position) { - if (Sse2.IsSupported) + long Key = Position >> PTPageBits; + + if (ObservedPages.TryGetValue(Key, out IntPtr Ptr)) { - WriteUInt16Unchecked(Position, Sse2.Extract(Sse.StaticCast<float, ushort>(Value), 0)); + return (byte*)Ptr + (Position & PageMask); } - else + + throw new VmmPageFaultException(Position); + } + + internal byte* TranslateWrite(long Position) + { + long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; + long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask; + + long Old = Position; + + byte** Lvl1 = PageTable[L0]; + + if ((Position >> (PTLvl0Bit + PTLvl0Bits)) != 0) { - throw new PlatformNotSupportedException(); + goto Unmapped; + } + + if (Lvl1 == null) + { + goto Unmapped; + } + + Position &= PageMask; + + byte* Ptr = Lvl1[L1]; + + if (Ptr == null) + { + goto Unmapped; } + + return Ptr + Position; + +Unmapped: + return HandleNullPteWrite(Old); } - [MethodImpl(MethodImplOptions.NoInlining)] - public void WriteVector32Unchecked(long Position, Vector128<float> Value) + private byte* HandleNullPteWrite(long Position) { - if (Sse.IsSupported) + long Key = Position >> PTPageBits; + + if (ObservedPages.TryGetValue(Key, out IntPtr Ptr)) { - Sse.StoreScalar((float*)(RamPtr + (uint)Position), Value); + SetPTEntry(Position, (byte*)Ptr); + + return (byte*)Ptr + (Position & PageMask); } - else + + throw new VmmPageFaultException(Position); + } + + private void SetPTEntries(long VA, byte* Ptr, long Size) + { + long EndPosition = (VA + Size + PageMask) & ~PageMask; + + while ((ulong)VA < (ulong)EndPosition) { - throw new PlatformNotSupportedException(); + SetPTEntry(VA, Ptr); + + VA += PageSize; + + if (Ptr != null) + { + Ptr += PageSize; + } } } - [MethodImpl(MethodImplOptions.NoInlining)] - public void WriteVector64Unchecked(long Position, Vector128<float> Value) + private void SetPTEntry(long Position, byte* Ptr) { - if (Sse2.IsSupported) + if (!IsValidPosition(Position)) { - Sse2.StoreScalar((double*)(RamPtr + (uint)Position), Sse.StaticCast<float, double>(Value)); + throw new ArgumentOutOfRangeException(nameof(Position)); } - else + + long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; + long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask; + + if (PageTable[L0] == null) { - throw new PlatformNotSupportedException(); + byte** Lvl1 = (byte**)Marshal.AllocHGlobal(PTLvl1Size * IntPtr.Size); + + for (int ZL1 = 0; ZL1 < PTLvl1Size; ZL1++) + { + Lvl1[ZL1] = null; + } + + Thread.MemoryBarrier(); + + PageTable[L0] = Lvl1; } + + PageTable[L0][L1] = Ptr; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void WriteVector128Unchecked(long Position, Vector128<float> Value) + public (bool[], int) IsRegionModified(long Position, long Size) { - if (Sse.IsSupported) + long EndPosition = (Position + Size + PageMask) & ~PageMask; + + Position &= ~PageMask; + + Size = EndPosition - Position; + + bool[] Modified = new bool[Size >> PTPageBits]; + + int Count = 0; + + lock (ObservedPages) { - Sse.Store((float*)(RamPtr + (uint)Position), Value); + for (int Page = 0; Page < Modified.Length; Page++) + { + byte* Ptr = Translate(Position); + + if (ObservedPages.TryAdd(Position >> PTPageBits, (IntPtr)Ptr)) + { + Modified[Page] = true; + + Count++; + } + else + { + long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask; + long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask; + + byte** Lvl1 = PageTable[L0]; + + if (Lvl1 != null) + { + if (Modified[Page] = Lvl1[L1] != null) + { + Count++; + } + } + } + + SetPTEntry(Position, null); + + Position += PageSize; + } } - else + + return (Modified, Count); + } + + public void StopObservingRegion(long Position, long Size) + { + long EndPosition = (Position + Size + PageMask) & ~PageMask; + + while (Position < EndPosition) { - throw new PlatformNotSupportedException(); + lock (ObservedPages) + { + if (ObservedPages.TryRemove(Position >> PTPageBits, out IntPtr Ptr)) + { + SetPTEntry(Position, (byte*)Ptr); + } + } + + Position += PageSize; } } - public void WriteBytes(long Position, byte[] Data) + public IntPtr GetHostAddress(long Position, long Size) { - EnsureRangeIsValid(Position, (uint)Data.Length, AMemoryPerm.Write); + EnsureRangeIsValid(Position, Size); - Marshal.Copy(Data, 0, (IntPtr)(RamPtr + (uint)Position), Data.Length); + return (IntPtr)Translate(Position); } - private void EnsureRangeIsValid(long Position, long Size, AMemoryPerm Perm) + internal void EnsureRangeIsValid(long Position, long Size) { long EndPos = Position + Size; - Position &= ~AMemoryMgr.PageMask; + Position &= ~PageMask; + + long ExpectedPA = GetPhysicalAddress(Position); while ((ulong)Position < (ulong)EndPos) { - EnsureAccessIsValid(Position, Perm); + long PA = GetPhysicalAddress(Position); + + if (PA != ExpectedPA) + { + throw new VmmAccessException(Position, Size); + } - Position += AMemoryMgr.PageSize; + Position += PageSize; + ExpectedPA += PageSize; } } - private void EnsureAccessIsValid(long Position, AMemoryPerm Perm) + public bool IsValidPosition(long Position) { - if (!Manager.IsMapped(Position)) - { - throw new VmmPageFaultException(Position); - } - - if (!Manager.HasPermission(Position, Perm)) - { - throw new VmmAccessViolationException(Position, Perm); - } + return Position >> (PTLvl0Bits + PTLvl1Bits + PTPageBits) == 0; } public void Dispose() @@ -725,19 +686,24 @@ namespace ChocolArm64.Memory protected virtual void Dispose(bool disposing) { - if (Ram != IntPtr.Zero) + if (PageTable == null) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - AMemoryWin32.Free(Ram); - } - else + return; + } + + for (int L0 = 0; L0 < PTLvl0Size; L0++) + { + if (PageTable[L0] != null) { - Marshal.FreeHGlobal(Ram); + Marshal.FreeHGlobal((IntPtr)PageTable[L0]); } - Ram = IntPtr.Zero; + PageTable[L0] = null; } + + Marshal.FreeHGlobal((IntPtr)PageTable); + + PageTable = null; } } }
\ No newline at end of file |
