SvcSystem.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. using ChocolArm64.Memory;
  2. using ChocolArm64.State;
  3. using Ryujinx.HLE.Exceptions;
  4. using Ryujinx.HLE.HOS.Ipc;
  5. using Ryujinx.HLE.HOS.Services;
  6. using Ryujinx.HLE.Logging;
  7. using System;
  8. using System.Threading;
  9. using static Ryujinx.HLE.HOS.ErrorCode;
  10. namespace Ryujinx.HLE.HOS.Kernel
  11. {
  12. partial class SvcHandler
  13. {
  14. private const int AllowedCpuIdBitmask = 0b1111;
  15. private const bool EnableProcessDebugging = false;
  16. private void SvcExitProcess(AThreadState ThreadState)
  17. {
  18. Device.System.ExitProcess(Process.ProcessId);
  19. }
  20. private void SvcClearEvent(AThreadState ThreadState)
  21. {
  22. int Handle = (int)ThreadState.X0;
  23. //TODO: Implement events.
  24. ThreadState.X0 = 0;
  25. }
  26. private void SvcCloseHandle(AThreadState ThreadState)
  27. {
  28. int Handle = (int)ThreadState.X0;
  29. object Obj = Process.HandleTable.CloseHandle(Handle);
  30. if (Obj == null)
  31. {
  32. Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!");
  33. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  34. return;
  35. }
  36. if (Obj is KSession Session)
  37. {
  38. Session.Dispose();
  39. }
  40. else if (Obj is KTransferMemory TransferMemory)
  41. {
  42. Process.MemoryManager.ResetTransferMemory(
  43. TransferMemory.Position,
  44. TransferMemory.Size);
  45. }
  46. ThreadState.X0 = 0;
  47. }
  48. private void SvcResetSignal(AThreadState ThreadState)
  49. {
  50. int Handle = (int)ThreadState.X0;
  51. KEvent Event = Process.HandleTable.GetData<KEvent>(Handle);
  52. if (Event != null)
  53. {
  54. Event.Reset();
  55. ThreadState.X0 = 0;
  56. }
  57. else
  58. {
  59. Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid event handle 0x{Handle:x8}!");
  60. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  61. }
  62. }
  63. private void SvcGetSystemTick(AThreadState ThreadState)
  64. {
  65. ThreadState.X0 = ThreadState.CntpctEl0;
  66. }
  67. private void SvcConnectToNamedPort(AThreadState ThreadState)
  68. {
  69. long StackPtr = (long)ThreadState.X0;
  70. long NamePtr = (long)ThreadState.X1;
  71. string Name = AMemoryHelper.ReadAsciiString(Memory, NamePtr, 8);
  72. //TODO: Validate that app has perms to access the service, and that the service
  73. //actually exists, return error codes otherwise.
  74. KSession Session = new KSession(ServiceFactory.MakeService(System, Name), Name);
  75. ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
  76. ThreadState.X0 = 0;
  77. ThreadState.X1 = Handle;
  78. }
  79. private void SvcSendSyncRequest(AThreadState ThreadState)
  80. {
  81. SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0);
  82. }
  83. private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState)
  84. {
  85. SendSyncRequest(
  86. ThreadState,
  87. (long)ThreadState.X0,
  88. (long)ThreadState.X1,
  89. (int)ThreadState.X2);
  90. }
  91. private void SendSyncRequest(AThreadState ThreadState, long MessagePtr, long Size, int Handle)
  92. {
  93. KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
  94. byte[] MessageData = Memory.ReadBytes(MessagePtr, Size);
  95. KSession Session = Process.HandleTable.GetData<KSession>(Handle);
  96. if (Session != null)
  97. {
  98. //Process.Scheduler.Suspend(CurrThread);
  99. System.CriticalSectionLock.Lock();
  100. KThread CurrentThread = System.Scheduler.GetCurrentThread();
  101. CurrentThread.SignaledObj = null;
  102. CurrentThread.ObjSyncResult = 0;
  103. CurrentThread.Reschedule(ThreadSchedState.Paused);
  104. IpcMessage Message = new IpcMessage(MessageData, MessagePtr);
  105. ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
  106. CurrentThread,
  107. Session,
  108. Message,
  109. MessagePtr));
  110. System.CriticalSectionLock.Unlock();
  111. ThreadState.X0 = (ulong)CurrentThread.ObjSyncResult;
  112. }
  113. else
  114. {
  115. Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{Handle:x8}!");
  116. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  117. }
  118. }
  119. private void ProcessIpcRequest(object State)
  120. {
  121. HleIpcMessage IpcMessage = (HleIpcMessage)State;
  122. IpcMessage.Thread.ObjSyncResult = (int)IpcHandler.IpcCall(
  123. Device,
  124. Process,
  125. Memory,
  126. IpcMessage.Session,
  127. IpcMessage.Message,
  128. IpcMessage.MessagePtr);
  129. IpcMessage.Thread.Reschedule(ThreadSchedState.Running);
  130. }
  131. private void SvcBreak(AThreadState ThreadState)
  132. {
  133. long Reason = (long)ThreadState.X0;
  134. long Unknown = (long)ThreadState.X1;
  135. long Info = (long)ThreadState.X2;
  136. Process.PrintStackTrace(ThreadState);
  137. throw new GuestBrokeExecutionException();
  138. }
  139. private void SvcOutputDebugString(AThreadState ThreadState)
  140. {
  141. long Position = (long)ThreadState.X0;
  142. long Size = (long)ThreadState.X1;
  143. string Str = AMemoryHelper.ReadAsciiString(Memory, Position, Size);
  144. Device.Log.PrintWarning(LogClass.KernelSvc, Str);
  145. ThreadState.X0 = 0;
  146. }
  147. private void SvcGetInfo(AThreadState ThreadState)
  148. {
  149. long StackPtr = (long)ThreadState.X0;
  150. int InfoType = (int)ThreadState.X1;
  151. long Handle = (long)ThreadState.X2;
  152. int InfoId = (int)ThreadState.X3;
  153. //Fail for info not available on older Kernel versions.
  154. if (InfoType == 18 ||
  155. InfoType == 19 ||
  156. InfoType == 20 ||
  157. InfoType == 21)
  158. {
  159. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
  160. return;
  161. }
  162. switch (InfoType)
  163. {
  164. case 0:
  165. ThreadState.X1 = AllowedCpuIdBitmask;
  166. break;
  167. case 2:
  168. ThreadState.X1 = (ulong)Process.MemoryManager.MapRegionStart;
  169. break;
  170. case 3:
  171. ThreadState.X1 = (ulong)Process.MemoryManager.MapRegionEnd -
  172. (ulong)Process.MemoryManager.MapRegionStart;
  173. break;
  174. case 4:
  175. ThreadState.X1 = (ulong)Process.MemoryManager.HeapRegionStart;
  176. break;
  177. case 5:
  178. ThreadState.X1 = (ulong)Process.MemoryManager.HeapRegionEnd -
  179. (ulong)Process.MemoryManager.HeapRegionStart;
  180. break;
  181. case 6:
  182. ThreadState.X1 = (ulong)Process.Device.Memory.Allocator.TotalAvailableSize;
  183. break;
  184. case 7:
  185. ThreadState.X1 = (ulong)Process.Device.Memory.Allocator.TotalUsedSize;
  186. break;
  187. case 8:
  188. ThreadState.X1 = EnableProcessDebugging ? 1 : 0;
  189. break;
  190. case 11:
  191. ThreadState.X1 = (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
  192. break;
  193. case 12:
  194. ThreadState.X1 = (ulong)Process.MemoryManager.AddrSpaceStart;
  195. break;
  196. case 13:
  197. ThreadState.X1 = (ulong)Process.MemoryManager.AddrSpaceEnd -
  198. (ulong)Process.MemoryManager.AddrSpaceStart;
  199. break;
  200. case 14:
  201. ThreadState.X1 = (ulong)Process.MemoryManager.NewMapRegionStart;
  202. break;
  203. case 15:
  204. ThreadState.X1 = (ulong)Process.MemoryManager.NewMapRegionEnd -
  205. (ulong)Process.MemoryManager.NewMapRegionStart;
  206. break;
  207. case 16:
  208. ThreadState.X1 = (ulong)(Process.MetaData?.SystemResourceSize ?? 0);
  209. break;
  210. case 17:
  211. ThreadState.X1 = (ulong)Process.MemoryManager.PersonalMmHeapUsage;
  212. break;
  213. default:
  214. Process.PrintStackTrace(ThreadState);
  215. throw new NotImplementedException($"SvcGetInfo: {InfoType} 0x{Handle:x8} {InfoId}");
  216. }
  217. ThreadState.X0 = 0;
  218. }
  219. }
  220. }