NvGpuVmm.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. using ChocolArm64.Memory;
  2. using Ryujinx.Graphics.Gal;
  3. using System;
  4. namespace Ryujinx.Graphics.Memory
  5. {
  6. public class NvGpuVmm : IAMemory, IGalMemory
  7. {
  8. public const long AddrSize = 1L << 40;
  9. private const int PTLvl0Bits = 14;
  10. private const int PTLvl1Bits = 14;
  11. private const int PTPageBits = 12;
  12. private const int PTLvl0Size = 1 << PTLvl0Bits;
  13. private const int PTLvl1Size = 1 << PTLvl1Bits;
  14. public const int PageSize = 1 << PTPageBits;
  15. private const int PTLvl0Mask = PTLvl0Size - 1;
  16. private const int PTLvl1Mask = PTLvl1Size - 1;
  17. public const int PageMask = PageSize - 1;
  18. private const int PTLvl0Bit = PTPageBits + PTLvl1Bits;
  19. private const int PTLvl1Bit = PTPageBits;
  20. public AMemory Memory { get; private set; }
  21. private NvGpuVmmCache Cache;
  22. private const long PteUnmapped = -1;
  23. private const long PteReserved = -2;
  24. private long[][] PageTable;
  25. public NvGpuVmm(AMemory Memory)
  26. {
  27. this.Memory = Memory;
  28. Cache = new NvGpuVmmCache();
  29. PageTable = new long[PTLvl0Size][];
  30. }
  31. public long Map(long PA, long VA, long Size)
  32. {
  33. lock (PageTable)
  34. {
  35. for (long Offset = 0; Offset < Size; Offset += PageSize)
  36. {
  37. SetPte(VA + Offset, PA + Offset);
  38. }
  39. }
  40. return VA;
  41. }
  42. public long Map(long PA, long Size)
  43. {
  44. lock (PageTable)
  45. {
  46. long VA = GetFreePosition(Size);
  47. if (VA != -1)
  48. {
  49. for (long Offset = 0; Offset < Size; Offset += PageSize)
  50. {
  51. SetPte(VA + Offset, PA + Offset);
  52. }
  53. }
  54. return VA;
  55. }
  56. }
  57. public long ReserveFixed(long VA, long Size)
  58. {
  59. lock (PageTable)
  60. {
  61. for (long Offset = 0; Offset < Size; Offset += PageSize)
  62. {
  63. if (IsPageInUse(VA + Offset))
  64. {
  65. return -1;
  66. }
  67. }
  68. for (long Offset = 0; Offset < Size; Offset += PageSize)
  69. {
  70. SetPte(VA + Offset, PteReserved);
  71. }
  72. }
  73. return VA;
  74. }
  75. public long Reserve(long Size, long Align)
  76. {
  77. lock (PageTable)
  78. {
  79. long Position = GetFreePosition(Size, Align);
  80. if (Position != -1)
  81. {
  82. for (long Offset = 0; Offset < Size; Offset += PageSize)
  83. {
  84. SetPte(Position + Offset, PteReserved);
  85. }
  86. }
  87. return Position;
  88. }
  89. }
  90. public void Free(long VA, long Size)
  91. {
  92. lock (PageTable)
  93. {
  94. for (long Offset = 0; Offset < Size; Offset += PageSize)
  95. {
  96. SetPte(VA + Offset, PteUnmapped);
  97. }
  98. }
  99. }
  100. private long GetFreePosition(long Size, long Align = 1)
  101. {
  102. //Note: Address 0 is not considered valid by the driver,
  103. //when 0 is returned it's considered a mapping error.
  104. long Position = PageSize;
  105. long FreeSize = 0;
  106. if (Align < 1)
  107. {
  108. Align = 1;
  109. }
  110. Align = (Align + PageMask) & ~PageMask;
  111. while (Position + FreeSize < AddrSize)
  112. {
  113. if (!IsPageInUse(Position + FreeSize))
  114. {
  115. FreeSize += PageSize;
  116. if (FreeSize >= Size)
  117. {
  118. return Position;
  119. }
  120. }
  121. else
  122. {
  123. Position += FreeSize + PageSize;
  124. FreeSize = 0;
  125. long Remainder = Position % Align;
  126. if (Remainder != 0)
  127. {
  128. Position = (Position - Remainder) + Align;
  129. }
  130. }
  131. }
  132. return -1;
  133. }
  134. public long GetPhysicalAddress(long VA)
  135. {
  136. long BasePos = GetPte(VA);
  137. if (BasePos < 0)
  138. {
  139. return -1;
  140. }
  141. return BasePos + (VA & PageMask);
  142. }
  143. public bool IsRegionFree(long VA, long Size)
  144. {
  145. for (long Offset = 0; Offset < Size; Offset += PageSize)
  146. {
  147. if (IsPageInUse(VA + Offset))
  148. {
  149. return false;
  150. }
  151. }
  152. return true;
  153. }
  154. private bool IsPageInUse(long VA)
  155. {
  156. if (VA >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
  157. {
  158. return false;
  159. }
  160. long L0 = (VA >> PTLvl0Bit) & PTLvl0Mask;
  161. long L1 = (VA >> PTLvl1Bit) & PTLvl1Mask;
  162. if (PageTable[L0] == null)
  163. {
  164. return false;
  165. }
  166. return PageTable[L0][L1] != PteUnmapped;
  167. }
  168. private long GetPte(long Position)
  169. {
  170. long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
  171. long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
  172. if (PageTable[L0] == null)
  173. {
  174. return -1;
  175. }
  176. return PageTable[L0][L1];
  177. }
  178. private void SetPte(long Position, long TgtAddr)
  179. {
  180. long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
  181. long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
  182. if (PageTable[L0] == null)
  183. {
  184. PageTable[L0] = new long[PTLvl1Size];
  185. for (int Index = 0; Index < PTLvl1Size; Index++)
  186. {
  187. PageTable[L0][Index] = PteUnmapped;
  188. }
  189. }
  190. PageTable[L0][L1] = TgtAddr;
  191. }
  192. public bool IsRegionModified(long PA, long Size, NvGpuBufferType BufferType)
  193. {
  194. return Cache.IsRegionModified(Memory, BufferType, PA, Size);
  195. }
  196. public IntPtr GetHostAddress(long Position, long Size)
  197. {
  198. return Memory.GetHostAddress(GetPhysicalAddress(Position), Size);
  199. }
  200. public byte ReadByte(long Position)
  201. {
  202. Position = GetPhysicalAddress(Position);
  203. return Memory.ReadByte(Position);
  204. }
  205. public ushort ReadUInt16(long Position)
  206. {
  207. Position = GetPhysicalAddress(Position);
  208. return Memory.ReadUInt16(Position);
  209. }
  210. public uint ReadUInt32(long Position)
  211. {
  212. Position = GetPhysicalAddress(Position);
  213. return Memory.ReadUInt32(Position);
  214. }
  215. public ulong ReadUInt64(long Position)
  216. {
  217. Position = GetPhysicalAddress(Position);
  218. return Memory.ReadUInt64(Position);
  219. }
  220. public sbyte ReadSByte(long Position)
  221. {
  222. Position = GetPhysicalAddress(Position);
  223. return Memory.ReadSByte(Position);
  224. }
  225. public short ReadInt16(long Position)
  226. {
  227. Position = GetPhysicalAddress(Position);
  228. return Memory.ReadInt16(Position);
  229. }
  230. public int ReadInt32(long Position)
  231. {
  232. Position = GetPhysicalAddress(Position);
  233. return Memory.ReadInt32(Position);
  234. }
  235. public long ReadInt64(long Position)
  236. {
  237. Position = GetPhysicalAddress(Position);
  238. return Memory.ReadInt64(Position);
  239. }
  240. public byte[] ReadBytes(long Position, long Size)
  241. {
  242. Position = GetPhysicalAddress(Position);
  243. return Memory.ReadBytes(Position, Size);
  244. }
  245. public void WriteByte(long Position, byte Value)
  246. {
  247. Position = GetPhysicalAddress(Position);
  248. Memory.WriteByte(Position, Value);
  249. }
  250. public void WriteUInt16(long Position, ushort Value)
  251. {
  252. Position = GetPhysicalAddress(Position);
  253. Memory.WriteUInt16(Position, Value);
  254. }
  255. public void WriteUInt32(long Position, uint Value)
  256. {
  257. Position = GetPhysicalAddress(Position);
  258. Memory.WriteUInt32(Position, Value);
  259. }
  260. public void WriteUInt64(long Position, ulong Value)
  261. {
  262. Position = GetPhysicalAddress(Position);
  263. Memory.WriteUInt64(Position, Value);
  264. }
  265. public void WriteSByte(long Position, sbyte Value)
  266. {
  267. Position = GetPhysicalAddress(Position);
  268. Memory.WriteSByte(Position, Value);
  269. }
  270. public void WriteInt16(long Position, short Value)
  271. {
  272. Position = GetPhysicalAddress(Position);
  273. Memory.WriteInt16(Position, Value);
  274. }
  275. public void WriteInt32(long Position, int Value)
  276. {
  277. Position = GetPhysicalAddress(Position);
  278. Memory.WriteInt32(Position, Value);
  279. }
  280. public void WriteInt64(long Position, long Value)
  281. {
  282. Position = GetPhysicalAddress(Position);
  283. Memory.WriteInt64(Position, Value);
  284. }
  285. public void WriteBytes(long Position, byte[] Data)
  286. {
  287. Position = GetPhysicalAddress(Position);
  288. Memory.WriteBytes(Position, Data);
  289. }
  290. }
  291. }