SvcMemory.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. using ChocolArm64.Memory;
  2. using ChocolArm64.State;
  3. using Ryujinx.HLE.Logging;
  4. using Ryujinx.HLE.OsHle.Handles;
  5. using static Ryujinx.HLE.OsHle.ErrorCode;
  6. namespace Ryujinx.HLE.OsHle.Kernel
  7. {
  8. partial class SvcHandler
  9. {
  10. private void SvcSetHeapSize(AThreadState ThreadState)
  11. {
  12. uint Size = (uint)ThreadState.X1;
  13. long Position = MemoryRegions.HeapRegionAddress;
  14. if (Size > CurrentHeapSize)
  15. {
  16. Memory.Manager.Map(Position, Size, (int)MemoryType.Heap, AMemoryPerm.RW);
  17. }
  18. else
  19. {
  20. Memory.Manager.Unmap(Position + Size, (long)CurrentHeapSize - Size);
  21. }
  22. CurrentHeapSize = Size;
  23. ThreadState.X0 = 0;
  24. ThreadState.X1 = (ulong)Position;
  25. }
  26. private void SvcSetMemoryAttribute(AThreadState ThreadState)
  27. {
  28. long Position = (long)ThreadState.X0;
  29. long Size = (long)ThreadState.X1;
  30. int State0 = (int)ThreadState.X2;
  31. int State1 = (int)ThreadState.X3;
  32. if ((State0 == 0 && State1 == 0) ||
  33. (State0 == 8 && State1 == 0))
  34. {
  35. Memory.Manager.ClearAttrBit(Position, Size, 3);
  36. }
  37. else if (State0 == 8 && State1 == 8)
  38. {
  39. Memory.Manager.SetAttrBit(Position, Size, 3);
  40. }
  41. ThreadState.X0 = 0;
  42. }
  43. private void SvcMapMemory(AThreadState ThreadState)
  44. {
  45. long Dst = (long)ThreadState.X0;
  46. long Src = (long)ThreadState.X1;
  47. long Size = (long)ThreadState.X2;
  48. if (!IsValidPosition(Src))
  49. {
  50. Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid src address {Src:x16}!");
  51. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
  52. return;
  53. }
  54. if (!IsValidMapPosition(Dst))
  55. {
  56. Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid dst address {Dst:x16}!");
  57. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
  58. return;
  59. }
  60. AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src);
  61. Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm);
  62. Memory.Manager.Reprotect(Src, Size, AMemoryPerm.None);
  63. Memory.Manager.SetAttrBit(Src, Size, 0);
  64. ThreadState.X0 = 0;
  65. }
  66. private void SvcUnmapMemory(AThreadState ThreadState)
  67. {
  68. long Dst = (long)ThreadState.X0;
  69. long Src = (long)ThreadState.X1;
  70. long Size = (long)ThreadState.X2;
  71. if (!IsValidPosition(Src))
  72. {
  73. Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid src address {Src:x16}!");
  74. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
  75. return;
  76. }
  77. if (!IsValidMapPosition(Dst))
  78. {
  79. Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid dst address {Dst:x16}!");
  80. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
  81. return;
  82. }
  83. AMemoryMapInfo DstInfo = Memory.Manager.GetMapInfo(Dst);
  84. Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory);
  85. Memory.Manager.Reprotect(Src, Size, DstInfo.Perm);
  86. Memory.Manager.ClearAttrBit(Src, Size, 0);
  87. ThreadState.X0 = 0;
  88. }
  89. private void SvcQueryMemory(AThreadState ThreadState)
  90. {
  91. long InfoPtr = (long)ThreadState.X0;
  92. long Position = (long)ThreadState.X2;
  93. AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
  94. if (MapInfo == null)
  95. {
  96. long AddrSpaceEnd = MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize;
  97. long ReservedSize = (long)(ulong.MaxValue - (ulong)AddrSpaceEnd) + 1;
  98. MapInfo = new AMemoryMapInfo(AddrSpaceEnd, ReservedSize, (int)MemoryType.Reserved, 0, AMemoryPerm.None);
  99. }
  100. Memory.WriteInt64(InfoPtr + 0x00, MapInfo.Position);
  101. Memory.WriteInt64(InfoPtr + 0x08, MapInfo.Size);
  102. Memory.WriteInt32(InfoPtr + 0x10, MapInfo.Type);
  103. Memory.WriteInt32(InfoPtr + 0x14, MapInfo.Attr);
  104. Memory.WriteInt32(InfoPtr + 0x18, (int)MapInfo.Perm);
  105. Memory.WriteInt32(InfoPtr + 0x1c, 0);
  106. Memory.WriteInt32(InfoPtr + 0x20, 0);
  107. Memory.WriteInt32(InfoPtr + 0x24, 0);
  108. //TODO: X1.
  109. ThreadState.X0 = 0;
  110. ThreadState.X1 = 0;
  111. }
  112. private void SvcMapSharedMemory(AThreadState ThreadState)
  113. {
  114. int Handle = (int)ThreadState.X0;
  115. long Src = (long)ThreadState.X1;
  116. long Size = (long)ThreadState.X2;
  117. int Perm = (int)ThreadState.X3;
  118. if (!IsValidPosition(Src))
  119. {
  120. Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address {Src:x16}!");
  121. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
  122. return;
  123. }
  124. HSharedMem SharedMem = Process.HandleTable.GetData<HSharedMem>(Handle);
  125. if (SharedMem != null)
  126. {
  127. Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, AMemoryPerm.Write);
  128. AMemoryHelper.FillWithZeros(Memory, Src, (int)Size);
  129. Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm);
  130. lock (MappedSharedMems)
  131. {
  132. MappedSharedMems.Add((SharedMem, Src));
  133. }
  134. SharedMem.AddVirtualPosition(Memory, Src);
  135. ThreadState.X0 = 0;
  136. }
  137. //TODO: Error codes.
  138. }
  139. private void SvcUnmapSharedMemory(AThreadState ThreadState)
  140. {
  141. int Handle = (int)ThreadState.X0;
  142. long Src = (long)ThreadState.X1;
  143. long Size = (long)ThreadState.X2;
  144. if (!IsValidPosition(Src))
  145. {
  146. Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address {Src:x16}!");
  147. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
  148. return;
  149. }
  150. HSharedMem SharedMem = Process.HandleTable.GetData<HSharedMem>(Handle);
  151. if (SharedMem != null)
  152. {
  153. Memory.Manager.Unmap(Src, Size, (int)MemoryType.SharedMemory);
  154. SharedMem.RemoveVirtualPosition(Memory, Src);
  155. lock (MappedSharedMems)
  156. {
  157. MappedSharedMems.Remove((SharedMem, Src));
  158. }
  159. ThreadState.X0 = 0;
  160. }
  161. //TODO: Error codes.
  162. }
  163. private void SvcCreateTransferMemory(AThreadState ThreadState)
  164. {
  165. long Src = (long)ThreadState.X1;
  166. long Size = (long)ThreadState.X2;
  167. int Perm = (int)ThreadState.X3;
  168. if (!IsValidPosition(Src))
  169. {
  170. Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid address {Src:x16}!");
  171. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
  172. return;
  173. }
  174. AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Src);
  175. Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm);
  176. HTransferMem TMem = new HTransferMem(Memory, MapInfo.Perm, Src, Size);
  177. ulong Handle = (ulong)Process.HandleTable.OpenHandle(TMem);
  178. ThreadState.X0 = 0;
  179. ThreadState.X1 = Handle;
  180. }
  181. private void SvcMapPhysicalMemory(AThreadState ThreadState)
  182. {
  183. long Position = (long)ThreadState.X0;
  184. uint Size = (uint)ThreadState.X1;
  185. Memory.Manager.Map(Position, Size, (int)MemoryType.Heap, AMemoryPerm.RW);
  186. ThreadState.X0 = 0;
  187. }
  188. private void SvcUnmapPhysicalMemory(AThreadState ThreadState)
  189. {
  190. long Position = (long)ThreadState.X0;
  191. uint Size = (uint)ThreadState.X1;
  192. Memory.Manager.Unmap(Position, Size);
  193. ThreadState.X0 = 0;
  194. }
  195. private static bool IsValidPosition(long Position)
  196. {
  197. return Position >= MemoryRegions.AddrSpaceStart &&
  198. Position < MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize;
  199. }
  200. private static bool IsValidMapPosition(long Position)
  201. {
  202. return Position >= MemoryRegions.MapRegionAddress &&
  203. Position < MemoryRegions.MapRegionAddress + MemoryRegions.MapRegionSize;
  204. }
  205. }
  206. }