SvcThread.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. using ChocolArm64.State;
  2. using Ryujinx.Common.Logging;
  3. using static Ryujinx.HLE.HOS.ErrorCode;
  4. namespace Ryujinx.HLE.HOS.Kernel
  5. {
  6. partial class SvcHandler
  7. {
  8. private void CreateThread64(CpuThreadState ThreadState)
  9. {
  10. ulong Entrypoint = ThreadState.X1;
  11. ulong ArgsPtr = ThreadState.X2;
  12. ulong StackTop = ThreadState.X3;
  13. int Priority = (int)ThreadState.X4;
  14. int CpuCore = (int)ThreadState.X5;
  15. KernelResult Result = CreateThread(Entrypoint, ArgsPtr, StackTop, Priority, CpuCore, out int Handle);
  16. ThreadState.X0 = (ulong)Result;
  17. ThreadState.X1 = (ulong)Handle;
  18. }
  19. private KernelResult CreateThread(
  20. ulong Entrypoint,
  21. ulong ArgsPtr,
  22. ulong StackTop,
  23. int Priority,
  24. int CpuCore,
  25. out int Handle)
  26. {
  27. Handle = 0;
  28. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  29. if (CpuCore == -2)
  30. {
  31. CpuCore = CurrentProcess.DefaultCpuCore;
  32. }
  33. if ((uint)CpuCore >= KScheduler.CpuCoresCount || !CurrentProcess.IsCpuCoreAllowed(CpuCore))
  34. {
  35. return KernelResult.InvalidCpuCore;
  36. }
  37. if ((uint)Priority >= KScheduler.PrioritiesCount || !CurrentProcess.IsPriorityAllowed(Priority))
  38. {
  39. return KernelResult.InvalidPriority;
  40. }
  41. long Timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100);
  42. if (CurrentProcess.ResourceLimit != null &&
  43. !CurrentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, Timeout))
  44. {
  45. return KernelResult.ResLimitExceeded;
  46. }
  47. KThread Thread = new KThread(System);
  48. KernelResult Result = CurrentProcess.InitializeThread(
  49. Thread,
  50. Entrypoint,
  51. ArgsPtr,
  52. StackTop,
  53. Priority,
  54. CpuCore);
  55. if (Result != KernelResult.Success)
  56. {
  57. CurrentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
  58. return Result;
  59. }
  60. Result = Process.HandleTable.GenerateHandle(Thread, out Handle);
  61. if (Result != KernelResult.Success)
  62. {
  63. Thread.Terminate();
  64. CurrentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
  65. }
  66. return Result;
  67. }
  68. private void SvcStartThread(CpuThreadState ThreadState)
  69. {
  70. int Handle = (int)ThreadState.X0;
  71. KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
  72. if (Thread != null)
  73. {
  74. KernelResult Result = Thread.Start();
  75. if (Result != KernelResult.Success)
  76. {
  77. Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{Result}\".");
  78. }
  79. ThreadState.X0 = (ulong)Result;
  80. }
  81. else
  82. {
  83. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
  84. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  85. }
  86. }
  87. private void SvcExitThread(CpuThreadState ThreadState)
  88. {
  89. KThread CurrentThread = System.Scheduler.GetCurrentThread();
  90. System.Scheduler.ExitThread(CurrentThread);
  91. CurrentThread.Exit();
  92. }
  93. private void SvcSleepThread(CpuThreadState ThreadState)
  94. {
  95. long Timeout = (long)ThreadState.X0;
  96. Logger.PrintDebug(LogClass.KernelSvc, "Timeout = 0x" + Timeout.ToString("x16"));
  97. KThread CurrentThread = System.Scheduler.GetCurrentThread();
  98. if (Timeout < 1)
  99. {
  100. switch (Timeout)
  101. {
  102. case 0: CurrentThread.Yield(); break;
  103. case -1: CurrentThread.YieldWithLoadBalancing(); break;
  104. case -2: CurrentThread.YieldAndWaitForLoadBalancing(); break;
  105. }
  106. }
  107. else
  108. {
  109. CurrentThread.Sleep(Timeout);
  110. ThreadState.X0 = 0;
  111. }
  112. }
  113. private void SvcGetThreadPriority(CpuThreadState ThreadState)
  114. {
  115. int Handle = (int)ThreadState.X1;
  116. KThread Thread = Process.HandleTable.GetKThread(Handle);
  117. if (Thread != null)
  118. {
  119. ThreadState.X0 = 0;
  120. ThreadState.X1 = (ulong)Thread.DynamicPriority;
  121. }
  122. else
  123. {
  124. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
  125. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  126. }
  127. }
  128. private void SvcSetThreadPriority(CpuThreadState ThreadState)
  129. {
  130. int Handle = (int)ThreadState.X0;
  131. int Priority = (int)ThreadState.X1;
  132. Logger.PrintDebug(LogClass.KernelSvc,
  133. "Handle = 0x" + Handle .ToString("x8") + ", " +
  134. "Priority = 0x" + Priority.ToString("x8"));
  135. //TODO: NPDM check.
  136. KThread Thread = Process.HandleTable.GetKThread(Handle);
  137. if (Thread == null)
  138. {
  139. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
  140. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  141. return;
  142. }
  143. Thread.SetPriority(Priority);
  144. ThreadState.X0 = 0;
  145. }
  146. private void SvcGetThreadCoreMask(CpuThreadState ThreadState)
  147. {
  148. int Handle = (int)ThreadState.X2;
  149. Logger.PrintDebug(LogClass.KernelSvc, "Handle = 0x" + Handle.ToString("x8"));
  150. KThread Thread = Process.HandleTable.GetKThread(Handle);
  151. if (Thread != null)
  152. {
  153. ThreadState.X0 = 0;
  154. ThreadState.X1 = (ulong)Thread.PreferredCore;
  155. ThreadState.X2 = (ulong)Thread.AffinityMask;
  156. }
  157. else
  158. {
  159. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
  160. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  161. }
  162. }
  163. private void SetThreadCoreMask64(CpuThreadState ThreadState)
  164. {
  165. int Handle = (int)ThreadState.X0;
  166. int PreferredCore = (int)ThreadState.X1;
  167. long AffinityMask = (long)ThreadState.X2;
  168. Logger.PrintDebug(LogClass.KernelSvc,
  169. "Handle = 0x" + Handle .ToString("x8") + ", " +
  170. "PreferredCore = 0x" + PreferredCore.ToString("x8") + ", " +
  171. "AffinityMask = 0x" + AffinityMask .ToString("x16"));
  172. KernelResult Result = SetThreadCoreMask(Handle, PreferredCore, AffinityMask);
  173. if (Result != KernelResult.Success)
  174. {
  175. Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error \"{Result}\".");
  176. }
  177. ThreadState.X0 = (ulong)Result;
  178. }
  179. private KernelResult SetThreadCoreMask(int Handle, int PreferredCore, long AffinityMask)
  180. {
  181. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  182. if (PreferredCore == -2)
  183. {
  184. PreferredCore = CurrentProcess.DefaultCpuCore;
  185. AffinityMask = 1 << PreferredCore;
  186. }
  187. else
  188. {
  189. if ((CurrentProcess.Capabilities.AllowedCpuCoresMask | AffinityMask) !=
  190. CurrentProcess.Capabilities.AllowedCpuCoresMask)
  191. {
  192. return KernelResult.InvalidCpuCore;
  193. }
  194. if (AffinityMask == 0)
  195. {
  196. return KernelResult.InvalidCombination;
  197. }
  198. if ((uint)PreferredCore > 3)
  199. {
  200. if ((PreferredCore | 2) != -1)
  201. {
  202. return KernelResult.InvalidCpuCore;
  203. }
  204. }
  205. else if ((AffinityMask & (1 << PreferredCore)) == 0)
  206. {
  207. return KernelResult.InvalidCombination;
  208. }
  209. }
  210. KThread Thread = Process.HandleTable.GetKThread(Handle);
  211. if (Thread == null)
  212. {
  213. return KernelResult.InvalidHandle;
  214. }
  215. return Thread.SetCoreAndAffinityMask(PreferredCore, AffinityMask);
  216. }
  217. private void SvcGetCurrentProcessorNumber(CpuThreadState ThreadState)
  218. {
  219. ThreadState.X0 = (ulong)System.Scheduler.GetCurrentThread().CurrentCore;
  220. }
  221. private void SvcGetThreadId(CpuThreadState ThreadState)
  222. {
  223. int Handle = (int)ThreadState.X1;
  224. KThread Thread = Process.HandleTable.GetKThread(Handle);
  225. if (Thread != null)
  226. {
  227. ThreadState.X0 = 0;
  228. ThreadState.X1 = (ulong)Thread.ThreadUid;
  229. }
  230. else
  231. {
  232. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
  233. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  234. }
  235. }
  236. private void SvcSetThreadActivity(CpuThreadState ThreadState)
  237. {
  238. int Handle = (int)ThreadState.X0;
  239. bool Pause = (int)ThreadState.X1 == 1;
  240. KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
  241. if (Thread == null)
  242. {
  243. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
  244. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  245. return;
  246. }
  247. if (Thread.Owner != System.Scheduler.GetCurrentProcess())
  248. {
  249. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread, it belongs to another process.");
  250. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  251. return;
  252. }
  253. if (Thread == System.Scheduler.GetCurrentThread())
  254. {
  255. Logger.PrintWarning(LogClass.KernelSvc, "Invalid thread, current thread is not accepted.");
  256. ThreadState.X0 = (ulong)KernelResult.InvalidThread;
  257. return;
  258. }
  259. long Result = Thread.SetActivity(Pause);
  260. if (Result != 0)
  261. {
  262. Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!");
  263. }
  264. ThreadState.X0 = (ulong)Result;
  265. }
  266. private void SvcGetThreadContext3(CpuThreadState ThreadState)
  267. {
  268. long Position = (long)ThreadState.X0;
  269. int Handle = (int)ThreadState.X1;
  270. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  271. KThread CurrentThread = System.Scheduler.GetCurrentThread();
  272. KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
  273. if (Thread == null)
  274. {
  275. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
  276. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  277. return;
  278. }
  279. if (Thread.Owner != CurrentProcess)
  280. {
  281. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread, it belongs to another process.");
  282. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  283. return;
  284. }
  285. if (CurrentThread == Thread)
  286. {
  287. Logger.PrintWarning(LogClass.KernelSvc, "Invalid thread, current thread is not accepted.");
  288. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread);
  289. return;
  290. }
  291. Memory.WriteUInt64(Position + 0x0, Thread.Context.ThreadState.X0);
  292. Memory.WriteUInt64(Position + 0x8, Thread.Context.ThreadState.X1);
  293. Memory.WriteUInt64(Position + 0x10, Thread.Context.ThreadState.X2);
  294. Memory.WriteUInt64(Position + 0x18, Thread.Context.ThreadState.X3);
  295. Memory.WriteUInt64(Position + 0x20, Thread.Context.ThreadState.X4);
  296. Memory.WriteUInt64(Position + 0x28, Thread.Context.ThreadState.X5);
  297. Memory.WriteUInt64(Position + 0x30, Thread.Context.ThreadState.X6);
  298. Memory.WriteUInt64(Position + 0x38, Thread.Context.ThreadState.X7);
  299. Memory.WriteUInt64(Position + 0x40, Thread.Context.ThreadState.X8);
  300. Memory.WriteUInt64(Position + 0x48, Thread.Context.ThreadState.X9);
  301. Memory.WriteUInt64(Position + 0x50, Thread.Context.ThreadState.X10);
  302. Memory.WriteUInt64(Position + 0x58, Thread.Context.ThreadState.X11);
  303. Memory.WriteUInt64(Position + 0x60, Thread.Context.ThreadState.X12);
  304. Memory.WriteUInt64(Position + 0x68, Thread.Context.ThreadState.X13);
  305. Memory.WriteUInt64(Position + 0x70, Thread.Context.ThreadState.X14);
  306. Memory.WriteUInt64(Position + 0x78, Thread.Context.ThreadState.X15);
  307. Memory.WriteUInt64(Position + 0x80, Thread.Context.ThreadState.X16);
  308. Memory.WriteUInt64(Position + 0x88, Thread.Context.ThreadState.X17);
  309. Memory.WriteUInt64(Position + 0x90, Thread.Context.ThreadState.X18);
  310. Memory.WriteUInt64(Position + 0x98, Thread.Context.ThreadState.X19);
  311. Memory.WriteUInt64(Position + 0xa0, Thread.Context.ThreadState.X20);
  312. Memory.WriteUInt64(Position + 0xa8, Thread.Context.ThreadState.X21);
  313. Memory.WriteUInt64(Position + 0xb0, Thread.Context.ThreadState.X22);
  314. Memory.WriteUInt64(Position + 0xb8, Thread.Context.ThreadState.X23);
  315. Memory.WriteUInt64(Position + 0xc0, Thread.Context.ThreadState.X24);
  316. Memory.WriteUInt64(Position + 0xc8, Thread.Context.ThreadState.X25);
  317. Memory.WriteUInt64(Position + 0xd0, Thread.Context.ThreadState.X26);
  318. Memory.WriteUInt64(Position + 0xd8, Thread.Context.ThreadState.X27);
  319. Memory.WriteUInt64(Position + 0xe0, Thread.Context.ThreadState.X28);
  320. Memory.WriteUInt64(Position + 0xe8, Thread.Context.ThreadState.X29);
  321. Memory.WriteUInt64(Position + 0xf0, Thread.Context.ThreadState.X30);
  322. Memory.WriteUInt64(Position + 0xf8, Thread.Context.ThreadState.X31);
  323. Memory.WriteInt64(Position + 0x100, Thread.LastPc);
  324. Memory.WriteUInt64(Position + 0x108, (ulong)Thread.Context.ThreadState.Psr);
  325. Memory.WriteVector128(Position + 0x110, Thread.Context.ThreadState.V0);
  326. Memory.WriteVector128(Position + 0x120, Thread.Context.ThreadState.V1);
  327. Memory.WriteVector128(Position + 0x130, Thread.Context.ThreadState.V2);
  328. Memory.WriteVector128(Position + 0x140, Thread.Context.ThreadState.V3);
  329. Memory.WriteVector128(Position + 0x150, Thread.Context.ThreadState.V4);
  330. Memory.WriteVector128(Position + 0x160, Thread.Context.ThreadState.V5);
  331. Memory.WriteVector128(Position + 0x170, Thread.Context.ThreadState.V6);
  332. Memory.WriteVector128(Position + 0x180, Thread.Context.ThreadState.V7);
  333. Memory.WriteVector128(Position + 0x190, Thread.Context.ThreadState.V8);
  334. Memory.WriteVector128(Position + 0x1a0, Thread.Context.ThreadState.V9);
  335. Memory.WriteVector128(Position + 0x1b0, Thread.Context.ThreadState.V10);
  336. Memory.WriteVector128(Position + 0x1c0, Thread.Context.ThreadState.V11);
  337. Memory.WriteVector128(Position + 0x1d0, Thread.Context.ThreadState.V12);
  338. Memory.WriteVector128(Position + 0x1e0, Thread.Context.ThreadState.V13);
  339. Memory.WriteVector128(Position + 0x1f0, Thread.Context.ThreadState.V14);
  340. Memory.WriteVector128(Position + 0x200, Thread.Context.ThreadState.V15);
  341. Memory.WriteVector128(Position + 0x210, Thread.Context.ThreadState.V16);
  342. Memory.WriteVector128(Position + 0x220, Thread.Context.ThreadState.V17);
  343. Memory.WriteVector128(Position + 0x230, Thread.Context.ThreadState.V18);
  344. Memory.WriteVector128(Position + 0x240, Thread.Context.ThreadState.V19);
  345. Memory.WriteVector128(Position + 0x250, Thread.Context.ThreadState.V20);
  346. Memory.WriteVector128(Position + 0x260, Thread.Context.ThreadState.V21);
  347. Memory.WriteVector128(Position + 0x270, Thread.Context.ThreadState.V22);
  348. Memory.WriteVector128(Position + 0x280, Thread.Context.ThreadState.V23);
  349. Memory.WriteVector128(Position + 0x290, Thread.Context.ThreadState.V24);
  350. Memory.WriteVector128(Position + 0x2a0, Thread.Context.ThreadState.V25);
  351. Memory.WriteVector128(Position + 0x2b0, Thread.Context.ThreadState.V26);
  352. Memory.WriteVector128(Position + 0x2c0, Thread.Context.ThreadState.V27);
  353. Memory.WriteVector128(Position + 0x2d0, Thread.Context.ThreadState.V28);
  354. Memory.WriteVector128(Position + 0x2e0, Thread.Context.ThreadState.V29);
  355. Memory.WriteVector128(Position + 0x2f0, Thread.Context.ThreadState.V30);
  356. Memory.WriteVector128(Position + 0x300, Thread.Context.ThreadState.V31);
  357. Memory.WriteInt32(Position + 0x310, Thread.Context.ThreadState.Fpcr);
  358. Memory.WriteInt32(Position + 0x314, Thread.Context.ThreadState.Fpsr);
  359. Memory.WriteInt64(Position + 0x318, Thread.Context.ThreadState.Tpidr);
  360. ThreadState.X0 = 0;
  361. }
  362. }
  363. }