k_process.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. // SPDX-FileCopyrightText: 2015 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <cstddef>
  6. #include <list>
  7. #include <map>
  8. #include <string>
  9. #include "core/hle/kernel/k_address_arbiter.h"
  10. #include "core/hle/kernel/k_auto_object.h"
  11. #include "core/hle/kernel/k_condition_variable.h"
  12. #include "core/hle/kernel/k_handle_table.h"
  13. #include "core/hle/kernel/k_page_table.h"
  14. #include "core/hle/kernel/k_synchronization_object.h"
  15. #include "core/hle/kernel/k_thread_local_page.h"
  16. #include "core/hle/kernel/k_typed_address.h"
  17. #include "core/hle/kernel/k_worker_task.h"
  18. #include "core/hle/kernel/process_capability.h"
  19. #include "core/hle/kernel/slab_helpers.h"
  20. #include "core/hle/result.h"
  21. namespace Core {
  22. namespace Memory {
  23. class Memory;
  24. };
  25. class System;
  26. } // namespace Core
  27. namespace FileSys {
  28. class ProgramMetadata;
  29. }
  30. namespace Kernel {
  31. class KernelCore;
  32. class KResourceLimit;
  33. class KThread;
  34. class KSharedMemoryInfo;
  35. class TLSPage;
  36. struct CodeSet;
  37. enum class MemoryRegion : u16 {
  38. APPLICATION = 1,
  39. SYSTEM = 2,
  40. BASE = 3,
  41. };
  42. enum class ProcessActivity : u32 {
  43. Runnable,
  44. Paused,
  45. };
  46. enum class DebugWatchpointType : u8 {
  47. None = 0,
  48. Read = 1 << 0,
  49. Write = 1 << 1,
  50. ReadOrWrite = Read | Write,
  51. };
  52. DECLARE_ENUM_FLAG_OPERATORS(DebugWatchpointType);
  53. struct DebugWatchpoint {
  54. KProcessAddress start_address;
  55. KProcessAddress end_address;
  56. DebugWatchpointType type;
  57. };
  58. class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> {
  59. KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
  60. public:
  61. explicit KProcess(KernelCore& kernel);
  62. ~KProcess() override;
  63. enum class State {
  64. Created = static_cast<u32>(Svc::ProcessState::Created),
  65. CreatedAttached = static_cast<u32>(Svc::ProcessState::CreatedAttached),
  66. Running = static_cast<u32>(Svc::ProcessState::Running),
  67. Crashed = static_cast<u32>(Svc::ProcessState::Crashed),
  68. RunningAttached = static_cast<u32>(Svc::ProcessState::RunningAttached),
  69. Terminating = static_cast<u32>(Svc::ProcessState::Terminating),
  70. Terminated = static_cast<u32>(Svc::ProcessState::Terminated),
  71. DebugBreak = static_cast<u32>(Svc::ProcessState::DebugBreak),
  72. };
  73. enum : u64 {
  74. /// Lowest allowed process ID for a kernel initial process.
  75. InitialKIPIDMin = 1,
  76. /// Highest allowed process ID for a kernel initial process.
  77. InitialKIPIDMax = 80,
  78. /// Lowest allowed process ID for a userland process.
  79. ProcessIDMin = 81,
  80. /// Highest allowed process ID for a userland process.
  81. ProcessIDMax = 0xFFFFFFFFFFFFFFFF,
  82. };
  83. // Used to determine how process IDs are assigned.
  84. enum class ProcessType {
  85. KernelInternal,
  86. Userland,
  87. };
  88. static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
  89. static Result Initialize(KProcess* process, Core::System& system, std::string process_name,
  90. ProcessType type, KResourceLimit* res_limit);
  91. /// Gets a reference to the process' page table.
  92. KPageTable& GetPageTable() {
  93. return m_page_table;
  94. }
  95. /// Gets const a reference to the process' page table.
  96. const KPageTable& GetPageTable() const {
  97. return m_page_table;
  98. }
  99. /// Gets a reference to the process' handle table.
  100. KHandleTable& GetHandleTable() {
  101. return m_handle_table;
  102. }
  103. /// Gets a const reference to the process' handle table.
  104. const KHandleTable& GetHandleTable() const {
  105. return m_handle_table;
  106. }
  107. /// Gets a reference to process's memory.
  108. Core::Memory::Memory& GetMemory() const;
  109. Result SignalToAddress(KProcessAddress address) {
  110. return m_condition_var.SignalToAddress(address);
  111. }
  112. Result WaitForAddress(Handle handle, KProcessAddress address, u32 tag) {
  113. return m_condition_var.WaitForAddress(handle, address, tag);
  114. }
  115. void SignalConditionVariable(u64 cv_key, int32_t count) {
  116. return m_condition_var.Signal(cv_key, count);
  117. }
  118. Result WaitConditionVariable(KProcessAddress address, u64 cv_key, u32 tag, s64 ns) {
  119. R_RETURN(m_condition_var.Wait(address, cv_key, tag, ns));
  120. }
  121. Result SignalAddressArbiter(uint64_t address, Svc::SignalType signal_type, s32 value,
  122. s32 count) {
  123. R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count));
  124. }
  125. Result WaitAddressArbiter(uint64_t address, Svc::ArbitrationType arb_type, s32 value,
  126. s64 timeout) {
  127. R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout));
  128. }
  129. KProcessAddress GetProcessLocalRegionAddress() const {
  130. return m_plr_address;
  131. }
  132. /// Gets the current status of the process
  133. State GetState() const {
  134. return m_state;
  135. }
  136. /// Gets the unique ID that identifies this particular process.
  137. u64 GetProcessId() const {
  138. return m_process_id;
  139. }
  140. /// Gets the program ID corresponding to this process.
  141. u64 GetProgramId() const {
  142. return m_program_id;
  143. }
  144. KProcessAddress GetEntryPoint() const {
  145. return m_code_address;
  146. }
  147. /// Gets the resource limit descriptor for this process
  148. KResourceLimit* GetResourceLimit() const;
  149. /// Gets the ideal CPU core ID for this process
  150. u8 GetIdealCoreId() const {
  151. return m_ideal_core;
  152. }
  153. /// Checks if the specified thread priority is valid.
  154. bool CheckThreadPriority(s32 prio) const {
  155. return ((1ULL << prio) & GetPriorityMask()) != 0;
  156. }
  157. /// Gets the bitmask of allowed cores that this process' threads can run on.
  158. u64 GetCoreMask() const {
  159. return m_capabilities.GetCoreMask();
  160. }
  161. /// Gets the bitmask of allowed thread priorities.
  162. u64 GetPriorityMask() const {
  163. return m_capabilities.GetPriorityMask();
  164. }
  165. /// Gets the amount of secure memory to allocate for memory management.
  166. u32 GetSystemResourceSize() const {
  167. return m_system_resource_size;
  168. }
  169. /// Gets the amount of secure memory currently in use for memory management.
  170. u32 GetSystemResourceUsage() const {
  171. // On hardware, this returns the amount of system resource memory that has
  172. // been used by the kernel. This is problematic for Yuzu to emulate, because
  173. // system resource memory is used for page tables -- and yuzu doesn't really
  174. // have a way to calculate how much memory is required for page tables for
  175. // the current process at any given time.
  176. // TODO: Is this even worth implementing? Games may retrieve this value via
  177. // an SDK function that gets used + available system resource size for debug
  178. // or diagnostic purposes. However, it seems unlikely that a game would make
  179. // decisions based on how much system memory is dedicated to its page tables.
  180. // Is returning a value other than zero wise?
  181. return 0;
  182. }
  183. /// Whether this process is an AArch64 or AArch32 process.
  184. bool Is64BitProcess() const {
  185. return m_is_64bit_process;
  186. }
  187. bool IsSuspended() const {
  188. return m_is_suspended;
  189. }
  190. void SetSuspended(bool suspended) {
  191. m_is_suspended = suspended;
  192. }
  193. /// Gets the total running time of the process instance in ticks.
  194. u64 GetCPUTimeTicks() const {
  195. return m_total_process_running_time_ticks;
  196. }
  197. /// Updates the total running time, adding the given ticks to it.
  198. void UpdateCPUTimeTicks(u64 ticks) {
  199. m_total_process_running_time_ticks += ticks;
  200. }
  201. /// Gets the process schedule count, used for thread yielding
  202. s64 GetScheduledCount() const {
  203. return m_schedule_count;
  204. }
  205. /// Increments the process schedule count, used for thread yielding.
  206. void IncrementScheduledCount() {
  207. ++m_schedule_count;
  208. }
  209. void IncrementRunningThreadCount();
  210. void DecrementRunningThreadCount();
  211. void SetRunningThread(s32 core, KThread* thread, u64 idle_count) {
  212. m_running_threads[core] = thread;
  213. m_running_thread_idle_counts[core] = idle_count;
  214. }
  215. void ClearRunningThread(KThread* thread) {
  216. for (size_t i = 0; i < m_running_threads.size(); ++i) {
  217. if (m_running_threads[i] == thread) {
  218. m_running_threads[i] = nullptr;
  219. }
  220. }
  221. }
  222. [[nodiscard]] KThread* GetRunningThread(s32 core) const {
  223. return m_running_threads[core];
  224. }
  225. bool ReleaseUserException(KThread* thread);
  226. [[nodiscard]] KThread* GetPinnedThread(s32 core_id) const {
  227. ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
  228. return m_pinned_threads[core_id];
  229. }
  230. /// Gets 8 bytes of random data for svcGetInfo RandomEntropy
  231. u64 GetRandomEntropy(std::size_t index) const {
  232. return m_random_entropy.at(index);
  233. }
  234. /// Retrieves the total physical memory available to this process in bytes.
  235. u64 GetTotalPhysicalMemoryAvailable();
  236. /// Retrieves the total physical memory available to this process in bytes,
  237. /// without the size of the personal system resource heap added to it.
  238. u64 GetTotalPhysicalMemoryAvailableWithoutSystemResource();
  239. /// Retrieves the total physical memory used by this process in bytes.
  240. u64 GetTotalPhysicalMemoryUsed();
  241. /// Retrieves the total physical memory used by this process in bytes,
  242. /// without the size of the personal system resource heap added to it.
  243. u64 GetTotalPhysicalMemoryUsedWithoutSystemResource();
  244. /// Gets the list of all threads created with this process as their owner.
  245. std::list<KThread*>& GetThreadList() {
  246. return m_thread_list;
  247. }
  248. /// Registers a thread as being created under this process,
  249. /// adding it to this process' thread list.
  250. void RegisterThread(KThread* thread);
  251. /// Unregisters a thread from this process, removing it
  252. /// from this process' thread list.
  253. void UnregisterThread(KThread* thread);
  254. /// Retrieves the number of available threads for this process.
  255. u64 GetFreeThreadCount() const;
  256. /// Clears the signaled state of the process if and only if it's signaled.
  257. ///
  258. /// @pre The process must not be already terminated. If this is called on a
  259. /// terminated process, then ResultInvalidState will be returned.
  260. ///
  261. /// @pre The process must be in a signaled state. If this is called on a
  262. /// process instance that is not signaled, ResultInvalidState will be
  263. /// returned.
  264. Result Reset();
  265. /**
  266. * Loads process-specifics configuration info with metadata provided
  267. * by an executable.
  268. *
  269. * @param metadata The provided metadata to load process specific info from.
  270. *
  271. * @returns ResultSuccess if all relevant metadata was able to be
  272. * loaded and parsed. Otherwise, an error code is returned.
  273. */
  274. Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
  275. bool is_hbl);
  276. /**
  277. * Starts the main application thread for this process.
  278. *
  279. * @param main_thread_priority The priority for the main thread.
  280. * @param stack_size The stack size for the main thread in bytes.
  281. */
  282. void Run(s32 main_thread_priority, u64 stack_size);
  283. /**
  284. * Prepares a process for termination by stopping all of its threads
  285. * and clearing any other resources.
  286. */
  287. void PrepareForTermination();
  288. void LoadModule(CodeSet code_set, KProcessAddress base_addr);
  289. bool IsInitialized() const override {
  290. return m_is_initialized;
  291. }
  292. static void PostDestroy(uintptr_t arg) {}
  293. void Finalize() override;
  294. u64 GetId() const override {
  295. return GetProcessId();
  296. }
  297. bool IsHbl() const {
  298. return m_is_hbl;
  299. }
  300. bool IsSignaled() const override;
  301. void DoWorkerTaskImpl();
  302. Result SetActivity(ProcessActivity activity);
  303. void PinCurrentThread(s32 core_id);
  304. void UnpinCurrentThread(s32 core_id);
  305. void UnpinThread(KThread* thread);
  306. KLightLock& GetStateLock() {
  307. return m_state_lock;
  308. }
  309. Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
  310. void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
  311. ///////////////////////////////////////////////////////////////////////////////////////////////
  312. // Thread-local storage management
  313. // Marks the next available region as used and returns the address of the slot.
  314. [[nodiscard]] Result CreateThreadLocalRegion(KProcessAddress* out);
  315. // Frees a used TLS slot identified by the given address
  316. Result DeleteThreadLocalRegion(KProcessAddress addr);
  317. ///////////////////////////////////////////////////////////////////////////////////////////////
  318. // Debug watchpoint management
  319. // Attempts to insert a watchpoint into a free slot. Returns false if none are available.
  320. bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
  321. // Attempts to remove the watchpoint specified by the given parameters.
  322. bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
  323. const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const {
  324. return m_watchpoints;
  325. }
  326. const std::string& GetName() {
  327. return name;
  328. }
  329. private:
  330. void PinThread(s32 core_id, KThread* thread) {
  331. ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
  332. ASSERT(thread != nullptr);
  333. ASSERT(m_pinned_threads[core_id] == nullptr);
  334. m_pinned_threads[core_id] = thread;
  335. }
  336. void UnpinThread(s32 core_id, KThread* thread) {
  337. ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
  338. ASSERT(thread != nullptr);
  339. ASSERT(m_pinned_threads[core_id] == thread);
  340. m_pinned_threads[core_id] = nullptr;
  341. }
  342. void FinalizeHandleTable() {
  343. // Finalize the table.
  344. m_handle_table.Finalize();
  345. // Note that the table is finalized.
  346. m_is_handle_table_initialized = false;
  347. }
  348. void ChangeState(State new_state);
  349. /// Allocates the main thread stack for the process, given the stack size in bytes.
  350. Result AllocateMainThreadStack(std::size_t stack_size);
  351. /// Memory manager for this process
  352. KPageTable m_page_table;
  353. /// Current status of the process
  354. State m_state{};
  355. /// The ID of this process
  356. u64 m_process_id = 0;
  357. /// Title ID corresponding to the process
  358. u64 m_program_id = 0;
  359. /// Specifies additional memory to be reserved for the process's memory management by the
  360. /// system. When this is non-zero, secure memory is allocated and used for page table allocation
  361. /// instead of using the normal global page tables/memory block management.
  362. u32 m_system_resource_size = 0;
  363. /// Resource limit descriptor for this process
  364. KResourceLimit* m_resource_limit{};
  365. KVirtualAddress m_system_resource_address{};
  366. /// The ideal CPU core for this process, threads are scheduled on this core by default.
  367. u8 m_ideal_core = 0;
  368. /// Contains the parsed process capability descriptors.
  369. ProcessCapabilities m_capabilities;
  370. /// Whether or not this process is AArch64, or AArch32.
  371. /// By default, we currently assume this is true, unless otherwise
  372. /// specified by metadata provided to the process during loading.
  373. bool m_is_64bit_process = true;
  374. /// Total running time for the process in ticks.
  375. std::atomic<u64> m_total_process_running_time_ticks = 0;
  376. /// Per-process handle table for storing created object handles in.
  377. KHandleTable m_handle_table;
  378. /// Per-process address arbiter.
  379. KAddressArbiter m_address_arbiter;
  380. /// The per-process mutex lock instance used for handling various
  381. /// forms of services, such as lock arbitration, and condition
  382. /// variable related facilities.
  383. KConditionVariable m_condition_var;
  384. /// Address indicating the location of the process' dedicated TLS region.
  385. KProcessAddress m_plr_address = 0;
  386. /// Address indicating the location of the process's entry point.
  387. KProcessAddress m_code_address = 0;
  388. /// Random values for svcGetInfo RandomEntropy
  389. std::array<u64, RANDOM_ENTROPY_SIZE> m_random_entropy{};
  390. /// List of threads that are running with this process as their owner.
  391. std::list<KThread*> m_thread_list;
  392. /// List of shared memory that are running with this process as their owner.
  393. std::list<KSharedMemoryInfo*> m_shared_memory_list;
  394. /// Address of the top of the main thread's stack
  395. KProcessAddress m_main_thread_stack_top{};
  396. /// Size of the main thread's stack
  397. std::size_t m_main_thread_stack_size{};
  398. /// Memory usage capacity for the process
  399. std::size_t m_memory_usage_capacity{};
  400. /// Process total image size
  401. std::size_t m_image_size{};
  402. /// Schedule count of this process
  403. s64 m_schedule_count{};
  404. size_t m_memory_release_hint{};
  405. std::string name{};
  406. bool m_is_signaled{};
  407. bool m_is_suspended{};
  408. bool m_is_immortal{};
  409. bool m_is_handle_table_initialized{};
  410. bool m_is_initialized{};
  411. bool m_is_hbl{};
  412. std::atomic<u16> m_num_running_threads{};
  413. std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_running_threads{};
  414. std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_idle_counts{};
  415. std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_pinned_threads{};
  416. std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> m_watchpoints{};
  417. std::map<KProcessAddress, u64> m_debug_page_refcounts;
  418. KThread* m_exception_thread{};
  419. KLightLock m_state_lock;
  420. KLightLock m_list_lock;
  421. using TLPTree =
  422. Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
  423. using TLPIterator = TLPTree::iterator;
  424. TLPTree m_fully_used_tlp_tree;
  425. TLPTree m_partially_used_tlp_tree;
  426. };
  427. } // namespace Kernel