|
@@ -17,18 +17,18 @@ namespace ChocolArm64.Memory
|
|
|
{
|
|
{
|
|
|
private const int PtLvl0Bits = 13;
|
|
private const int PtLvl0Bits = 13;
|
|
|
private const int PtLvl1Bits = 14;
|
|
private const int PtLvl1Bits = 14;
|
|
|
- private const int PtPageBits = 12;
|
|
|
|
|
|
|
+ public const int PageBits = 12;
|
|
|
|
|
|
|
|
private const int PtLvl0Size = 1 << PtLvl0Bits;
|
|
private const int PtLvl0Size = 1 << PtLvl0Bits;
|
|
|
private const int PtLvl1Size = 1 << PtLvl1Bits;
|
|
private const int PtLvl1Size = 1 << PtLvl1Bits;
|
|
|
- public const int PageSize = 1 << PtPageBits;
|
|
|
|
|
|
|
+ public const int PageSize = 1 << PageBits;
|
|
|
|
|
|
|
|
private const int PtLvl0Mask = PtLvl0Size - 1;
|
|
private const int PtLvl0Mask = PtLvl0Size - 1;
|
|
|
private const int PtLvl1Mask = PtLvl1Size - 1;
|
|
private const int PtLvl1Mask = PtLvl1Size - 1;
|
|
|
public const int PageMask = PageSize - 1;
|
|
public const int PageMask = PageSize - 1;
|
|
|
|
|
|
|
|
- private const int PtLvl0Bit = PtPageBits + PtLvl1Bits;
|
|
|
|
|
- private const int PtLvl1Bit = PtPageBits;
|
|
|
|
|
|
|
+ private const int PtLvl0Bit = PageBits + PtLvl1Bits;
|
|
|
|
|
+ private const int PtLvl1Bit = PageBits;
|
|
|
|
|
|
|
|
private const long ErgMask = (4 << CpuThreadState.ErgSizeLog2) - 1;
|
|
private const long ErgMask = (4 << CpuThreadState.ErgSizeLog2) - 1;
|
|
|
|
|
|
|
@@ -53,7 +53,9 @@ namespace ChocolArm64.Memory
|
|
|
|
|
|
|
|
private byte*** _pageTable;
|
|
private byte*** _pageTable;
|
|
|
|
|
|
|
|
- public event EventHandler<InvalidAccessEventArgs> InvalidAccess;
|
|
|
|
|
|
|
+ public event EventHandler<MemoryAccessEventArgs> InvalidAccess;
|
|
|
|
|
+
|
|
|
|
|
+ public event EventHandler<MemoryAccessEventArgs> ObservedAccess;
|
|
|
|
|
|
|
|
public MemoryManager(IntPtr ram)
|
|
public MemoryManager(IntPtr ram)
|
|
|
{
|
|
{
|
|
@@ -632,7 +634,7 @@ namespace ChocolArm64.Memory
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return _pageTable[l0][l1] != null || _observedPages.ContainsKey(position >> PtPageBits);
|
|
|
|
|
|
|
+ return _pageTable[l0][l1] != null || _observedPages.ContainsKey(position >> PageBits);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public long GetPhysicalAddress(long virtualAddress)
|
|
public long GetPhysicalAddress(long virtualAddress)
|
|
@@ -678,14 +680,14 @@ Unmapped:
|
|
|
|
|
|
|
|
private byte* HandleNullPte(long position)
|
|
private byte* HandleNullPte(long position)
|
|
|
{
|
|
{
|
|
|
- long key = position >> PtPageBits;
|
|
|
|
|
|
|
+ long key = position >> PageBits;
|
|
|
|
|
|
|
|
if (_observedPages.TryGetValue(key, out IntPtr ptr))
|
|
if (_observedPages.TryGetValue(key, out IntPtr ptr))
|
|
|
{
|
|
{
|
|
|
return (byte*)ptr + (position & PageMask);
|
|
return (byte*)ptr + (position & PageMask);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- InvalidAccess?.Invoke(this, new InvalidAccessEventArgs(position));
|
|
|
|
|
|
|
+ InvalidAccess?.Invoke(this, new MemoryAccessEventArgs(position));
|
|
|
|
|
|
|
|
throw new VmmPageFaultException(position);
|
|
throw new VmmPageFaultException(position);
|
|
|
}
|
|
}
|
|
@@ -726,16 +728,20 @@ Unmapped:
|
|
|
|
|
|
|
|
private byte* HandleNullPteWrite(long position)
|
|
private byte* HandleNullPteWrite(long position)
|
|
|
{
|
|
{
|
|
|
- long key = position >> PtPageBits;
|
|
|
|
|
|
|
+ long key = position >> PageBits;
|
|
|
|
|
+
|
|
|
|
|
+ MemoryAccessEventArgs e = new MemoryAccessEventArgs(position);
|
|
|
|
|
|
|
|
if (_observedPages.TryGetValue(key, out IntPtr ptr))
|
|
if (_observedPages.TryGetValue(key, out IntPtr ptr))
|
|
|
{
|
|
{
|
|
|
SetPtEntry(position, (byte*)ptr);
|
|
SetPtEntry(position, (byte*)ptr);
|
|
|
|
|
|
|
|
|
|
+ ObservedAccess?.Invoke(this, e);
|
|
|
|
|
+
|
|
|
return (byte*)ptr + (position & PageMask);
|
|
return (byte*)ptr + (position & PageMask);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- InvalidAccess?.Invoke(this, new InvalidAccessEventArgs(position));
|
|
|
|
|
|
|
+ InvalidAccess?.Invoke(this, e);
|
|
|
|
|
|
|
|
throw new VmmPageFaultException(position);
|
|
throw new VmmPageFaultException(position);
|
|
|
}
|
|
}
|
|
@@ -784,53 +790,20 @@ Unmapped:
|
|
|
_pageTable[l0][l1] = ptr;
|
|
_pageTable[l0][l1] = ptr;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public (bool[], int) IsRegionModified(long position, long size)
|
|
|
|
|
|
|
+ public void StartObservingRegion(long position, long size)
|
|
|
{
|
|
{
|
|
|
long endPosition = (position + size + PageMask) & ~PageMask;
|
|
long endPosition = (position + size + PageMask) & ~PageMask;
|
|
|
|
|
|
|
|
position &= ~PageMask;
|
|
position &= ~PageMask;
|
|
|
|
|
|
|
|
- size = endPosition - position;
|
|
|
|
|
-
|
|
|
|
|
- bool[] modified = new bool[size >> PtPageBits];
|
|
|
|
|
-
|
|
|
|
|
- int count = 0;
|
|
|
|
|
-
|
|
|
|
|
- lock (_observedPages)
|
|
|
|
|
|
|
+ while ((ulong)position < (ulong)endPosition)
|
|
|
{
|
|
{
|
|
|
- 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++;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ _observedPages[position >> PageBits] = (IntPtr)Translate(position);
|
|
|
|
|
|
|
|
- SetPtEntry(position, null);
|
|
|
|
|
|
|
+ SetPtEntry(position, null);
|
|
|
|
|
|
|
|
- position += PageSize;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ position += PageSize;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return (modified, count);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void StopObservingRegion(long position, long size)
|
|
public void StopObservingRegion(long position, long size)
|
|
@@ -841,7 +814,7 @@ Unmapped:
|
|
|
{
|
|
{
|
|
|
lock (_observedPages)
|
|
lock (_observedPages)
|
|
|
{
|
|
{
|
|
|
- if (_observedPages.TryRemove(position >> PtPageBits, out IntPtr ptr))
|
|
|
|
|
|
|
+ if (_observedPages.TryRemove(position >> PageBits, out IntPtr ptr))
|
|
|
{
|
|
{
|
|
|
SetPtEntry(position, (byte*)ptr);
|
|
SetPtEntry(position, (byte*)ptr);
|
|
|
}
|
|
}
|
|
@@ -891,7 +864,7 @@ Unmapped:
|
|
|
|
|
|
|
|
public bool IsValidPosition(long position)
|
|
public bool IsValidPosition(long position)
|
|
|
{
|
|
{
|
|
|
- return position >> (PtLvl0Bits + PtLvl1Bits + PtPageBits) == 0;
|
|
|
|
|
|
|
+ return position >> (PtLvl0Bits + PtLvl1Bits + PageBits) == 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
public void Dispose()
|