diff options
author | Roderick Sieben <RyadaProductions@users.noreply.github.com> | 2018-12-12 02:48:54 +0100 |
---|---|---|
committer | gdkchan <gab.dark.100@gmail.com> | 2018-12-11 23:48:54 -0200 |
commit | 2e143365eb9023b97ea51f6c47a12091ee3dc74c (patch) | |
tree | c83d2c6ee15d4f374bd548e331002b2ca06a5453 /ChocolArm64/Memory/MemoryManager.cs | |
parent | 36e8e074c90f11480389560e3f019a161f82efbe (diff) |
Optimized memory modified check (#538)
* Optimized memory modified check
This was initially in some cases more expensive than plainly sending the data. Now it should have way better performance.
* Small refactoring
* renamed InvalidAccessEventArgs
* Renamed PtPageBits
* Removed ValueRange(set)
They are currently unused and won't be likely to be used in the near future
Diffstat (limited to 'ChocolArm64/Memory/MemoryManager.cs')
-rw-r--r-- | ChocolArm64/Memory/MemoryManager.cs | 73 |
1 files changed, 23 insertions, 50 deletions
diff --git a/ChocolArm64/Memory/MemoryManager.cs b/ChocolArm64/Memory/MemoryManager.cs index eacb5336..1f212568 100644 --- a/ChocolArm64/Memory/MemoryManager.cs +++ b/ChocolArm64/Memory/MemoryManager.cs @@ -17,18 +17,18 @@ namespace ChocolArm64.Memory { private const int PtLvl0Bits = 13; private const int PtLvl1Bits = 14; - private const int PtPageBits = 12; + public const int PageBits = 12; private const int PtLvl0Size = 1 << PtLvl0Bits; 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 PtLvl1Mask = PtLvl1Size - 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; @@ -53,7 +53,9 @@ namespace ChocolArm64.Memory private byte*** _pageTable; - public event EventHandler<InvalidAccessEventArgs> InvalidAccess; + public event EventHandler<MemoryAccessEventArgs> InvalidAccess; + + public event EventHandler<MemoryAccessEventArgs> ObservedAccess; public MemoryManager(IntPtr ram) { @@ -632,7 +634,7 @@ namespace ChocolArm64.Memory 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) @@ -678,14 +680,14 @@ Unmapped: private byte* HandleNullPte(long position) { - long key = position >> PtPageBits; + long key = position >> PageBits; if (_observedPages.TryGetValue(key, out IntPtr ptr)) { return (byte*)ptr + (position & PageMask); } - InvalidAccess?.Invoke(this, new InvalidAccessEventArgs(position)); + InvalidAccess?.Invoke(this, new MemoryAccessEventArgs(position)); throw new VmmPageFaultException(position); } @@ -726,16 +728,20 @@ Unmapped: 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)) { SetPtEntry(position, (byte*)ptr); + ObservedAccess?.Invoke(this, e); + return (byte*)ptr + (position & PageMask); } - InvalidAccess?.Invoke(this, new InvalidAccessEventArgs(position)); + InvalidAccess?.Invoke(this, e); throw new VmmPageFaultException(position); } @@ -784,53 +790,20 @@ Unmapped: _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; 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) @@ -841,7 +814,7 @@ Unmapped: { lock (_observedPages) { - if (_observedPages.TryRemove(position >> PtPageBits, out IntPtr ptr)) + if (_observedPages.TryRemove(position >> PageBits, out IntPtr ptr)) { SetPtEntry(position, (byte*)ptr); } @@ -891,7 +864,7 @@ Unmapped: public bool IsValidPosition(long position) { - return position >> (PtLvl0Bits + PtLvl1Bits + PtPageBits) == 0; + return position >> (PtLvl0Bits + PtLvl1Bits + PageBits) == 0; } public void Dispose() |