VirtualRegion.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. IList<RegionHandle> handles = Handles;
  21. for (int i = 0; i < handles.Count; i++)
  22. {
  23. handles[i].Signal(address, size, write, ref handles);
  24. }
  25. UpdateProtection();
  26. }
  27. /// <summary>
  28. /// Signal that this region has been mapped or unmapped.
  29. /// </summary>
  30. /// <param name="mapped">True if the region has been mapped, false if unmapped</param>
  31. public void SignalMappingChanged(bool mapped)
  32. {
  33. _lastPermission = MemoryPermission.Invalid;
  34. foreach (RegionHandle handle in Handles)
  35. {
  36. handle.SignalMappingChanged(mapped);
  37. }
  38. }
  39. /// <summary>
  40. /// Gets the strictest permission that the child handles demand. Assumes that the tracking lock has been obtained.
  41. /// </summary>
  42. /// <returns>Protection level that this region demands</returns>
  43. public MemoryPermission GetRequiredPermission()
  44. {
  45. // Start with Read/Write, each handle can strip off permissions as necessary.
  46. // Assumes the tracking lock has already been obtained.
  47. MemoryPermission result = MemoryPermission.ReadAndWrite;
  48. foreach (var handle in Handles)
  49. {
  50. result &= handle.RequiredPermission;
  51. if (result == 0) return result;
  52. }
  53. return result;
  54. }
  55. /// <summary>
  56. /// Updates the protection for this virtual region.
  57. /// </summary>
  58. public bool UpdateProtection()
  59. {
  60. MemoryPermission permission = GetRequiredPermission();
  61. if (_lastPermission != permission)
  62. {
  63. _tracking.ProtectVirtualRegion(this, permission);
  64. _lastPermission = permission;
  65. return true;
  66. }
  67. return false;
  68. }
  69. /// <summary>
  70. /// Removes a handle from this virtual region. If there are no handles left, this virtual region is removed.
  71. /// </summary>
  72. /// <param name="handle">Handle to remove</param>
  73. public void RemoveHandle(RegionHandle handle)
  74. {
  75. lock (_tracking.TrackingLock)
  76. {
  77. Handles.Remove(handle);
  78. UpdateProtection();
  79. if (Handles.Count == 0)
  80. {
  81. _tracking.RemoveVirtual(this);
  82. }
  83. }
  84. }
  85. public override INonOverlappingRange Split(ulong splitAddress)
  86. {
  87. VirtualRegion newRegion = new VirtualRegion(_tracking, splitAddress, EndAddress - splitAddress, _lastPermission);
  88. Size = splitAddress - Address;
  89. // The new region inherits all of our parents.
  90. newRegion.Handles = new List<RegionHandle>(Handles);
  91. foreach (var parent in Handles)
  92. {
  93. parent.AddChild(newRegion);
  94. }
  95. return newRegion;
  96. }
  97. }
  98. }