k_process.h 17 KB

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