NvGpuASCtx.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using Ryujinx.Graphics.Memory;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.HLE.HOS.Services.Nv.NvGpuAS
  4. {
  5. class NvGpuASCtx
  6. {
  7. public NvGpuVmm Vmm { get; private set; }
  8. private class Range
  9. {
  10. public ulong Start { get; private set; }
  11. public ulong End { get; private set; }
  12. public Range(long position, long size)
  13. {
  14. Start = (ulong)position;
  15. End = (ulong)size + Start;
  16. }
  17. }
  18. private class MappedMemory : Range
  19. {
  20. public long PhysicalAddress { get; private set; }
  21. public bool VaAllocated { get; private set; }
  22. public MappedMemory(
  23. long position,
  24. long size,
  25. long physicalAddress,
  26. bool vaAllocated) : base(position, size)
  27. {
  28. PhysicalAddress = physicalAddress;
  29. VaAllocated = vaAllocated;
  30. }
  31. }
  32. private SortedList<long, Range> _maps;
  33. private SortedList<long, Range> _reservations;
  34. public NvGpuASCtx(ServiceCtx context)
  35. {
  36. Vmm = new NvGpuVmm(context.Memory);
  37. _maps = new SortedList<long, Range>();
  38. _reservations = new SortedList<long, Range>();
  39. }
  40. public bool ValidateFixedBuffer(long position, long size)
  41. {
  42. long mapEnd = position + size;
  43. //Check if size is valid (0 is also not allowed).
  44. if ((ulong)mapEnd <= (ulong)position)
  45. {
  46. return false;
  47. }
  48. //Check if address is page aligned.
  49. if ((position & NvGpuVmm.PageMask) != 0)
  50. {
  51. return false;
  52. }
  53. //Check if region is reserved.
  54. if (BinarySearch(_reservations, position) == null)
  55. {
  56. return false;
  57. }
  58. //Check for overlap with already mapped buffers.
  59. Range map = BinarySearchLt(_maps, mapEnd);
  60. if (map != null && map.End > (ulong)position)
  61. {
  62. return false;
  63. }
  64. return true;
  65. }
  66. public void AddMap(
  67. long position,
  68. long size,
  69. long physicalAddress,
  70. bool vaAllocated)
  71. {
  72. _maps.Add(position, new MappedMemory(position, size, physicalAddress, vaAllocated));
  73. }
  74. public bool RemoveMap(long position, out long size)
  75. {
  76. size = 0;
  77. if (_maps.Remove(position, out Range value))
  78. {
  79. MappedMemory map = (MappedMemory)value;
  80. if (map.VaAllocated)
  81. {
  82. size = (long)(map.End - map.Start);
  83. }
  84. return true;
  85. }
  86. return false;
  87. }
  88. public bool TryGetMapPhysicalAddress(long position, out long physicalAddress)
  89. {
  90. Range map = BinarySearch(_maps, position);
  91. if (map != null)
  92. {
  93. physicalAddress = ((MappedMemory)map).PhysicalAddress;
  94. return true;
  95. }
  96. physicalAddress = 0;
  97. return false;
  98. }
  99. public void AddReservation(long position, long size)
  100. {
  101. _reservations.Add(position, new Range(position, size));
  102. }
  103. public bool RemoveReservation(long position)
  104. {
  105. return _reservations.Remove(position);
  106. }
  107. private Range BinarySearch(SortedList<long, Range> lst, long position)
  108. {
  109. int left = 0;
  110. int right = lst.Count - 1;
  111. while (left <= right)
  112. {
  113. int size = right - left;
  114. int middle = left + (size >> 1);
  115. Range rg = lst.Values[middle];
  116. if ((ulong)position >= rg.Start && (ulong)position < rg.End)
  117. {
  118. return rg;
  119. }
  120. if ((ulong)position < rg.Start)
  121. {
  122. right = middle - 1;
  123. }
  124. else
  125. {
  126. left = middle + 1;
  127. }
  128. }
  129. return null;
  130. }
  131. private Range BinarySearchLt(SortedList<long, Range> lst, long position)
  132. {
  133. Range ltRg = null;
  134. int left = 0;
  135. int right = lst.Count - 1;
  136. while (left <= right)
  137. {
  138. int size = right - left;
  139. int middle = left + (size >> 1);
  140. Range rg = lst.Values[middle];
  141. if ((ulong)position < rg.Start)
  142. {
  143. right = middle - 1;
  144. }
  145. else
  146. {
  147. left = middle + 1;
  148. if ((ulong)position > rg.Start)
  149. {
  150. ltRg = rg;
  151. }
  152. }
  153. }
  154. return ltRg;
  155. }
  156. }
  157. }