aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Memory/Tracking/RegionHandle.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Memory/Tracking/RegionHandle.cs')
-rw-r--r--src/Ryujinx.Memory/Tracking/RegionHandle.cs68
1 files changed, 56 insertions, 12 deletions
diff --git a/src/Ryujinx.Memory/Tracking/RegionHandle.cs b/src/Ryujinx.Memory/Tracking/RegionHandle.cs
index df3d9c31..a94ffa43 100644
--- a/src/Ryujinx.Memory/Tracking/RegionHandle.cs
+++ b/src/Ryujinx.Memory/Tracking/RegionHandle.cs
@@ -55,6 +55,8 @@ namespace Ryujinx.Memory.Tracking
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
private PreciseRegionSignal _preciseAction; // Action to perform on a precise read or write.
private readonly List<VirtualRegion> _regions;
+ private readonly List<VirtualRegion> _guestRegions;
+ private readonly List<VirtualRegion> _allRegions;
private readonly MemoryTracking _tracking;
private bool _disposed;
@@ -99,6 +101,7 @@ namespace Ryujinx.Memory.Tracking
/// <param name="bitmap">The bitmap the dirty flag for this handle is stored in</param>
/// <param name="bit">The bit index representing the dirty flag for this handle</param>
/// <param name="id">Handle ID</param>
+ /// <param name="flags">Region flags</param>
/// <param name="mapped">True if the region handle starts mapped</param>
internal RegionHandle(
MemoryTracking tracking,
@@ -109,6 +112,7 @@ namespace Ryujinx.Memory.Tracking
ConcurrentBitmap bitmap,
int bit,
int id,
+ RegionFlags flags,
bool mapped = true)
{
Bitmap = bitmap;
@@ -128,11 +132,12 @@ namespace Ryujinx.Memory.Tracking
RealEndAddress = realAddress + realSize;
_tracking = tracking;
- _regions = tracking.GetVirtualRegionsForHandle(address, size);
- foreach (var region in _regions)
- {
- region.Handles.Add(this);
- }
+
+ _regions = tracking.GetVirtualRegionsForHandle(address, size, false);
+ _guestRegions = GetGuestRegions(tracking, address, size, flags);
+ _allRegions = new List<VirtualRegion>(_regions.Count + _guestRegions.Count);
+
+ InitializeRegions();
}
/// <summary>
@@ -145,8 +150,9 @@ namespace Ryujinx.Memory.Tracking
/// <param name="realAddress">The real, unaligned address of the handle</param>
/// <param name="realSize">The real, unaligned size of the handle</param>
/// <param name="id">Handle ID</param>
+ /// <param name="flags">Region flags</param>
/// <param name="mapped">True if the region handle starts mapped</param>
- internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, ulong realAddress, ulong realSize, int id, bool mapped = true)
+ internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, ulong realAddress, ulong realSize, int id, RegionFlags flags, bool mapped = true)
{
Bitmap = new ConcurrentBitmap(1, mapped);
@@ -163,8 +169,37 @@ namespace Ryujinx.Memory.Tracking
RealEndAddress = realAddress + realSize;
_tracking = tracking;
- _regions = tracking.GetVirtualRegionsForHandle(address, size);
- foreach (var region in _regions)
+
+ _regions = tracking.GetVirtualRegionsForHandle(address, size, false);
+ _guestRegions = GetGuestRegions(tracking, address, size, flags);
+ _allRegions = new List<VirtualRegion>(_regions.Count + _guestRegions.Count);
+
+ InitializeRegions();
+ }
+
+ private List<VirtualRegion> GetGuestRegions(MemoryTracking tracking, ulong address, ulong size, RegionFlags flags)
+ {
+ ulong guestAddress;
+ ulong guestSize;
+
+ if (flags.HasFlag(RegionFlags.UnalignedAccess))
+ {
+ (guestAddress, guestSize) = tracking.GetUnalignedSafeRegion(address, size);
+ }
+ else
+ {
+ (guestAddress, guestSize) = (address, size);
+ }
+
+ return tracking.GetVirtualRegionsForHandle(guestAddress, guestSize, true);
+ }
+
+ private void InitializeRegions()
+ {
+ _allRegions.AddRange(_regions);
+ _allRegions.AddRange(_guestRegions);
+
+ foreach (var region in _allRegions)
{
region.Handles.Add(this);
}
@@ -321,7 +356,7 @@ namespace Ryujinx.Memory.Tracking
lock (_tracking.TrackingLock)
{
- foreach (VirtualRegion region in _regions)
+ foreach (VirtualRegion region in _allRegions)
{
protectionChanged |= region.UpdateProtection();
}
@@ -379,7 +414,7 @@ namespace Ryujinx.Memory.Tracking
{
lock (_tracking.TrackingLock)
{
- foreach (VirtualRegion region in _regions)
+ foreach (VirtualRegion region in _allRegions)
{
region.UpdateProtection();
}
@@ -414,7 +449,16 @@ namespace Ryujinx.Memory.Tracking
/// <param name="region">Virtual region to add as a child</param>
internal void AddChild(VirtualRegion region)
{
- _regions.Add(region);
+ if (region.Guest)
+ {
+ _guestRegions.Add(region);
+ }
+ else
+ {
+ _regions.Add(region);
+ }
+
+ _allRegions.Add(region);
}
/// <summary>
@@ -469,7 +513,7 @@ namespace Ryujinx.Memory.Tracking
lock (_tracking.TrackingLock)
{
- foreach (VirtualRegion region in _regions)
+ foreach (VirtualRegion region in _allRegions)
{
region.RemoveHandle(this);
}