KMemoryBlock.cs 3.6 KB

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