KMemoryBlock.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using Ryujinx.Common.Collections;
  2. using System;
  3. namespace Ryujinx.HLE.HOS.Kernel.Memory
  4. {
  5. class KMemoryBlock : IntrusiveRedBlackTreeNode<KMemoryBlock>, IComparable<KMemoryBlock>, IComparable<ulong>
  6. {
  7. public ulong BaseAddress { get; private set; }
  8. public ulong PagesCount { get; private set; }
  9. public MemoryState State { get; private set; }
  10. public KMemoryPermission Permission { get; private set; }
  11. public MemoryAttribute Attribute { get; private set; }
  12. public KMemoryPermission SourcePermission { get; private set; }
  13. public int IpcRefCount { get; private set; }
  14. public int DeviceRefCount { get; private set; }
  15. public KMemoryBlock(
  16. ulong baseAddress,
  17. ulong pagesCount,
  18. MemoryState state,
  19. KMemoryPermission permission,
  20. MemoryAttribute attribute,
  21. int ipcRefCount = 0,
  22. int deviceRefCount = 0)
  23. {
  24. BaseAddress = baseAddress;
  25. PagesCount = pagesCount;
  26. State = state;
  27. Attribute = attribute;
  28. Permission = permission;
  29. IpcRefCount = ipcRefCount;
  30. DeviceRefCount = deviceRefCount;
  31. }
  32. public void SetState(KMemoryPermission permission, MemoryState state, MemoryAttribute attribute)
  33. {
  34. Permission = permission;
  35. State = state;
  36. Attribute &= MemoryAttribute.IpcAndDeviceMapped;
  37. Attribute |= attribute;
  38. }
  39. public void SetIpcMappingPermission(KMemoryPermission newPermission)
  40. {
  41. int oldIpcRefCount = IpcRefCount++;
  42. if ((ushort)IpcRefCount == 0)
  43. {
  44. throw new InvalidOperationException("IPC reference count increment overflowed.");
  45. }
  46. if (oldIpcRefCount == 0)
  47. {
  48. SourcePermission = Permission;
  49. Permission &= ~KMemoryPermission.ReadAndWrite;
  50. Permission |= KMemoryPermission.ReadAndWrite & newPermission;
  51. }
  52. Attribute |= MemoryAttribute.IpcMapped;
  53. }
  54. public void RestoreIpcMappingPermission()
  55. {
  56. int oldIpcRefCount = IpcRefCount--;
  57. if (oldIpcRefCount == 0)
  58. {
  59. throw new InvalidOperationException("IPC reference count decrement underflowed.");
  60. }
  61. if (oldIpcRefCount == 1)
  62. {
  63. Permission = SourcePermission;
  64. SourcePermission = KMemoryPermission.None;
  65. Attribute &= ~MemoryAttribute.IpcMapped;
  66. }
  67. }
  68. public KMemoryBlock SplitRightAtAddress(ulong address)
  69. {
  70. ulong leftAddress = BaseAddress;
  71. ulong leftPagesCount = (address - leftAddress) / KPageTableBase.PageSize;
  72. BaseAddress = address;
  73. PagesCount -= leftPagesCount;
  74. return new KMemoryBlock(
  75. leftAddress,
  76. leftPagesCount,
  77. State,
  78. Permission,
  79. Attribute,
  80. IpcRefCount,
  81. DeviceRefCount);
  82. }
  83. public void AddPages(ulong pagesCount)
  84. {
  85. PagesCount += pagesCount;
  86. }
  87. public KMemoryInfo GetInfo()
  88. {
  89. ulong size = PagesCount * KPageTableBase.PageSize;
  90. return new KMemoryInfo(
  91. BaseAddress,
  92. size,
  93. State,
  94. Permission,
  95. Attribute,
  96. SourcePermission,
  97. IpcRefCount,
  98. DeviceRefCount);
  99. }
  100. public int CompareTo(KMemoryBlock other)
  101. {
  102. if (BaseAddress < other.BaseAddress)
  103. {
  104. return -1;
  105. }
  106. else if (BaseAddress <= other.BaseAddress + other.PagesCount * KPageTableBase.PageSize - 1UL)
  107. {
  108. return 0;
  109. }
  110. else
  111. {
  112. return 1;
  113. }
  114. }
  115. public int CompareTo(ulong address)
  116. {
  117. if (address < BaseAddress)
  118. {
  119. return 1;
  120. }
  121. else if (address <= BaseAddress + PagesCount * KPageTableBase.PageSize - 1UL)
  122. {
  123. return 0;
  124. }
  125. else
  126. {
  127. return -1;
  128. }
  129. }
  130. }
  131. }