diff options
Diffstat (limited to 'ARMeilleure/Memory/MemoryManager.cs')
-rw-r--r-- | ARMeilleure/Memory/MemoryManager.cs | 201 |
1 files changed, 28 insertions, 173 deletions
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); |