k_process.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <map>
  5. #include "core/arm/arm_interface.h"
  6. #include "core/file_sys/program_metadata.h"
  7. #include "core/hle/kernel/code_set.h"
  8. #include "core/hle/kernel/k_address_arbiter.h"
  9. #include "core/hle/kernel/k_capabilities.h"
  10. #include "core/hle/kernel/k_condition_variable.h"
  11. #include "core/hle/kernel/k_handle_table.h"
  12. #include "core/hle/kernel/k_page_table_manager.h"
  13. #include "core/hle/kernel/k_process_page_table.h"
  14. #include "core/hle/kernel/k_system_resource.h"
  15. #include "core/hle/kernel/k_thread.h"
  16. #include "core/hle/kernel/k_thread_local_page.h"
  17. namespace Kernel {
  18. enum class DebugWatchpointType : u8 {
  19. None = 0,
  20. Read = 1 << 0,
  21. Write = 1 << 1,
  22. ReadOrWrite = Read | Write,
  23. };
  24. DECLARE_ENUM_FLAG_OPERATORS(DebugWatchpointType);
  25. struct DebugWatchpoint {
  26. KProcessAddress start_address;
  27. KProcessAddress end_address;
  28. DebugWatchpointType type;
  29. };
  30. class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> {
  31. KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
  32. public:
  33. enum class State {
  34. Created = static_cast<u32>(Svc::ProcessState::Created),
  35. CreatedAttached = static_cast<u32>(Svc::ProcessState::CreatedAttached),
  36. Running = static_cast<u32>(Svc::ProcessState::Running),
  37. Crashed = static_cast<u32>(Svc::ProcessState::Crashed),
  38. RunningAttached = static_cast<u32>(Svc::ProcessState::RunningAttached),
  39. Terminating = static_cast<u32>(Svc::ProcessState::Terminating),
  40. Terminated = static_cast<u32>(Svc::ProcessState::Terminated),
  41. DebugBreak = static_cast<u32>(Svc::ProcessState::DebugBreak),
  42. };
  43. using ThreadList = Common::IntrusiveListMemberTraits<&KThread::m_process_list_node>::ListType;
  44. static constexpr size_t AslrAlignment = 2_MiB;
  45. public:
  46. static constexpr u64 InitialProcessIdMin = 1;
  47. static constexpr u64 InitialProcessIdMax = 0x50;
  48. static constexpr u64 ProcessIdMin = InitialProcessIdMax + 1;
  49. static constexpr u64 ProcessIdMax = std::numeric_limits<u64>::max();
  50. private:
  51. using SharedMemoryInfoList = Common::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
  52. using TLPTree =
  53. Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
  54. using TLPIterator = TLPTree::iterator;
  55. private:
  56. KProcessPageTable m_page_table;
  57. std::atomic<size_t> m_used_kernel_memory_size{};
  58. TLPTree m_fully_used_tlp_tree{};
  59. TLPTree m_partially_used_tlp_tree{};
  60. s32 m_ideal_core_id{};
  61. KResourceLimit* m_resource_limit{};
  62. KSystemResource* m_system_resource{};
  63. size_t m_memory_release_hint{};
  64. State m_state{};
  65. KLightLock m_state_lock;
  66. KLightLock m_list_lock;
  67. KConditionVariable m_cond_var;
  68. KAddressArbiter m_address_arbiter;
  69. std::array<u64, 4> m_entropy{};
  70. bool m_is_signaled{};
  71. bool m_is_initialized{};
  72. bool m_is_application{};
  73. bool m_is_default_application_system_resource{};
  74. bool m_is_hbl{};
  75. std::array<char, 13> m_name{};
  76. std::atomic<u16> m_num_running_threads{};
  77. Svc::CreateProcessFlag m_flags{};
  78. KMemoryManager::Pool m_memory_pool{};
  79. s64 m_schedule_count{};
  80. KCapabilities m_capabilities{};
  81. u64 m_program_id{};
  82. u64 m_process_id{};
  83. KProcessAddress m_code_address{};
  84. size_t m_code_size{};
  85. size_t m_main_thread_stack_size{};
  86. size_t m_max_process_memory{};
  87. u32 m_version{};
  88. KHandleTable m_handle_table;
  89. KProcessAddress m_plr_address{};
  90. KThread* m_exception_thread{};
  91. ThreadList m_thread_list{};
  92. SharedMemoryInfoList m_shared_memory_list{};
  93. bool m_is_suspended{};
  94. bool m_is_immortal{};
  95. bool m_is_handle_table_initialized{};
  96. std::array<std::unique_ptr<Core::ArmInterface>, Core::Hardware::NUM_CPU_CORES>
  97. m_arm_interfaces{};
  98. std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_running_threads{};
  99. std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_idle_counts{};
  100. std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_switch_counts{};
  101. std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_pinned_threads{};
  102. std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> m_watchpoints{};
  103. std::map<KProcessAddress, u64> m_debug_page_refcounts{};
  104. std::atomic<s64> m_cpu_time{};
  105. std::atomic<s64> m_num_process_switches{};
  106. std::atomic<s64> m_num_thread_switches{};
  107. std::atomic<s64> m_num_fpu_switches{};
  108. std::atomic<s64> m_num_supervisor_calls{};
  109. std::atomic<s64> m_num_ipc_messages{};
  110. std::atomic<s64> m_num_ipc_replies{};
  111. std::atomic<s64> m_num_ipc_receives{};
  112. #ifdef HAS_NCE
  113. std::unordered_map<u64, u64> m_post_handlers{};
  114. #endif
  115. private:
  116. Result StartTermination();
  117. void FinishTermination();
  118. void PinThread(s32 core_id, KThread* thread) {
  119. ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
  120. ASSERT(thread != nullptr);
  121. ASSERT(m_pinned_threads[core_id] == nullptr);
  122. m_pinned_threads[core_id] = thread;
  123. }
  124. void UnpinThread(s32 core_id, KThread* thread) {
  125. ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
  126. ASSERT(thread != nullptr);
  127. ASSERT(m_pinned_threads[core_id] == thread);
  128. m_pinned_threads[core_id] = nullptr;
  129. }
  130. public:
  131. explicit KProcess(KernelCore& kernel);
  132. ~KProcess() override;
  133. Result Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit,
  134. bool is_real);
  135. Result Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg,
  136. std::span<const u32> caps, KResourceLimit* res_limit,
  137. KMemoryManager::Pool pool, bool immortal);
  138. Result Initialize(const Svc::CreateProcessParameter& params, std::span<const u32> user_caps,
  139. KResourceLimit* res_limit, KMemoryManager::Pool pool,
  140. KProcessAddress aslr_space_start);
  141. void Exit();
  142. const char* GetName() const {
  143. return m_name.data();
  144. }
  145. u64 GetProgramId() const {
  146. return m_program_id;
  147. }
  148. u64 GetProcessId() const {
  149. return m_process_id;
  150. }
  151. State GetState() const {
  152. return m_state;
  153. }
  154. u64 GetCoreMask() const {
  155. return m_capabilities.GetCoreMask();
  156. }
  157. u64 GetPhysicalCoreMask() const {
  158. return m_capabilities.GetPhysicalCoreMask();
  159. }
  160. u64 GetPriorityMask() const {
  161. return m_capabilities.GetPriorityMask();
  162. }
  163. s32 GetIdealCoreId() const {
  164. return m_ideal_core_id;
  165. }
  166. void SetIdealCoreId(s32 core_id) {
  167. m_ideal_core_id = core_id;
  168. }
  169. bool CheckThreadPriority(s32 prio) const {
  170. return ((1ULL << prio) & this->GetPriorityMask()) != 0;
  171. }
  172. u32 GetCreateProcessFlags() const {
  173. return static_cast<u32>(m_flags);
  174. }
  175. bool Is64Bit() const {
  176. return True(m_flags & Svc::CreateProcessFlag::Is64Bit);
  177. }
  178. KProcessAddress GetEntryPoint() const {
  179. return m_code_address;
  180. }
  181. size_t GetMainStackSize() const {
  182. return m_main_thread_stack_size;
  183. }
  184. KMemoryManager::Pool GetMemoryPool() const {
  185. return m_memory_pool;
  186. }
  187. u64 GetRandomEntropy(size_t i) const {
  188. return m_entropy[i];
  189. }
  190. bool IsApplication() const {
  191. return m_is_application;
  192. }
  193. bool IsDefaultApplicationSystemResource() const {
  194. return m_is_default_application_system_resource;
  195. }
  196. bool IsSuspended() const {
  197. return m_is_suspended;
  198. }
  199. void SetSuspended(bool suspended) {
  200. m_is_suspended = suspended;
  201. }
  202. Result Terminate();
  203. bool IsTerminated() const {
  204. return m_state == State::Terminated;
  205. }
  206. bool IsPermittedSvc(u32 svc_id) const {
  207. return m_capabilities.IsPermittedSvc(svc_id);
  208. }
  209. bool IsPermittedInterrupt(s32 interrupt_id) const {
  210. return m_capabilities.IsPermittedInterrupt(interrupt_id);
  211. }
  212. bool IsPermittedDebug() const {
  213. return m_capabilities.IsPermittedDebug();
  214. }
  215. bool CanForceDebug() const {
  216. return m_capabilities.CanForceDebug();
  217. }
  218. bool IsHbl() const {
  219. return m_is_hbl;
  220. }
  221. u32 GetAllocateOption() const {
  222. return m_page_table.GetAllocateOption();
  223. }
  224. ThreadList& GetThreadList() {
  225. return m_thread_list;
  226. }
  227. const ThreadList& GetThreadList() const {
  228. return m_thread_list;
  229. }
  230. bool EnterUserException();
  231. bool LeaveUserException();
  232. bool ReleaseUserException(KThread* thread);
  233. KThread* GetPinnedThread(s32 core_id) const {
  234. ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
  235. return m_pinned_threads[core_id];
  236. }
  237. const Svc::SvcAccessFlagSet& GetSvcPermissions() const {
  238. return m_capabilities.GetSvcPermissions();
  239. }
  240. KResourceLimit* GetResourceLimit() const {
  241. return m_resource_limit;
  242. }
  243. bool ReserveResource(Svc::LimitableResource which, s64 value);
  244. bool ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout);
  245. void ReleaseResource(Svc::LimitableResource which, s64 value);
  246. void ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint);
  247. KLightLock& GetStateLock() {
  248. return m_state_lock;
  249. }
  250. KLightLock& GetListLock() {
  251. return m_list_lock;
  252. }
  253. KProcessPageTable& GetPageTable() {
  254. return m_page_table;
  255. }
  256. const KProcessPageTable& GetPageTable() const {
  257. return m_page_table;
  258. }
  259. KHandleTable& GetHandleTable() {
  260. return m_handle_table;
  261. }
  262. const KHandleTable& GetHandleTable() const {
  263. return m_handle_table;
  264. }
  265. size_t GetUsedUserPhysicalMemorySize() const;
  266. size_t GetTotalUserPhysicalMemorySize() const;
  267. size_t GetUsedNonSystemUserPhysicalMemorySize() const;
  268. size_t GetTotalNonSystemUserPhysicalMemorySize() const;
  269. Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
  270. void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
  271. Result CreateThreadLocalRegion(KProcessAddress* out);
  272. Result DeleteThreadLocalRegion(KProcessAddress addr);
  273. KProcessAddress GetProcessLocalRegionAddress() const {
  274. return m_plr_address;
  275. }
  276. KThread* GetExceptionThread() const {
  277. return m_exception_thread;
  278. }
  279. void AddCpuTime(s64 diff) {
  280. m_cpu_time += diff;
  281. }
  282. s64 GetCpuTime() {
  283. return m_cpu_time.load();
  284. }
  285. s64 GetScheduledCount() const {
  286. return m_schedule_count;
  287. }
  288. void IncrementScheduledCount() {
  289. ++m_schedule_count;
  290. }
  291. void IncrementRunningThreadCount();
  292. void DecrementRunningThreadCount();
  293. size_t GetRequiredSecureMemorySizeNonDefault() const {
  294. if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
  295. auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
  296. return secure_system_resource->CalculateRequiredSecureMemorySize();
  297. }
  298. return 0;
  299. }
  300. size_t GetRequiredSecureMemorySize() const {
  301. if (m_system_resource->IsSecureResource()) {
  302. auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
  303. return secure_system_resource->CalculateRequiredSecureMemorySize();
  304. }
  305. return 0;
  306. }
  307. size_t GetTotalSystemResourceSize() const {
  308. if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
  309. auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
  310. return secure_system_resource->GetSize();
  311. }
  312. return 0;
  313. }
  314. size_t GetUsedSystemResourceSize() const {
  315. if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
  316. auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
  317. return secure_system_resource->GetUsedSize();
  318. }
  319. return 0;
  320. }
  321. void SetRunningThread(s32 core, KThread* thread, u64 idle_count, u64 switch_count) {
  322. m_running_threads[core] = thread;
  323. m_running_thread_idle_counts[core] = idle_count;
  324. m_running_thread_switch_counts[core] = switch_count;
  325. }
  326. void ClearRunningThread(KThread* thread) {
  327. for (size_t i = 0; i < m_running_threads.size(); ++i) {
  328. if (m_running_threads[i] == thread) {
  329. m_running_threads[i] = nullptr;
  330. }
  331. }
  332. }
  333. const KSystemResource& GetSystemResource() const {
  334. return *m_system_resource;
  335. }
  336. const KMemoryBlockSlabManager& GetMemoryBlockSlabManager() const {
  337. return m_system_resource->GetMemoryBlockSlabManager();
  338. }
  339. const KBlockInfoManager& GetBlockInfoManager() const {
  340. return m_system_resource->GetBlockInfoManager();
  341. }
  342. const KPageTableManager& GetPageTableManager() const {
  343. return m_system_resource->GetPageTableManager();
  344. }
  345. KThread* GetRunningThread(s32 core) const {
  346. return m_running_threads[core];
  347. }
  348. u64 GetRunningThreadIdleCount(s32 core) const {
  349. return m_running_thread_idle_counts[core];
  350. }
  351. u64 GetRunningThreadSwitchCount(s32 core) const {
  352. return m_running_thread_switch_counts[core];
  353. }
  354. void RegisterThread(KThread* thread);
  355. void UnregisterThread(KThread* thread);
  356. Result Run(s32 priority, size_t stack_size);
  357. Result Reset();
  358. void SetDebugBreak() {
  359. if (m_state == State::RunningAttached) {
  360. this->ChangeState(State::DebugBreak);
  361. }
  362. }
  363. void SetAttached() {
  364. if (m_state == State::DebugBreak) {
  365. this->ChangeState(State::RunningAttached);
  366. }
  367. }
  368. Result SetActivity(Svc::ProcessActivity activity);
  369. void PinCurrentThread();
  370. void UnpinCurrentThread();
  371. void UnpinThread(KThread* thread);
  372. void SignalConditionVariable(uintptr_t cv_key, int32_t count) {
  373. return m_cond_var.Signal(cv_key, count);
  374. }
  375. Result WaitConditionVariable(KProcessAddress address, uintptr_t cv_key, u32 tag, s64 ns) {
  376. R_RETURN(m_cond_var.Wait(address, cv_key, tag, ns));
  377. }
  378. Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value,
  379. s32 count) {
  380. R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count));
  381. }
  382. Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value,
  383. s64 timeout) {
  384. R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout));
  385. }
  386. Result GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count);
  387. static void Switch(KProcess* cur_process, KProcess* next_process);
  388. #ifdef HAS_NCE
  389. std::unordered_map<u64, u64>& GetPostHandlers() noexcept {
  390. return m_post_handlers;
  391. }
  392. #endif
  393. Core::ArmInterface* GetArmInterface(size_t core_index) const {
  394. return m_arm_interfaces[core_index].get();
  395. }
  396. public:
  397. // Attempts to insert a watchpoint into a free slot. Returns false if none are available.
  398. bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
  399. // Attempts to remove the watchpoint specified by the given parameters.
  400. bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
  401. const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const {
  402. return m_watchpoints;
  403. }
  404. public:
  405. Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
  406. KProcessAddress aslr_space_start, bool is_hbl);
  407. void LoadModule(CodeSet code_set, KProcessAddress base_addr);
  408. void InitializeInterfaces();
  409. Core::Memory::Memory& GetMemory() const;
  410. public:
  411. // Overridden parent functions.
  412. bool IsInitialized() const override {
  413. return m_is_initialized;
  414. }
  415. static void PostDestroy(uintptr_t arg) {}
  416. void Finalize() override;
  417. u64 GetIdImpl() const {
  418. return this->GetProcessId();
  419. }
  420. u64 GetId() const override {
  421. return this->GetIdImpl();
  422. }
  423. virtual bool IsSignaled() const override {
  424. ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
  425. return m_is_signaled;
  426. }
  427. void DoWorkerTaskImpl();
  428. private:
  429. void ChangeState(State new_state) {
  430. if (m_state != new_state) {
  431. m_state = new_state;
  432. m_is_signaled = true;
  433. this->NotifyAvailable();
  434. }
  435. }
  436. Result InitializeHandleTable(s32 size) {
  437. // Try to initialize the handle table.
  438. R_TRY(m_handle_table.Initialize(size));
  439. // We succeeded, so note that we did.
  440. m_is_handle_table_initialized = true;
  441. R_SUCCEED();
  442. }
  443. void FinalizeHandleTable() {
  444. // Finalize the table.
  445. m_handle_table.Finalize();
  446. // Note that the table is finalized.
  447. m_is_handle_table_initialized = false;
  448. }
  449. };
  450. } // namespace Kernel