aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Memory
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-10-13 03:02:07 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commit1876b346fea647e8284a66bb6d62c38801035cff (patch)
tree6eeff094298cda84d1613dc5ec0691e51d7b35f1 /ARMeilleure/Memory
parentf617fb542a0e3d36012d77a4b5acbde7b08902f2 (diff)
Initial work
Diffstat (limited to 'ARMeilleure/Memory')
-rw-r--r--ARMeilleure/Memory/IMemory.cs37
-rw-r--r--ARMeilleure/Memory/MemoryManagement.cs24
-rw-r--r--ARMeilleure/Memory/MemoryManagementWindows.cs37
-rw-r--r--ARMeilleure/Memory/MemoryManager.cs201
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);