aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Cpu/MemoryManager.cs
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2021-05-24 21:52:44 +0100
committerGitHub <noreply@github.com>2021-05-24 22:52:44 +0200
commit54ea2285f05ef6f59a6f1c63df4a7bdd77d7b883 (patch)
tree244f601856dc96f2bf8ce15aecd0b5623ae7b234 /Ryujinx.Cpu/MemoryManager.cs
parentfb65f392d1c4b0e01f22b6ddebcc8317ba9769c3 (diff)
POWER - Performance Optimizations With Extensive Ramifications (#2286)
* Refactoring of KMemoryManager class * Replace some trivial uses of DRAM address with VA * Get rid of GetDramAddressFromVa * Abstracting more operations on derived page table class * Run auto-format on KPageTableBase * Managed to make TryConvertVaToPa private, few uses remains now * Implement guest physical pages ref counting, remove manual freeing * Make DoMmuOperation private and call new abstract methods only from the base class * Pass pages count rather than size on Map/UnmapMemory * Change memory managers to take host pointers * Fix a guest memory leak and simplify KPageTable * Expose new methods for host range query and mapping * Some refactoring of MapPagesFromClientProcess to allow proper page ref counting and mapping without KPageLists * Remove more uses of AddVaRangeToPageList, now only one remains (shared memory page checking) * Add a SharedMemoryStorage class, will be useful for host mapping * Sayonara AddVaRangeToPageList, you served us well * Start to implement host memory mapping (WIP) * Support memory tracking through host exception handling * Fix some access violations from HLE service guest memory access and CPU * Fix memory tracking * Fix mapping list bugs, including a race and a error adding mapping ranges * Simple page table for memory tracking * Simple "volatile" region handle mode * Update UBOs directly (experimental, rough) * Fix the overlap check * Only set non-modified buffers as volatile * Fix some memory tracking issues * Fix possible race in MapBufferFromClientProcess (block list updates were not locked) * Write uniform update to memory immediately, only defer the buffer set. * Fix some memory tracking issues * Pass correct pages count on shared memory unmap * Armeilleure Signal Handler v1 + Unix changes Unix currently behaves like windows, rather than remapping physical * Actually check if the host platform is unix * Fix decommit on linux. * Implement windows 10 placeholder shared memory, fix a buffer issue. * Make PTC version something that will never match with master * Remove testing variable for block count * Add reference count for memory manager, fix dispose Can still deadlock with OpenAL * Add address validation, use page table for mapped check, add docs Might clean up the page table traversing routines. * Implement batched mapping/tracking. * Move documentation, fix tests. * Cleanup uniform buffer update stuff. * Remove unnecessary assignment. * Add unsafe host mapped memory switch On by default. Would be good to turn this off for untrusted code (homebrew, exefs mods) and give the user the option to turn it on manually, though that requires some UI work. * Remove C# exception handlers They have issues due to current .NET limitations, so the meilleure one fully replaces them for now. * Fix MapPhysicalMemory on the software MemoryManager. * Null check for GetHostAddress, docs * Add configuration for setting memory manager mode (not in UI yet) * Add config to UI * Fix type mismatch on Unix signal handler code emit * Fix 6GB DRAM mode. The size can be greater than `uint.MaxValue` when the DRAM is >4GB. * Address some feedback. * More detailed error if backing memory cannot be mapped. * SetLastError on all OS functions for consistency * Force pages dirty with UBO update instead of setting them directly. Seems to be much faster across a few games. Need retesting. * Rebase, configuration rework, fix mem tracking regression * Fix race in FreePages * Set memory managers null after decrementing ref count * Remove readonly keyword, as this is now modified. * Use a local variable for the signal handler rather than a register. * Fix bug with buffer resize, and index/uniform buffer binding. Should fix flickering in games. * Add InvalidAccessHandler to MemoryTracking Doesn't do anything yet * Call invalid access handler on unmapped read/write. Same rules as the regular memory manager. * Make unsafe mapped memory its own MemoryManagerType * Move FlushUboDirty into UpdateState. * Buffer dirty cache, rather than ubo cache Much cleaner, may be reusable for Inline2Memory updates. * This doesn't return anything anymore. * Add sigaction remove methods, correct a few function signatures. * Return empty list of physical regions for size 0. * Also on AddressSpaceManager Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Diffstat (limited to 'Ryujinx.Cpu/MemoryManager.cs')
-rw-r--r--Ryujinx.Cpu/MemoryManager.cs291
1 files changed, 86 insertions, 205 deletions
diff --git a/Ryujinx.Cpu/MemoryManager.cs b/Ryujinx.Cpu/MemoryManager.cs
index 591299ca..dbc2f736 100644
--- a/Ryujinx.Cpu/MemoryManager.cs
+++ b/Ryujinx.Cpu/MemoryManager.cs
@@ -1,9 +1,11 @@
using ARMeilleure.Memory;
using Ryujinx.Cpu.Tracking;
using Ryujinx.Memory;
+using Ryujinx.Memory.Range;
using Ryujinx.Memory.Tracking;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
@@ -13,7 +15,7 @@ namespace Ryujinx.Cpu
/// <summary>
/// Represents a CPU memory manager.
/// </summary>
- public sealed class MemoryManager : IMemoryManager, IVirtualMemoryManager, IWritableBlock, IDisposable
+ public sealed class MemoryManager : MemoryManagerBase, IMemoryManager, IVirtualMemoryManagerTracked, IWritableBlock
{
public const int PageBits = 12;
public const int PageSize = 1 << PageBits;
@@ -32,7 +34,6 @@ namespace Ryujinx.Cpu
private readonly ulong _addressSpaceSize;
- private readonly MemoryBlock _backingMemory;
private readonly MemoryBlock _pageTable;
/// <summary>
@@ -40,17 +41,18 @@ namespace Ryujinx.Cpu
/// </summary>
public IntPtr PageTablePointer => _pageTable.Pointer;
+ public MemoryManagerType Type => MemoryManagerType.SoftwarePageTable;
+
public MemoryTracking Tracking { get; }
- internal event Action<ulong, ulong> UnmapEvent;
+ public event Action<ulong, ulong> UnmapEvent;
/// <summary>
/// Creates a new instance of the memory manager.
/// </summary>
- /// <param name="backingMemory">Physical backing memory where virtual memory will be mapped to</param>
/// <param name="addressSpaceSize">Size of the address space</param>
/// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param>
- public MemoryManager(MemoryBlock backingMemory, ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler = null)
+ public MemoryManager(ulong addressSpaceSize, InvalidAccessHandler invalidAccessHandler = null)
{
_invalidAccessHandler = invalidAccessHandler;
@@ -65,45 +67,30 @@ namespace Ryujinx.Cpu
AddressSpaceBits = asBits;
_addressSpaceSize = asSize;
- _backingMemory = backingMemory;
_pageTable = new MemoryBlock((asSize / PageSize) * PteSize);
- Tracking = new MemoryTracking(this, backingMemory, PageSize);
- Tracking.EnablePhysicalProtection = false; // Disabled for now, as protection is done in software.
+ Tracking = new MemoryTracking(this, PageSize);
}
- /// <summary>
- /// Maps a virtual memory range into a physical memory range.
- /// </summary>
- /// <remarks>
- /// Addresses and size must be page aligned.
- /// </remarks>
- /// <param name="va">Virtual memory address</param>
- /// <param name="pa">Physical memory address</param>
- /// <param name="size">Size to be mapped</param>
- public void Map(ulong va, ulong pa, ulong size)
+ /// <inheritdoc/>
+ public void Map(ulong va, nuint hostAddress, ulong size)
{
AssertValidAddressAndSize(va, size);
ulong remainingSize = size;
ulong oVa = va;
- ulong oPa = pa;
while (remainingSize != 0)
{
- _pageTable.Write((va / PageSize) * PteSize, PaToPte(pa));
+ _pageTable.Write((va / PageSize) * PteSize, hostAddress);
va += PageSize;
- pa += PageSize;
+ hostAddress += PageSize;
remainingSize -= PageSize;
}
- Tracking.Map(oVa, oPa, size);
+ Tracking.Map(oVa, size);
}
- /// <summary>
- /// Unmaps a previously mapped range of virtual memory.
- /// </summary>
- /// <param name="va">Virtual address of the range to be unmapped</param>
- /// <param name="size">Size of the range to be unmapped</param>
+ /// <inheritdoc/>
public void Unmap(ulong va, ulong size)
{
// If size is 0, there's nothing to unmap, just exit early.
@@ -120,66 +107,39 @@ namespace Ryujinx.Cpu
ulong remainingSize = size;
while (remainingSize != 0)
{
- _pageTable.Write((va / PageSize) * PteSize, 0UL);
+ _pageTable.Write((va / PageSize) * PteSize, (nuint)0);
va += PageSize;
remainingSize -= PageSize;
}
}
- /// <summary>
- /// Reads data from CPU mapped memory.
- /// </summary>
- /// <typeparam name="T">Type of the data being read</typeparam>
- /// <param name="va">Virtual address of the data in memory</param>
- /// <returns>The data</returns>
- /// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
+ /// <inheritdoc/>
public T Read<T>(ulong va) where T : unmanaged
{
return MemoryMarshal.Cast<byte, T>(GetSpan(va, Unsafe.SizeOf<T>(), true))[0];
}
- /// <summary>
- /// Reads data from CPU mapped memory, with read tracking
- /// </summary>
- /// <typeparam name="T">Type of the data being read</typeparam>
- /// <param name="va">Virtual address of the data in memory</param>
- /// <returns>The data</returns>
+ /// <inheritdoc/>
public T ReadTracked<T>(ulong va) where T : unmanaged
{
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), false);
return MemoryMarshal.Cast<byte, T>(GetSpan(va, Unsafe.SizeOf<T>()))[0];
}
- /// <summary>
- /// Reads data from CPU mapped memory.
- /// </summary>
- /// <param name="va">Virtual address of the data in memory</param>
- /// <param name="data">Span to store the data being read into</param>
- /// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
+ /// <inheritdoc/>
public void Read(ulong va, Span<byte> data)
{
ReadImpl(va, data);
}
- /// <summary>
- /// Writes data to CPU mapped memory.
- /// </summary>
- /// <typeparam name="T">Type of the data being written</typeparam>
- /// <param name="va">Virtual address to write the data into</param>
- /// <param name="value">Data to be written</param>
- /// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
+ /// <inheritdoc/>
public void Write<T>(ulong va, T value) where T : unmanaged
{
Write(va, MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref value, 1)));
}
- /// <summary>
- /// Writes data to CPU mapped memory, with write tracking.
- /// </summary>
- /// <param name="va">Virtual address to write the data into</param>
- /// <param name="data">Data to be written</param>
- /// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
+ /// <inheritdoc/>
public void Write(ulong va, ReadOnlySpan<byte> data)
{
if (data.Length == 0)
@@ -192,11 +152,7 @@ namespace Ryujinx.Cpu
WriteImpl(va, data);
}
- /// <summary>
- /// Writes data to CPU mapped memory, without write tracking.
- /// </summary>
- /// <param name="va">Virtual address to write the data into</param>
- /// <param name="data">Data to be written</param>
+ /// <inheritdoc/>
public void WriteUntracked(ulong va, ReadOnlySpan<byte> data)
{
if (data.Length == 0)
@@ -221,7 +177,7 @@ namespace Ryujinx.Cpu
if (IsContiguousAndMapped(va, data.Length))
{
- data.CopyTo(_backingMemory.GetSpan(GetPhysicalAddressInternal(va), data.Length));
+ data.CopyTo(GetHostSpanContiguous(va, data.Length));
}
else
{
@@ -229,22 +185,18 @@ namespace Ryujinx.Cpu
if ((va & PageMask) != 0)
{
- ulong pa = GetPhysicalAddressInternal(va);
-
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
- data.Slice(0, size).CopyTo(_backingMemory.GetSpan(pa, size));
+ data.Slice(0, size).CopyTo(GetHostSpanContiguous(va, size));
offset += size;
}
for (; offset < data.Length; offset += size)
{
- ulong pa = GetPhysicalAddressInternal(va + (ulong)offset);
-
size = Math.Min(data.Length - offset, PageSize);
- data.Slice(offset, size).CopyTo(_backingMemory.GetSpan(pa, size));
+ data.Slice(offset, size).CopyTo(GetHostSpanContiguous(va + (ulong)offset, size));
}
}
}
@@ -257,18 +209,7 @@ namespace Ryujinx.Cpu
}
}
- /// <summary>
- /// Gets a read-only span of data from CPU mapped memory.
- /// </summary>
- /// <remarks>
- /// This may perform a allocation if the data is not contiguous in memory.
- /// For this reason, the span is read-only, you can't modify the data.
- /// </remarks>
- /// <param name="va">Virtual address of the data</param>
- /// <param name="size">Size of the data</param>
- /// <param name="tracked">True if read tracking is triggered on the span</param>
- /// <returns>A read-only span of the data</returns>
- /// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
+ /// <inheritdoc/>
public ReadOnlySpan<byte> GetSpan(ulong va, int size, bool tracked = false)
{
if (size == 0)
@@ -283,7 +224,7 @@ namespace Ryujinx.Cpu
if (IsContiguousAndMapped(va, size))
{
- return _backingMemory.GetSpan(GetPhysicalAddressInternal(va), size);
+ return GetHostSpanContiguous(va, size);
}
else
{
@@ -295,19 +236,8 @@ namespace Ryujinx.Cpu
}
}
- /// <summary>
- /// Gets a region of memory that can be written to.
- /// </summary>
- /// <remarks>
- /// If the requested region is not contiguous in physical memory,
- /// this will perform an allocation, and flush the data (writing it
- /// back to guest memory) on disposal.
- /// </remarks>
- /// <param name="va">Virtual address of the data</param>
- /// <param name="size">Size of the data</param>
- /// <returns>A writable region of memory containing the data</returns>
- /// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
- public WritableRegion GetWritableRegion(ulong va, int size)
+ /// <inheritdoc/>
+ public unsafe WritableRegion GetWritableRegion(ulong va, int size)
{
if (size == 0)
{
@@ -316,7 +246,7 @@ namespace Ryujinx.Cpu
if (IsContiguousAndMapped(va, size))
{
- return new WritableRegion(null, va, _backingMemory.GetMemory(GetPhysicalAddressInternal(va), size));
+ return new WritableRegion(null, va, new NativeMemoryManager<byte>((byte*)GetHostAddress(va), size).Memory);
}
else
{
@@ -328,17 +258,8 @@ namespace Ryujinx.Cpu
}
}
- /// <summary>
- /// Gets a reference for the given type at the specified virtual memory address.
- /// </summary>
- /// <remarks>
- /// The data must be located at a contiguous memory region.
- /// </remarks>
- /// <typeparam name="T">Type of the data to get the reference</typeparam>
- /// <param name="va">Virtual address of the data</param>
- /// <returns>A reference to the data in memory</returns>
- /// <exception cref="MemoryNotContiguousException">Throw if the specified memory region is not contiguous in physical memory</exception>
- public ref T GetRef<T>(ulong va) where T : unmanaged
+ /// <inheritdoc/>
+ public unsafe ref T GetRef<T>(ulong va) where T : unmanaged
{
if (!IsContiguous(va, Unsafe.SizeOf<T>()))
{
@@ -347,7 +268,7 @@ namespace Ryujinx.Cpu
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), true);
- return ref _backingMemory.GetRef<T>(GetPhysicalAddressInternal(va));
+ return ref *(T*)GetHostAddress(va);
}
/// <summary>
@@ -389,7 +310,7 @@ namespace Ryujinx.Cpu
return false;
}
- if (GetPhysicalAddressInternal(va) + PageSize != GetPhysicalAddressInternal(va + PageSize))
+ if (GetHostAddress(va) + PageSize != GetHostAddress(va + PageSize))
{
return false;
}
@@ -400,15 +321,14 @@ namespace Ryujinx.Cpu
return true;
}
- /// <summary>
- /// Gets the physical regions that make up the given virtual address region.
- /// If any part of the virtual region is unmapped, null is returned.
- /// </summary>
- /// <param name="va">Virtual address of the range</param>
- /// <param name="size">Size of the range</param>
- /// <returns>Array of physical regions</returns>
- public (ulong address, ulong size)[] GetPhysicalRegions(ulong va, ulong size)
+ /// <inheritdoc/>
+ public IEnumerable<HostMemoryRange> GetPhysicalRegions(ulong va, ulong size)
{
+ if (size == 0)
+ {
+ return Enumerable.Empty<HostMemoryRange>();
+ }
+
if (!ValidateAddress(va) || !ValidateAddressAndSize(va, size))
{
return null;
@@ -416,9 +336,9 @@ namespace Ryujinx.Cpu
int pages = GetPagesCount(va, (uint)size, out va);
- List<(ulong, ulong)> regions = new List<(ulong, ulong)>();
+ var regions = new List<HostMemoryRange>();
- ulong regionStart = GetPhysicalAddressInternal(va);
+ nuint regionStart = GetHostAddress(va);
ulong regionSize = PageSize;
for (int page = 0; page < pages - 1; page++)
@@ -428,12 +348,12 @@ namespace Ryujinx.Cpu
return null;
}
- ulong newPa = GetPhysicalAddressInternal(va + PageSize);
+ nuint newHostAddress = GetHostAddress(va + PageSize);
- if (GetPhysicalAddressInternal(va) + PageSize != newPa)
+ if (GetHostAddress(va) + PageSize != newHostAddress)
{
- regions.Add((regionStart, regionSize));
- regionStart = newPa;
+ regions.Add(new HostMemoryRange(regionStart, regionSize));
+ regionStart = newHostAddress;
regionSize = 0;
}
@@ -441,9 +361,9 @@ namespace Ryujinx.Cpu
regionSize += PageSize;
}
- regions.Add((regionStart, regionSize));
+ regions.Add(new HostMemoryRange(regionStart, regionSize));
- return regions.ToArray();
+ return regions;
}
private void ReadImpl(ulong va, Span<byte> data)
@@ -461,22 +381,18 @@ namespace Ryujinx.Cpu
if ((va & PageMask) != 0)
{
- ulong pa = GetPhysicalAddressInternal(va);
-
size = Math.Min(data.Length, PageSize - (int)(va & PageMask));
- _backingMemory.GetSpan(pa, size).CopyTo(data.Slice(0, size));
+ GetHostSpanContiguous(va, size).CopyTo(data.Slice(0, size));
offset += size;
}
for (; offset < data.Length; offset += size)
{
- ulong pa = GetPhysicalAddressInternal(va + (ulong)offset);
-
size = Math.Min(data.Length - offset, PageSize);
- _backingMemory.GetSpan(pa, size).CopyTo(data.Slice(offset, size));
+ GetHostSpanContiguous(va + (ulong)offset, size).CopyTo(data.Slice(offset, size));
}
}
catch (InvalidMemoryRegionException)
@@ -488,12 +404,7 @@ namespace Ryujinx.Cpu
}
}
- /// <summary>
- /// Checks if a memory range is mapped.
- /// </summary>
- /// <param name="va">Virtual address of the range</param>
- /// <param name="size">Size of the range in bytes</param>
- /// <returns>True if the entire range is mapped, false otherwise</returns>
+ /// <inheritdoc/>
public bool IsRangeMapped(ulong va, ulong size)
{
if (size == 0UL)
@@ -521,11 +432,7 @@ namespace Ryujinx.Cpu
return true;
}
- /// <summary>
- /// Checks if the page at a given CPU virtual address is mapped.
- /// </summary>
- /// <param name="va">Virtual address to check</param>
- /// <returns>True if the address is mapped, false otherwise</returns>
+ /// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsMapped(ulong va)
{
@@ -534,7 +441,7 @@ namespace Ryujinx.Cpu
return false;
}
- return _pageTable.Read<ulong>((va / PageSize) * PteSize) != 0;
+ return _pageTable.Read<nuint>((va / PageSize) * PteSize) != 0;
}
private bool ValidateAddress(ulong va)
@@ -569,35 +476,39 @@ namespace Ryujinx.Cpu
}
/// <summary>
- /// Performs address translation of the address inside a CPU mapped memory range.
+ /// Get a span representing the given virtual address and size range in host memory.
+ /// This function assumes that the requested virtual memory region is contiguous.
/// </summary>
- /// <remarks>
- /// If the address is invalid or unmapped, -1 will be returned.
- /// </remarks>
- /// <param name="va">Virtual address to be translated</param>
- /// <returns>The physical address</returns>
- public ulong GetPhysicalAddress(ulong va)
+ /// <param name="va">Virtual address of the range</param>
+ /// <param name="size">Size of the range in bytes</param>
+ /// <returns>A span representing the given virtual range in host memory</returns>
+ /// <exception cref="InvalidMemoryRegionException">Throw when the base virtual address is not mapped</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private unsafe Span<byte> GetHostSpanContiguous(ulong va, int size)
{
- // We return -1L if the virtual address is invalid or unmapped.
- if (!ValidateAddress(va) || !IsMapped(va))
- {
- return ulong.MaxValue;
- }
-
- return GetPhysicalAddressInternal(va);
+ return new Span<byte>((void*)GetHostAddress(va), size);
}
- private ulong GetPhysicalAddressInternal(ulong va)
+ /// <summary>
+ /// Get the host address for a given virtual address, using the page table.
+ /// </summary>
+ /// <param name="va">Virtual address</param>
+ /// <returns>The corresponding host address for the given virtual address</returns>
+ /// <exception cref="InvalidMemoryRegionException">Throw when the virtual address is not mapped</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private nuint GetHostAddress(ulong va)
{
- return PteToPa(_pageTable.Read<ulong>((va / PageSize) * PteSize) & ~(0xffffUL << 48)) + (va & PageMask);
+ nuint pageBase = _pageTable.Read<nuint>((va / PageSize) * PteSize) & unchecked((nuint)0xffff_ffff_ffffUL);
+
+ if (pageBase == 0)
+ {
+ ThrowInvalidMemoryRegionException($"Not mapped: va=0x{va:X16}");
+ }
+
+ return pageBase + (nuint)(va & PageMask);
}
- /// <summary>
- /// Reprotect a region of virtual memory for tracking. Sets software protection bits.
- /// </summary>
- /// <param name="va">Virtual address base</param>
- /// <param name="size">Size of the region to protect</param>
- /// <param name="protection">Memory protection to set</param>
+ /// <inheritdoc/>
public void TrackingReprotect(ulong va, ulong size, MemoryPermission protection)
{
AssertValidAddressAndSize(va, size);
@@ -632,47 +543,25 @@ namespace Ryujinx.Cpu
}
}
- /// <summary>
- /// Obtains a memory tracking handle for the given virtual region. This should be disposed when finished with.
- /// </summary>
- /// <param name="address">CPU virtual address of the region</param>
- /// <param name="size">Size of the region</param>
- /// <returns>The memory tracking handle</returns>
+ /// <inheritdoc/>
public CpuRegionHandle BeginTracking(ulong address, ulong size)
{
return new CpuRegionHandle(Tracking.BeginTracking(address, size));
}
- /// <summary>
- /// Obtains a memory tracking handle for the given virtual region, with a specified granularity. This should be disposed when finished with.
- /// </summary>
- /// <param name="address">CPU virtual address of the region</param>
- /// <param name="size">Size of the region</param>
- /// <param name="granularity">Desired granularity of write tracking</param>
- /// <returns>The memory tracking handle</returns>
+ /// <inheritdoc/>
public CpuMultiRegionHandle BeginGranularTracking(ulong address, ulong size, ulong granularity)
{
return new CpuMultiRegionHandle(Tracking.BeginGranularTracking(address, size, granularity));
}
- /// <summary>
- /// Obtains a smart memory tracking handle for the given virtual region, with a specified granularity. This should be disposed when finished with.
- /// </summary>
- /// <param name="address">CPU virtual address of the region</param>
- /// <param name="size">Size of the region</param>
- /// <param name="granularity">Desired granularity of write tracking</param>
- /// <returns>The memory tracking handle</returns>
+ /// <inheritdoc/>
public CpuSmartMultiRegionHandle BeginSmartGranularTracking(ulong address, ulong size, ulong granularity)
{
return new CpuSmartMultiRegionHandle(Tracking.BeginSmartGranularTracking(address, size, granularity));
}
- /// <summary>
- /// Alerts the memory tracking that a given region has been read from or written to.
- /// This should be called before read/write is performed.
- /// </summary>
- /// <param name="va">Virtual address of the region</param>
- /// <param name="size">Size of the region</param>
+ /// <inheritdoc/>
public void SignalMemoryTracking(ulong va, ulong size, bool write)
{
AssertValidAddressAndSize(va, size);
@@ -704,19 +593,11 @@ namespace Ryujinx.Cpu
}
}
- private ulong PaToPte(ulong pa)
- {
- return (ulong)_backingMemory.GetPointer(pa, PageSize).ToInt64();
- }
-
- private ulong PteToPa(ulong pte)
- {
- return (ulong)((long)pte - _backingMemory.Pointer.ToInt64());
- }
-
/// <summary>
/// Disposes of resources used by the memory manager.
/// </summary>
- public void Dispose() => _pageTable.Dispose();
+ protected override void Destroy() => _pageTable.Dispose();
+
+ private void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message);
}
}