VirtualRegion.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using Ryujinx.Memory.Range;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Memory.Tracking
  4. {
  5. /// <summary>
  6. /// A region of virtual memory.
  7. /// </summary>
  8. class VirtualRegion : AbstractRegion
  9. {
  10. public List<RegionHandle> Handles = new List<RegionHandle>();
  11. private readonly MemoryTracking _tracking;
  12. private MemoryPermission _lastPermission;
  13. public VirtualRegion(MemoryTracking tracking, ulong address, ulong size, MemoryPermission lastPermission = MemoryPermission.Invalid) : base(address, size)
  14. {
  15. _lastPermission = lastPermission;
  16. _tracking = tracking;
  17. }
  18. public override void Signal(ulong address, ulong size, bool write)
  19. {
  20. foreach (var handle in Handles)
  21. {
  22. handle.Signal(address, size, write);
  23. }
  24. UpdateProtection();
  25. }
  26. /// <summary>
  27. /// Signal that this region has been mapped or unmapped.
  28. /// </summary>
  29. /// <param name="mapped">True if the region has been mapped, false if unmapped</param>
  30. public void SignalMappingChanged(bool mapped)
  31. {
  32. _lastPermission = MemoryPermission.Invalid;
  33. foreach (RegionHandle handle in Handles)
  34. {
  35. handle.SignalMappingChanged(mapped);
  36. }
  37. }
  38. /// <summary>
  39. /// Gets the strictest permission that the child handles demand. Assumes that the tracking lock has been obtained.
  40. /// </summary>
  41. /// <returns>Protection level that this region demands</returns>
  42. public MemoryPermission GetRequiredPermission()
  43. {
  44. // Start with Read/Write, each handle can strip off permissions as necessary.
  45. // Assumes the tracking lock has already been obtained.
  46. MemoryPermission result = MemoryPermission.ReadAndWrite;
  47. foreach (var handle in Handles)
  48. {
  49. result &= handle.RequiredPermission;
  50. if (result == 0) return result;
  51. }
  52. return result;
  53. }
  54. /// <summary>
  55. /// Updates the protection for this virtual region.
  56. /// </summary>
  57. public bool UpdateProtection()
  58. {
  59. MemoryPermission permission = GetRequiredPermission();
  60. if (_lastPermission != permission)
  61. {
  62. _tracking.ProtectVirtualRegion(this, permission);
  63. _lastPermission = permission;
  64. return true;
  65. }
  66. return false;
  67. }
  68. /// <summary>
  69. /// Removes a handle from this virtual region. If there are no handles left, this virtual region is removed.
  70. /// </summary>
  71. /// <param name="handle">Handle to remove</param>
  72. public void RemoveHandle(RegionHandle handle)
  73. {
  74. lock (_tracking.TrackingLock)
  75. {
  76. Handles.Remove(handle);
  77. UpdateProtection();
  78. if (Handles.Count == 0)
  79. {
  80. _tracking.RemoveVirtual(this);
  81. }
  82. }
  83. }
  84. public override INonOverlappingRange Split(ulong splitAddress)
  85. {
  86. VirtualRegion newRegion = new VirtualRegion(_tracking, splitAddress, EndAddress - splitAddress, _lastPermission);
  87. Size = splitAddress - Address;
  88. // The new region inherits all of our parents.
  89. newRegion.Handles = new List<RegionHandle>(Handles);
  90. foreach (var parent in Handles)
  91. {
  92. parent.AddChild(newRegion);
  93. }
  94. return newRegion;
  95. }
  96. }
  97. }