diff options
| author | gdk <gab.dark.100@gmail.com> | 2019-10-13 03:02:07 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | 1876b346fea647e8284a66bb6d62c38801035cff (patch) | |
| tree | 6eeff094298cda84d1613dc5ec0691e51d7b35f1 /ARMeilleure/Memory | |
| parent | f617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff) | |
Initial work
Diffstat (limited to 'ARMeilleure/Memory')
| -rw-r--r-- | ARMeilleure/Memory/IMemory.cs | 37 | ||||
| -rw-r--r-- | ARMeilleure/Memory/MemoryManagement.cs | 24 | ||||
| -rw-r--r-- | ARMeilleure/Memory/MemoryManagementWindows.cs | 37 | ||||
| -rw-r--r-- | ARMeilleure/Memory/MemoryManager.cs | 201 |
4 files changed, 28 insertions, 271 deletions
diff --git a/ARMeilleure/Memory/IMemory.cs b/ARMeilleure/Memory/IMemory.cs deleted file mode 100644 index 0c3849c0..00000000 --- a/ARMeilleure/Memory/IMemory.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace ARMeilleure.Memory -{ - public interface IMemory - { - sbyte ReadSByte(long position); - - short ReadInt16(long position); - - int ReadInt32(long position); - - long ReadInt64(long position); - - byte ReadByte(long position); - - ushort ReadUInt16(long position); - - uint ReadUInt32(long position); - - ulong ReadUInt64(long position); - - void WriteSByte(long position, sbyte value); - - void WriteInt16(long position, short value); - - void WriteInt32(long position, int value); - - void WriteInt64(long position, long value); - - void WriteByte(long position, byte value); - - void WriteUInt16(long position, ushort value); - - void WriteUInt32(long position, uint value); - - void WriteUInt64(long position, ulong value); - } -}
\ No newline at end of file diff --git a/ARMeilleure/Memory/MemoryManagement.cs b/ARMeilleure/Memory/MemoryManagement.cs index bf0bd02c..e299ae49 100644 --- a/ARMeilleure/Memory/MemoryManagement.cs +++ b/ARMeilleure/Memory/MemoryManagement.cs @@ -6,8 +6,6 @@ namespace ARMeilleure.Memory { public static class MemoryManagement { - public static bool HasWriteWatchSupport => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - public static IntPtr Allocate(ulong size) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -88,27 +86,5 @@ namespace ARMeilleure.Memory throw new PlatformNotSupportedException(); } } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool GetModifiedPages( - IntPtr address, - IntPtr size, - IntPtr[] addresses, - out ulong count) - { - // This is only supported on windows, but returning - // false (failed) is also valid for platforms without - // write tracking support on the OS. - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return MemoryManagementWindows.GetModifiedPages(address, size, addresses, out count); - } - else - { - count = 0; - - return false; - } - } } }
\ No newline at end of file diff --git a/ARMeilleure/Memory/MemoryManagementWindows.cs b/ARMeilleure/Memory/MemoryManagementWindows.cs index c1a84c95..ae64b5c6 100644 --- a/ARMeilleure/Memory/MemoryManagementWindows.cs +++ b/ARMeilleure/Memory/MemoryManagementWindows.cs @@ -36,12 +36,6 @@ namespace ARMeilleure.Memory WriteCombineModifierflag = 0x400 } - private enum WriteWatchFlags : uint - { - None = 0, - Reset = 1 - } - [DllImport("kernel32.dll")] private static extern IntPtr VirtualAlloc( IntPtr lpAddress, @@ -62,15 +56,6 @@ namespace ARMeilleure.Memory IntPtr dwSize, AllocationType dwFreeType); - [DllImport("kernel32.dll")] - private static extern int GetWriteWatch( - WriteWatchFlags dwFlags, - IntPtr lpBaseAddress, - IntPtr dwRegionSize, - IntPtr[] lpAddresses, - ref ulong lpdwCount, - out uint lpdwGranularity); - public static IntPtr Allocate(IntPtr size) { const AllocationType flags = @@ -130,27 +115,5 @@ namespace ARMeilleure.Memory { return VirtualFree(address, IntPtr.Zero, AllocationType.Release); } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool GetModifiedPages( - IntPtr address, - IntPtr size, - IntPtr[] addresses, - out ulong count) - { - ulong pagesCount = (ulong)addresses.Length; - - int result = GetWriteWatch( - WriteWatchFlags.Reset, - address, - size, - addresses, - ref pagesCount, - out uint granularity); - - count = pagesCount; - - return result == 0; - } } }
\ No newline at end of file diff --git a/ARMeilleure/Memory/MemoryManager.cs b/ARMeilleure/Memory/MemoryManager.cs index c6224988..2bdbc309 100644 --- a/ARMeilleure/Memory/MemoryManager.cs +++ b/ARMeilleure/Memory/MemoryManager.cs @@ -1,5 +1,6 @@ using ARMeilleure.State; using System; +using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; @@ -29,8 +30,6 @@ namespace ARMeilleure.Memory internal int PtLevelSize { get; } internal int PtLevelMask { get; } - public bool HasWriteWatchSupport => MemoryManagement.HasWriteWatchSupport; - public int AddressSpaceBits { get; } public long AddressSpaceSize { get; } @@ -254,119 +253,57 @@ namespace ARMeilleure.Memory return ptePtr; } - public bool IsRegionModified(long position, long size) + public unsafe (ulong, ulong)[] GetModifiedRanges(ulong address, ulong size) { - if (!HasWriteWatchSupport) - { - return IsRegionModifiedFallback(position, size); - } - - IntPtr address = Translate(position); - - IntPtr baseAddr = address; - IntPtr expectedAddr = address; - - long pendingPages = 0; - - long pages = size / PageSize; - - bool modified = false; - - bool IsAnyPageModified() - { - IntPtr pendingSize = new IntPtr(pendingPages * PageSize); - - IntPtr[] addresses = new IntPtr[pendingPages]; - - bool result = GetModifiedPages(baseAddr, pendingSize, addresses, out ulong count); - - if (result) - { - return count != 0; - } - else - { - return true; - } - } - - while (pages-- > 0) - { - if (address != expectedAddr) - { - modified |= IsAnyPageModified(); - - baseAddr = address; - - pendingPages = 0; - } - - expectedAddr = address + PageSize; - - pendingPages++; - - if (pages == 0) - { - break; - } + List<(ulong, ulong)> ranges = new List<(ulong, ulong)>(); - position += PageSize; - - address = Translate(position); - } + ulong endAddress = (address + size + PageMask) & ~(ulong)PageMask; - if (pendingPages != 0) - { - modified |= IsAnyPageModified(); - } + address &= ~(ulong)PageMask; - return modified; - } + ulong currAddr = address; + ulong currSize = 0; - private unsafe bool IsRegionModifiedFallback(long position, long size) - { - long endAddr = (position + size + PageMask) & ~PageMask; - - bool modified = false; - - while ((ulong)position < (ulong)endAddr) + while (address < endAddress) { - if (IsValidPosition(position)) + if (IsValidPosition((long)address)) { - byte* ptr = ((byte**)_pageTable)[position >> PageBits]; + byte* ptr = ((byte**)_pageTable)[address >> PageBits]; ulong ptrUlong = (ulong)ptr; if ((ptrUlong & PteFlagNotModified) == 0) { - modified = true; + // Modified. + currSize += PageSize; + + SetPtEntryFlag((long)address, PteFlagNotModified); + } + else + { + if (currSize != 0) + { + ranges.Add((currAddr, currSize)); + } - SetPtEntryFlag(position, PteFlagNotModified); + currAddr = address + PageSize; + currSize = 0; } } else { - modified = true; + currSize += PageSize; } - position += PageSize; + address += PageSize; } - return modified; - } - - public bool TryGetHostAddress(long position, long size, out IntPtr ptr) - { - if (IsContiguous(position, size)) + if (currSize != 0) { - ptr = (IntPtr)Translate(position); - - return true; + ranges.Add((currAddr, currSize)); } - ptr = IntPtr.Zero; - - return false; + return ranges.ToArray(); } private bool IsContiguous(long position, long size) @@ -612,41 +549,6 @@ namespace ARMeilleure.Memory return data; } - public void ReadBytes(long position, byte[] data, int startIndex, int size) - { - // Note: This will be moved later. - long endAddr = position + size; - - if ((ulong)size > int.MaxValue) - { - throw new ArgumentOutOfRangeException(nameof(size)); - } - - if ((ulong)endAddr < (ulong)position) - { - throw new ArgumentOutOfRangeException(nameof(position)); - } - - int offset = startIndex; - - while ((ulong)position < (ulong)endAddr) - { - long pageLimit = (position + PageSize) & ~(long)PageMask; - - if ((ulong)pageLimit > (ulong)endAddr) - { - pageLimit = endAddr; - } - - int copySize = (int)(pageLimit - position); - - Marshal.Copy(Translate(position), data, offset, copySize); - - position += copySize; - offset += copySize; - } - } - public void WriteSByte(long position, sbyte value) { WriteByte(position, (byte)value); @@ -746,53 +648,6 @@ namespace ARMeilleure.Memory } } - public void WriteBytes(long position, byte[] data, int startIndex, int size) - { - // Note: This will be moved later. - long endAddr = position + size; - - if ((ulong)endAddr < (ulong)position) - { - throw new ArgumentOutOfRangeException(nameof(position)); - } - - int offset = startIndex; - - while ((ulong)position < (ulong)endAddr) - { - long pageLimit = (position + PageSize) & ~(long)PageMask; - - if ((ulong)pageLimit > (ulong)endAddr) - { - pageLimit = endAddr; - } - - int copySize = (int)(pageLimit - position); - - Marshal.Copy(data, offset, Translate(position), copySize); - - position += copySize; - offset += copySize; - } - } - - public void CopyBytes(long src, long dst, long size) - { - // Note: This will be moved later. - if (IsContiguous(src, size) && - IsContiguous(dst, size)) - { - byte* srcPtr = (byte*)Translate(src); - byte* dstPtr = (byte*)Translate(dst); - - Buffer.MemoryCopy(srcPtr, dstPtr, size, size); - } - else - { - WriteBytes(dst, ReadBytes(src, size)); - } - } - public void Dispose() { Dispose(true); |
