k_process.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <random>
  4. #include "common/scope_exit.h"
  5. #include "common/settings.h"
  6. #include "core/core.h"
  7. #include "core/hle/kernel/k_process.h"
  8. #include "core/hle/kernel/k_scoped_resource_reservation.h"
  9. #include "core/hle/kernel/k_shared_memory.h"
  10. #include "core/hle/kernel/k_shared_memory_info.h"
  11. #include "core/hle/kernel/k_thread_local_page.h"
  12. #include "core/hle/kernel/k_thread_queue.h"
  13. #include "core/hle/kernel/k_worker_task_manager.h"
  14. #include "core/arm/dynarmic/arm_dynarmic_32.h"
  15. #include "core/arm/dynarmic/arm_dynarmic_64.h"
  16. #ifdef HAS_NCE
  17. #include "core/arm/nce/arm_nce.h"
  18. #endif
  19. namespace Kernel {
  20. namespace {
  21. Result TerminateChildren(KernelCore& kernel, KProcess* process,
  22. const KThread* thread_to_not_terminate) {
  23. // Request that all children threads terminate.
  24. {
  25. KScopedLightLock proc_lk(process->GetListLock());
  26. KScopedSchedulerLock sl(kernel);
  27. if (thread_to_not_terminate != nullptr &&
  28. process->GetPinnedThread(GetCurrentCoreId(kernel)) == thread_to_not_terminate) {
  29. // NOTE: Here Nintendo unpins the current thread instead of the thread_to_not_terminate.
  30. // This is valid because the only caller which uses non-nullptr as argument uses
  31. // GetCurrentThreadPointer(), but it's still notable because it seems incorrect at
  32. // first glance.
  33. process->UnpinCurrentThread();
  34. }
  35. auto& thread_list = process->GetThreadList();
  36. for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
  37. if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) {
  38. if (thread->GetState() != ThreadState::Terminated) {
  39. thread->RequestTerminate();
  40. }
  41. }
  42. }
  43. }
  44. // Wait for all children threads to terminate.
  45. while (true) {
  46. // Get the next child.
  47. KThread* cur_child = nullptr;
  48. {
  49. KScopedLightLock proc_lk(process->GetListLock());
  50. auto& thread_list = process->GetThreadList();
  51. for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
  52. if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) {
  53. if (thread->GetState() != ThreadState::Terminated) {
  54. if (thread->Open()) {
  55. cur_child = thread;
  56. break;
  57. }
  58. }
  59. }
  60. }
  61. }
  62. // If we didn't find any non-terminated children, we're done.
  63. if (cur_child == nullptr) {
  64. break;
  65. }
  66. // Terminate and close the thread.
  67. SCOPE_EXIT({ cur_child->Close(); });
  68. if (const Result terminate_result = cur_child->Terminate();
  69. ResultTerminationRequested == terminate_result) {
  70. R_THROW(terminate_result);
  71. }
  72. }
  73. R_SUCCEED();
  74. }
  75. class ThreadQueueImplForKProcessEnterUserException final : public KThreadQueue {
  76. private:
  77. KThread** m_exception_thread;
  78. public:
  79. explicit ThreadQueueImplForKProcessEnterUserException(KernelCore& kernel, KThread** t)
  80. : KThreadQueue(kernel), m_exception_thread(t) {}
  81. virtual void EndWait(KThread* waiting_thread, Result wait_result) override {
  82. // Set the exception thread.
  83. *m_exception_thread = waiting_thread;
  84. // Invoke the base end wait handler.
  85. KThreadQueue::EndWait(waiting_thread, wait_result);
  86. }
  87. virtual void CancelWait(KThread* waiting_thread, Result wait_result,
  88. bool cancel_timer_task) override {
  89. // Remove the thread as a waiter on its mutex owner.
  90. waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread);
  91. // Invoke the base cancel wait handler.
  92. KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task);
  93. }
  94. };
  95. void GenerateRandom(std::span<u64> out_random) {
  96. std::mt19937 rng(Settings::values.rng_seed_enabled ? Settings::values.rng_seed.GetValue()
  97. : static_cast<u32>(std::time(nullptr)));
  98. std::uniform_int_distribution<u64> distribution;
  99. std::generate(out_random.begin(), out_random.end(), [&] { return distribution(rng); });
  100. }
  101. } // namespace
  102. void KProcess::Finalize() {
  103. // Delete the process local region.
  104. this->DeleteThreadLocalRegion(m_plr_address);
  105. // Get the used memory size.
  106. const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize();
  107. // Finalize the page table.
  108. m_page_table.Finalize();
  109. // Finish using our system resource.
  110. if (m_system_resource) {
  111. if (m_system_resource->IsSecureResource()) {
  112. // Finalize optimized memory. If memory wasn't optimized, this is a no-op.
  113. m_kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
  114. }
  115. m_system_resource->Close();
  116. m_system_resource = nullptr;
  117. }
  118. // Free all shared memory infos.
  119. {
  120. auto it = m_shared_memory_list.begin();
  121. while (it != m_shared_memory_list.end()) {
  122. KSharedMemoryInfo* info = std::addressof(*it);
  123. KSharedMemory* shmem = info->GetSharedMemory();
  124. while (!info->Close()) {
  125. shmem->Close();
  126. }
  127. shmem->Close();
  128. it = m_shared_memory_list.erase(it);
  129. KSharedMemoryInfo::Free(m_kernel, info);
  130. }
  131. }
  132. // Our thread local page list must be empty at this point.
  133. ASSERT(m_partially_used_tlp_tree.empty());
  134. ASSERT(m_fully_used_tlp_tree.empty());
  135. // Release memory to the resource limit.
  136. if (m_resource_limit != nullptr) {
  137. ASSERT(used_memory_size >= m_memory_release_hint);
  138. m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, used_memory_size,
  139. used_memory_size - m_memory_release_hint);
  140. m_resource_limit->Close();
  141. }
  142. // Perform inherited finalization.
  143. KSynchronizationObject::Finalize();
  144. }
  145. Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit,
  146. bool is_real) {
  147. // TODO: remove this special case
  148. if (is_real) {
  149. // Create and clear the process local region.
  150. R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address)));
  151. this->GetMemory().ZeroBlock(m_plr_address, Svc::ThreadLocalRegionSize);
  152. }
  153. // Copy in the name from parameters.
  154. static_assert(sizeof(params.name) < sizeof(m_name));
  155. std::memcpy(m_name.data(), params.name.data(), sizeof(params.name));
  156. m_name[sizeof(params.name)] = 0;
  157. // Set misc fields.
  158. m_state = State::Created;
  159. m_main_thread_stack_size = 0;
  160. m_used_kernel_memory_size = 0;
  161. m_ideal_core_id = 0;
  162. m_flags = params.flags;
  163. m_version = params.version;
  164. m_program_id = params.program_id;
  165. m_code_address = params.code_address;
  166. m_code_size = params.code_num_pages * PageSize;
  167. m_is_application = True(params.flags & Svc::CreateProcessFlag::IsApplication);
  168. // Set thread fields.
  169. for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  170. m_running_threads[i] = nullptr;
  171. m_pinned_threads[i] = nullptr;
  172. m_running_thread_idle_counts[i] = 0;
  173. m_running_thread_switch_counts[i] = 0;
  174. }
  175. // Set max memory based on address space type.
  176. switch ((params.flags & Svc::CreateProcessFlag::AddressSpaceMask)) {
  177. case Svc::CreateProcessFlag::AddressSpace32Bit:
  178. case Svc::CreateProcessFlag::AddressSpace64BitDeprecated:
  179. case Svc::CreateProcessFlag::AddressSpace64Bit:
  180. m_max_process_memory = m_page_table.GetHeapRegionSize();
  181. break;
  182. case Svc::CreateProcessFlag::AddressSpace32BitWithoutAlias:
  183. m_max_process_memory = m_page_table.GetHeapRegionSize() + m_page_table.GetAliasRegionSize();
  184. break;
  185. default:
  186. UNREACHABLE();
  187. }
  188. // Generate random entropy.
  189. GenerateRandom(m_entropy);
  190. // Clear remaining fields.
  191. m_num_running_threads = 0;
  192. m_num_process_switches = 0;
  193. m_num_thread_switches = 0;
  194. m_num_fpu_switches = 0;
  195. m_num_supervisor_calls = 0;
  196. m_num_ipc_messages = 0;
  197. m_is_signaled = false;
  198. m_exception_thread = nullptr;
  199. m_is_suspended = false;
  200. m_memory_release_hint = 0;
  201. m_schedule_count = 0;
  202. m_is_handle_table_initialized = false;
  203. // Open a reference to our resource limit.
  204. m_resource_limit = res_limit;
  205. m_resource_limit->Open();
  206. // We're initialized!
  207. m_is_initialized = true;
  208. R_SUCCEED();
  209. }
  210. Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg,
  211. std::span<const u32> caps, KResourceLimit* res_limit,
  212. KMemoryManager::Pool pool, bool immortal) {
  213. ASSERT(res_limit != nullptr);
  214. ASSERT((params.code_num_pages * PageSize) / PageSize ==
  215. static_cast<size_t>(params.code_num_pages));
  216. // Set members.
  217. m_memory_pool = pool;
  218. m_is_default_application_system_resource = false;
  219. m_is_immortal = immortal;
  220. // Setup our system resource.
  221. if (const size_t system_resource_num_pages = params.system_resource_num_pages;
  222. system_resource_num_pages != 0) {
  223. // Create a secure system resource.
  224. KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel);
  225. R_UNLESS(secure_resource != nullptr, ResultOutOfResource);
  226. ON_RESULT_FAILURE {
  227. secure_resource->Close();
  228. };
  229. // Initialize the secure resource.
  230. R_TRY(secure_resource->Initialize(system_resource_num_pages * PageSize, res_limit,
  231. m_memory_pool));
  232. // Set our system resource.
  233. m_system_resource = secure_resource;
  234. } else {
  235. // Use the system-wide system resource.
  236. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication);
  237. m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource()
  238. : m_kernel.GetSystemSystemResource());
  239. m_is_default_application_system_resource = is_app;
  240. // Open reference to the system resource.
  241. m_system_resource->Open();
  242. }
  243. // Ensure we clean up our secure resource, if we fail.
  244. ON_RESULT_FAILURE {
  245. m_system_resource->Close();
  246. m_system_resource = nullptr;
  247. };
  248. // Setup page table.
  249. {
  250. const auto as_type = params.flags & Svc::CreateProcessFlag::AddressSpaceMask;
  251. const bool enable_aslr = True(params.flags & Svc::CreateProcessFlag::EnableAslr);
  252. const bool enable_das_merge =
  253. False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge);
  254. R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool,
  255. params.code_address, params.code_num_pages * PageSize,
  256. m_system_resource, res_limit, this->GetMemory(), 0));
  257. }
  258. ON_RESULT_FAILURE_2 {
  259. m_page_table.Finalize();
  260. };
  261. // Ensure we can insert the code region.
  262. R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize,
  263. KMemoryState::Code),
  264. ResultInvalidMemoryRegion);
  265. // Map the code region.
  266. R_TRY(m_page_table.MapPageGroup(params.code_address, pg, KMemoryState::Code,
  267. KMemoryPermission::KernelRead));
  268. // Initialize capabilities.
  269. R_TRY(m_capabilities.InitializeForKip(caps, std::addressof(m_page_table)));
  270. // Initialize the process id.
  271. m_process_id = m_kernel.CreateNewUserProcessID();
  272. ASSERT(InitialProcessIdMin <= m_process_id);
  273. ASSERT(m_process_id <= InitialProcessIdMax);
  274. // Initialize the rest of the process.
  275. R_TRY(this->Initialize(params, res_limit, true));
  276. // We succeeded!
  277. R_SUCCEED();
  278. }
  279. Result KProcess::Initialize(const Svc::CreateProcessParameter& params,
  280. std::span<const u32> user_caps, KResourceLimit* res_limit,
  281. KMemoryManager::Pool pool, KProcessAddress aslr_space_start) {
  282. ASSERT(res_limit != nullptr);
  283. // Set members.
  284. m_memory_pool = pool;
  285. m_is_default_application_system_resource = false;
  286. m_is_immortal = false;
  287. // Get the memory sizes.
  288. const size_t code_num_pages = params.code_num_pages;
  289. const size_t system_resource_num_pages = params.system_resource_num_pages;
  290. const size_t code_size = code_num_pages * PageSize;
  291. const size_t system_resource_size = system_resource_num_pages * PageSize;
  292. // Reserve memory for our code resource.
  293. KScopedResourceReservation memory_reservation(
  294. res_limit, Svc::LimitableResource::PhysicalMemoryMax, code_size);
  295. R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
  296. // Setup our system resource.
  297. if (system_resource_num_pages != 0) {
  298. // Create a secure system resource.
  299. KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel);
  300. R_UNLESS(secure_resource != nullptr, ResultOutOfResource);
  301. ON_RESULT_FAILURE {
  302. secure_resource->Close();
  303. };
  304. // Initialize the secure resource.
  305. R_TRY(secure_resource->Initialize(system_resource_size, res_limit, m_memory_pool));
  306. // Set our system resource.
  307. m_system_resource = secure_resource;
  308. } else {
  309. // Use the system-wide system resource.
  310. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication);
  311. m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource()
  312. : m_kernel.GetSystemSystemResource());
  313. m_is_default_application_system_resource = is_app;
  314. // Open reference to the system resource.
  315. m_system_resource->Open();
  316. }
  317. // Ensure we clean up our secure resource, if we fail.
  318. ON_RESULT_FAILURE {
  319. m_system_resource->Close();
  320. m_system_resource = nullptr;
  321. };
  322. // Setup page table.
  323. {
  324. const auto as_type = params.flags & Svc::CreateProcessFlag::AddressSpaceMask;
  325. const bool enable_aslr = True(params.flags & Svc::CreateProcessFlag::EnableAslr);
  326. const bool enable_das_merge =
  327. False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge);
  328. R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool,
  329. params.code_address, code_size, m_system_resource, res_limit,
  330. this->GetMemory(), aslr_space_start));
  331. }
  332. ON_RESULT_FAILURE_2 {
  333. m_page_table.Finalize();
  334. };
  335. // Ensure we can insert the code region.
  336. R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code),
  337. ResultInvalidMemoryRegion);
  338. // Map the code region.
  339. R_TRY(m_page_table.MapPages(params.code_address, code_num_pages, KMemoryState::Code,
  340. KMemoryPermission::KernelRead | KMemoryPermission::NotMapped));
  341. // Initialize capabilities.
  342. R_TRY(m_capabilities.InitializeForUser(user_caps, std::addressof(m_page_table)));
  343. // Initialize the process id.
  344. m_process_id = m_kernel.CreateNewUserProcessID();
  345. ASSERT(ProcessIdMin <= m_process_id);
  346. ASSERT(m_process_id <= ProcessIdMax);
  347. // If we should optimize memory allocations, do so.
  348. if (m_system_resource->IsSecureResource() &&
  349. True(params.flags & Svc::CreateProcessFlag::OptimizeMemoryAllocation)) {
  350. R_TRY(m_kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool));
  351. }
  352. // Initialize the rest of the process.
  353. R_TRY(this->Initialize(params, res_limit, true));
  354. // We succeeded, so commit our memory reservation.
  355. memory_reservation.Commit();
  356. R_SUCCEED();
  357. }
  358. void KProcess::DoWorkerTaskImpl() {
  359. // Terminate child threads.
  360. TerminateChildren(m_kernel, this, nullptr);
  361. // Finalize the handle table, if we're not immortal.
  362. if (!m_is_immortal && m_is_handle_table_initialized) {
  363. this->FinalizeHandleTable();
  364. }
  365. // Finish termination.
  366. this->FinishTermination();
  367. }
  368. Result KProcess::StartTermination() {
  369. // Finalize the handle table when we're done, if the process isn't immortal.
  370. SCOPE_EXIT({
  371. if (!m_is_immortal) {
  372. this->FinalizeHandleTable();
  373. }
  374. });
  375. // Terminate child threads other than the current one.
  376. R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel)));
  377. }
  378. void KProcess::FinishTermination() {
  379. // Only allow termination to occur if the process isn't immortal.
  380. if (!m_is_immortal) {
  381. // Release resource limit hint.
  382. if (m_resource_limit != nullptr) {
  383. m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize();
  384. m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, 0,
  385. m_memory_release_hint);
  386. }
  387. // Change state.
  388. {
  389. KScopedSchedulerLock sl(m_kernel);
  390. this->ChangeState(State::Terminated);
  391. }
  392. // Close.
  393. this->Close();
  394. }
  395. }
  396. void KProcess::Exit() {
  397. // Determine whether we need to start terminating
  398. bool needs_terminate = false;
  399. {
  400. KScopedLightLock lk(m_state_lock);
  401. KScopedSchedulerLock sl(m_kernel);
  402. ASSERT(m_state != State::Created);
  403. ASSERT(m_state != State::CreatedAttached);
  404. ASSERT(m_state != State::Crashed);
  405. ASSERT(m_state != State::Terminated);
  406. if (m_state == State::Running || m_state == State::RunningAttached ||
  407. m_state == State::DebugBreak) {
  408. this->ChangeState(State::Terminating);
  409. needs_terminate = true;
  410. }
  411. }
  412. // If we need to start termination, do so.
  413. if (needs_terminate) {
  414. this->StartTermination();
  415. // Register the process as a work task.
  416. m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this);
  417. }
  418. // Exit the current thread.
  419. GetCurrentThread(m_kernel).Exit();
  420. }
  421. Result KProcess::Terminate() {
  422. // Determine whether we need to start terminating.
  423. bool needs_terminate = false;
  424. {
  425. KScopedLightLock lk(m_state_lock);
  426. // Check whether we're allowed to terminate.
  427. R_UNLESS(m_state != State::Created, ResultInvalidState);
  428. R_UNLESS(m_state != State::CreatedAttached, ResultInvalidState);
  429. KScopedSchedulerLock sl(m_kernel);
  430. if (m_state == State::Running || m_state == State::RunningAttached ||
  431. m_state == State::Crashed || m_state == State::DebugBreak) {
  432. this->ChangeState(State::Terminating);
  433. needs_terminate = true;
  434. }
  435. }
  436. // If we need to terminate, do so.
  437. if (needs_terminate) {
  438. // Start termination.
  439. if (R_SUCCEEDED(this->StartTermination())) {
  440. // Finish termination.
  441. this->FinishTermination();
  442. } else {
  443. // Register the process as a work task.
  444. m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit,
  445. this);
  446. }
  447. }
  448. R_SUCCEED();
  449. }
  450. Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) {
  451. // Lock ourselves, to prevent concurrent access.
  452. KScopedLightLock lk(m_state_lock);
  453. // Try to find an existing info for the memory.
  454. KSharedMemoryInfo* info = nullptr;
  455. for (auto it = m_shared_memory_list.begin(); it != m_shared_memory_list.end(); ++it) {
  456. if (it->GetSharedMemory() == shmem) {
  457. info = std::addressof(*it);
  458. break;
  459. }
  460. }
  461. // If we didn't find an info, create one.
  462. if (info == nullptr) {
  463. // Allocate a new info.
  464. info = KSharedMemoryInfo::Allocate(m_kernel);
  465. R_UNLESS(info != nullptr, ResultOutOfResource);
  466. // Initialize the info and add it to our list.
  467. info->Initialize(shmem);
  468. m_shared_memory_list.push_back(*info);
  469. }
  470. // Open a reference to the shared memory and its info.
  471. shmem->Open();
  472. info->Open();
  473. R_SUCCEED();
  474. }
  475. void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) {
  476. // Lock ourselves, to prevent concurrent access.
  477. KScopedLightLock lk(m_state_lock);
  478. // Find an existing info for the memory.
  479. KSharedMemoryInfo* info = nullptr;
  480. auto it = m_shared_memory_list.begin();
  481. for (; it != m_shared_memory_list.end(); ++it) {
  482. if (it->GetSharedMemory() == shmem) {
  483. info = std::addressof(*it);
  484. break;
  485. }
  486. }
  487. ASSERT(info != nullptr);
  488. // Close a reference to the info and its memory.
  489. if (info->Close()) {
  490. m_shared_memory_list.erase(it);
  491. KSharedMemoryInfo::Free(m_kernel, info);
  492. }
  493. shmem->Close();
  494. }
  495. Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) {
  496. KThreadLocalPage* tlp = nullptr;
  497. KProcessAddress tlr = 0;
  498. // See if we can get a region from a partially used TLP.
  499. {
  500. KScopedSchedulerLock sl(m_kernel);
  501. if (auto it = m_partially_used_tlp_tree.begin(); it != m_partially_used_tlp_tree.end()) {
  502. tlr = it->Reserve();
  503. ASSERT(tlr != 0);
  504. if (it->IsAllUsed()) {
  505. tlp = std::addressof(*it);
  506. m_partially_used_tlp_tree.erase(it);
  507. m_fully_used_tlp_tree.insert(*tlp);
  508. }
  509. *out = tlr;
  510. R_SUCCEED();
  511. }
  512. }
  513. // Allocate a new page.
  514. tlp = KThreadLocalPage::Allocate(m_kernel);
  515. R_UNLESS(tlp != nullptr, ResultOutOfMemory);
  516. ON_RESULT_FAILURE {
  517. KThreadLocalPage::Free(m_kernel, tlp);
  518. };
  519. // Initialize the new page.
  520. R_TRY(tlp->Initialize(m_kernel, this));
  521. // Reserve a TLR.
  522. tlr = tlp->Reserve();
  523. ASSERT(tlr != 0);
  524. // Insert into our tree.
  525. {
  526. KScopedSchedulerLock sl(m_kernel);
  527. if (tlp->IsAllUsed()) {
  528. m_fully_used_tlp_tree.insert(*tlp);
  529. } else {
  530. m_partially_used_tlp_tree.insert(*tlp);
  531. }
  532. }
  533. // We succeeded!
  534. *out = tlr;
  535. R_SUCCEED();
  536. }
  537. Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
  538. KThreadLocalPage* page_to_free = nullptr;
  539. // Release the region.
  540. {
  541. KScopedSchedulerLock sl(m_kernel);
  542. // Try to find the page in the partially used list.
  543. auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize));
  544. if (it == m_partially_used_tlp_tree.end()) {
  545. // If we don't find it, it has to be in the fully used list.
  546. it = m_fully_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize));
  547. R_UNLESS(it != m_fully_used_tlp_tree.end(), ResultInvalidAddress);
  548. // Release the region.
  549. it->Release(addr);
  550. // Move the page out of the fully used list.
  551. KThreadLocalPage* tlp = std::addressof(*it);
  552. m_fully_used_tlp_tree.erase(it);
  553. if (tlp->IsAllFree()) {
  554. page_to_free = tlp;
  555. } else {
  556. m_partially_used_tlp_tree.insert(*tlp);
  557. }
  558. } else {
  559. // Release the region.
  560. it->Release(addr);
  561. // Handle the all-free case.
  562. KThreadLocalPage* tlp = std::addressof(*it);
  563. if (tlp->IsAllFree()) {
  564. m_partially_used_tlp_tree.erase(it);
  565. page_to_free = tlp;
  566. }
  567. }
  568. }
  569. // If we should free the page it was in, do so.
  570. if (page_to_free != nullptr) {
  571. page_to_free->Finalize();
  572. KThreadLocalPage::Free(m_kernel, page_to_free);
  573. }
  574. R_SUCCEED();
  575. }
  576. bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value) {
  577. if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) {
  578. return rl->Reserve(which, value);
  579. } else {
  580. return true;
  581. }
  582. }
  583. bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout) {
  584. if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) {
  585. return rl->Reserve(which, value, timeout);
  586. } else {
  587. return true;
  588. }
  589. }
  590. void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value) {
  591. if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) {
  592. rl->Release(which, value);
  593. }
  594. }
  595. void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint) {
  596. if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) {
  597. rl->Release(which, value, hint);
  598. }
  599. }
  600. void KProcess::IncrementRunningThreadCount() {
  601. ASSERT(m_num_running_threads.load() >= 0);
  602. ++m_num_running_threads;
  603. }
  604. void KProcess::DecrementRunningThreadCount() {
  605. ASSERT(m_num_running_threads.load() > 0);
  606. if (const auto prev = m_num_running_threads--; prev == 1) {
  607. this->Terminate();
  608. }
  609. }
  610. bool KProcess::EnterUserException() {
  611. // Get the current thread.
  612. KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
  613. ASSERT(this == cur_thread->GetOwnerProcess());
  614. // Check that we haven't already claimed the exception thread.
  615. if (m_exception_thread == cur_thread) {
  616. return false;
  617. }
  618. // Create the wait queue we'll be using.
  619. ThreadQueueImplForKProcessEnterUserException wait_queue(m_kernel,
  620. std::addressof(m_exception_thread));
  621. // Claim the exception thread.
  622. {
  623. // Lock the scheduler.
  624. KScopedSchedulerLock sl(m_kernel);
  625. // Check that we're not terminating.
  626. if (cur_thread->IsTerminationRequested()) {
  627. return false;
  628. }
  629. // If we don't have an exception thread, we can just claim it directly.
  630. if (m_exception_thread == nullptr) {
  631. m_exception_thread = cur_thread;
  632. KScheduler::SetSchedulerUpdateNeeded(m_kernel);
  633. return true;
  634. }
  635. // Otherwise, we need to wait until we don't have an exception thread.
  636. // Add the current thread as a waiter on the current exception thread.
  637. cur_thread->SetKernelAddressKey(
  638. reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1);
  639. m_exception_thread->AddWaiter(cur_thread);
  640. // Wait to claim the exception thread.
  641. cur_thread->BeginWait(std::addressof(wait_queue));
  642. }
  643. // If our wait didn't end due to thread termination, we succeeded.
  644. return ResultTerminationRequested != cur_thread->GetWaitResult();
  645. }
  646. bool KProcess::LeaveUserException() {
  647. return this->ReleaseUserException(GetCurrentThreadPointer(m_kernel));
  648. }
  649. bool KProcess::ReleaseUserException(KThread* thread) {
  650. KScopedSchedulerLock sl(m_kernel);
  651. if (m_exception_thread == thread) {
  652. m_exception_thread = nullptr;
  653. // Remove waiter thread.
  654. bool has_waiters;
  655. if (KThread* next = thread->RemoveKernelWaiterByKey(
  656. std::addressof(has_waiters),
  657. reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1);
  658. next != nullptr) {
  659. next->EndWait(ResultSuccess);
  660. }
  661. KScheduler::SetSchedulerUpdateNeeded(m_kernel);
  662. return true;
  663. } else {
  664. return false;
  665. }
  666. }
  667. void KProcess::RegisterThread(KThread* thread) {
  668. KScopedLightLock lk(m_list_lock);
  669. m_thread_list.push_back(*thread);
  670. }
  671. void KProcess::UnregisterThread(KThread* thread) {
  672. KScopedLightLock lk(m_list_lock);
  673. m_thread_list.erase(m_thread_list.iterator_to(*thread));
  674. }
  675. size_t KProcess::GetUsedUserPhysicalMemorySize() const {
  676. const size_t norm_size = m_page_table.GetNormalMemorySize();
  677. const size_t other_size = m_code_size + m_main_thread_stack_size;
  678. const size_t sec_size = this->GetRequiredSecureMemorySizeNonDefault();
  679. return norm_size + other_size + sec_size;
  680. }
  681. size_t KProcess::GetTotalUserPhysicalMemorySize() const {
  682. // Get the amount of free and used size.
  683. const size_t free_size =
  684. m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax);
  685. const size_t max_size = m_max_process_memory;
  686. // Determine used size.
  687. // NOTE: This does *not* check this->IsDefaultApplicationSystemResource(), unlike
  688. // GetUsedUserPhysicalMemorySize().
  689. const size_t norm_size = m_page_table.GetNormalMemorySize();
  690. const size_t other_size = m_code_size + m_main_thread_stack_size;
  691. const size_t sec_size = this->GetRequiredSecureMemorySize();
  692. const size_t used_size = norm_size + other_size + sec_size;
  693. // NOTE: These function calls will recalculate, introducing a race...it is unclear why Nintendo
  694. // does it this way.
  695. if (used_size + free_size > max_size) {
  696. return max_size;
  697. } else {
  698. return free_size + this->GetUsedUserPhysicalMemorySize();
  699. }
  700. }
  701. size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize() const {
  702. const size_t norm_size = m_page_table.GetNormalMemorySize();
  703. const size_t other_size = m_code_size + m_main_thread_stack_size;
  704. return norm_size + other_size;
  705. }
  706. size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const {
  707. // Get the amount of free and used size.
  708. const size_t free_size =
  709. m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax);
  710. const size_t max_size = m_max_process_memory;
  711. // Determine used size.
  712. // NOTE: This does *not* check this->IsDefaultApplicationSystemResource(), unlike
  713. // GetUsedUserPhysicalMemorySize().
  714. const size_t norm_size = m_page_table.GetNormalMemorySize();
  715. const size_t other_size = m_code_size + m_main_thread_stack_size;
  716. const size_t sec_size = this->GetRequiredSecureMemorySize();
  717. const size_t used_size = norm_size + other_size + sec_size;
  718. // NOTE: These function calls will recalculate, introducing a race...it is unclear why Nintendo
  719. // does it this way.
  720. if (used_size + free_size > max_size) {
  721. return max_size - this->GetRequiredSecureMemorySizeNonDefault();
  722. } else {
  723. return free_size + this->GetUsedNonSystemUserPhysicalMemorySize();
  724. }
  725. }
  726. Result KProcess::Run(s32 priority, size_t stack_size) {
  727. // Lock ourselves, to prevent concurrent access.
  728. KScopedLightLock lk(m_state_lock);
  729. // Validate that we're in a state where we can initialize.
  730. const auto state = m_state;
  731. R_UNLESS(state == State::Created || state == State::CreatedAttached, ResultInvalidState);
  732. // Place a tentative reservation of a thread for this process.
  733. KScopedResourceReservation thread_reservation(this, Svc::LimitableResource::ThreadCountMax);
  734. R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached);
  735. // Ensure that we haven't already allocated stack.
  736. ASSERT(m_main_thread_stack_size == 0);
  737. // Ensure that we're allocating a valid stack.
  738. stack_size = Common::AlignUp(stack_size, PageSize);
  739. R_UNLESS(stack_size + m_code_size <= m_max_process_memory, ResultOutOfMemory);
  740. R_UNLESS(stack_size + m_code_size >= m_code_size, ResultOutOfMemory);
  741. // Place a tentative reservation of memory for our new stack.
  742. KScopedResourceReservation mem_reservation(this, Svc::LimitableResource::PhysicalMemoryMax,
  743. stack_size);
  744. R_UNLESS(mem_reservation.Succeeded(), ResultLimitReached);
  745. // Allocate and map our stack.
  746. KProcessAddress stack_top = 0;
  747. if (stack_size) {
  748. KProcessAddress stack_bottom;
  749. R_TRY(m_page_table.MapPages(std::addressof(stack_bottom), stack_size / PageSize,
  750. KMemoryState::Stack, KMemoryPermission::UserReadWrite));
  751. stack_top = stack_bottom + stack_size;
  752. m_main_thread_stack_size = stack_size;
  753. }
  754. // Ensure our stack is safe to clean up on exit.
  755. ON_RESULT_FAILURE {
  756. if (m_main_thread_stack_size) {
  757. ASSERT(R_SUCCEEDED(m_page_table.UnmapPages(stack_top - m_main_thread_stack_size,
  758. m_main_thread_stack_size / PageSize,
  759. KMemoryState::Stack)));
  760. m_main_thread_stack_size = 0;
  761. }
  762. };
  763. // Set our maximum heap size.
  764. R_TRY(m_page_table.SetMaxHeapSize(m_max_process_memory -
  765. (m_main_thread_stack_size + m_code_size)));
  766. // Initialize our handle table.
  767. R_TRY(this->InitializeHandleTable(m_capabilities.GetHandleTableSize()));
  768. ON_RESULT_FAILURE_2 {
  769. this->FinalizeHandleTable();
  770. };
  771. // Create a new thread for the process.
  772. KThread* main_thread = KThread::Create(m_kernel);
  773. R_UNLESS(main_thread != nullptr, ResultOutOfResource);
  774. SCOPE_EXIT({ main_thread->Close(); });
  775. // Initialize the thread.
  776. R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0,
  777. stack_top, priority, m_ideal_core_id, this));
  778. // Register the thread, and commit our reservation.
  779. KThread::Register(m_kernel, main_thread);
  780. thread_reservation.Commit();
  781. // Add the thread to our handle table.
  782. Handle thread_handle;
  783. R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread));
  784. // Set the thread arguments.
  785. main_thread->GetContext().r[0] = 0;
  786. main_thread->GetContext().r[1] = thread_handle;
  787. // Update our state.
  788. this->ChangeState((state == State::Created) ? State::Running : State::RunningAttached);
  789. ON_RESULT_FAILURE_2 {
  790. this->ChangeState(state);
  791. };
  792. // Suspend for debug, if we should.
  793. if (m_kernel.System().DebuggerEnabled()) {
  794. main_thread->RequestSuspend(SuspendType::Debug);
  795. }
  796. // Run our thread.
  797. R_TRY(main_thread->Run());
  798. // Open a reference to represent that we're running.
  799. this->Open();
  800. // We succeeded! Commit our memory reservation.
  801. mem_reservation.Commit();
  802. R_SUCCEED();
  803. }
  804. Result KProcess::Reset() {
  805. // Lock the process and the scheduler.
  806. KScopedLightLock lk(m_state_lock);
  807. KScopedSchedulerLock sl(m_kernel);
  808. // Validate that we're in a state that we can reset.
  809. R_UNLESS(m_state != State::Terminated, ResultInvalidState);
  810. R_UNLESS(m_is_signaled, ResultInvalidState);
  811. // Clear signaled.
  812. m_is_signaled = false;
  813. R_SUCCEED();
  814. }
  815. Result KProcess::SetActivity(Svc::ProcessActivity activity) {
  816. // Lock ourselves and the scheduler.
  817. KScopedLightLock lk(m_state_lock);
  818. KScopedLightLock list_lk(m_list_lock);
  819. KScopedSchedulerLock sl(m_kernel);
  820. // Validate our state.
  821. R_UNLESS(m_state != State::Terminating, ResultInvalidState);
  822. R_UNLESS(m_state != State::Terminated, ResultInvalidState);
  823. // Either pause or resume.
  824. if (activity == Svc::ProcessActivity::Paused) {
  825. // Verify that we're not suspended.
  826. R_UNLESS(!m_is_suspended, ResultInvalidState);
  827. // Suspend all threads.
  828. auto end = this->GetThreadList().end();
  829. for (auto it = this->GetThreadList().begin(); it != end; ++it) {
  830. it->RequestSuspend(SuspendType::Process);
  831. }
  832. // Set ourselves as suspended.
  833. this->SetSuspended(true);
  834. } else {
  835. ASSERT(activity == Svc::ProcessActivity::Runnable);
  836. // Verify that we're suspended.
  837. R_UNLESS(m_is_suspended, ResultInvalidState);
  838. // Resume all threads.
  839. auto end = this->GetThreadList().end();
  840. for (auto it = this->GetThreadList().begin(); it != end; ++it) {
  841. it->Resume(SuspendType::Process);
  842. }
  843. // Set ourselves as resumed.
  844. this->SetSuspended(false);
  845. }
  846. R_SUCCEED();
  847. }
  848. void KProcess::PinCurrentThread() {
  849. ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
  850. // Get the current thread.
  851. const s32 core_id = GetCurrentCoreId(m_kernel);
  852. KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
  853. // If the thread isn't terminated, pin it.
  854. if (!cur_thread->IsTerminationRequested()) {
  855. // Pin it.
  856. this->PinThread(core_id, cur_thread);
  857. cur_thread->Pin(core_id);
  858. // An update is needed.
  859. KScheduler::SetSchedulerUpdateNeeded(m_kernel);
  860. }
  861. }
  862. void KProcess::UnpinCurrentThread() {
  863. ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
  864. // Get the current thread.
  865. const s32 core_id = GetCurrentCoreId(m_kernel);
  866. KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
  867. // Unpin it.
  868. cur_thread->Unpin();
  869. this->UnpinThread(core_id, cur_thread);
  870. // An update is needed.
  871. KScheduler::SetSchedulerUpdateNeeded(m_kernel);
  872. }
  873. void KProcess::UnpinThread(KThread* thread) {
  874. ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
  875. // Get the thread's core id.
  876. const auto core_id = thread->GetActiveCore();
  877. // Unpin it.
  878. this->UnpinThread(core_id, thread);
  879. thread->Unpin();
  880. // An update is needed.
  881. KScheduler::SetSchedulerUpdateNeeded(m_kernel);
  882. }
  883. Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids,
  884. s32 max_out_count) {
  885. // TODO: use current memory reference
  886. auto& memory = m_kernel.System().ApplicationMemory();
  887. // Lock the list.
  888. KScopedLightLock lk(m_list_lock);
  889. // Iterate over the list.
  890. s32 count = 0;
  891. auto end = this->GetThreadList().end();
  892. for (auto it = this->GetThreadList().begin(); it != end; ++it) {
  893. // If we're within array bounds, write the id.
  894. if (count < max_out_count) {
  895. // Get the thread id.
  896. KThread* thread = std::addressof(*it);
  897. const u64 id = thread->GetId();
  898. // Copy the id to userland.
  899. memory.Write64(out_thread_ids + count * sizeof(u64), id);
  900. }
  901. // Increment the count.
  902. ++count;
  903. }
  904. // We successfully iterated the list.
  905. *out_num_threads = count;
  906. R_SUCCEED();
  907. }
  908. void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {}
  909. KProcess::KProcess(KernelCore& kernel)
  910. : KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel}, m_state_lock{kernel},
  911. m_list_lock{kernel}, m_cond_var{kernel.System()}, m_address_arbiter{kernel.System()},
  912. m_handle_table{kernel} {}
  913. KProcess::~KProcess() = default;
  914. Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
  915. KProcessAddress aslr_space_start, bool is_hbl) {
  916. // Create a resource limit for the process.
  917. const auto physical_memory_size =
  918. m_kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application);
  919. auto* res_limit =
  920. Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size);
  921. // Ensure we maintain a clean state on exit.
  922. SCOPE_EXIT({ res_limit->Close(); });
  923. // Declare flags and code address.
  924. Svc::CreateProcessFlag flag{};
  925. u64 code_address{};
  926. // We are an application.
  927. flag |= Svc::CreateProcessFlag::IsApplication;
  928. // If we are 64-bit, create as such.
  929. if (metadata.Is64BitProgram()) {
  930. flag |= Svc::CreateProcessFlag::Is64Bit;
  931. }
  932. // Set the address space type and code address.
  933. switch (metadata.GetAddressSpaceType()) {
  934. case FileSys::ProgramAddressSpaceType::Is39Bit:
  935. flag |= Svc::CreateProcessFlag::AddressSpace64Bit;
  936. // For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large.
  937. // However, some (buggy) programs/libraries like skyline incorrectly depend on the
  938. // existence of ASLR pages before the entry point, so we will adjust the load address
  939. // to point to about 2GiB into the ASLR region.
  940. code_address = 0x8000'0000;
  941. break;
  942. case FileSys::ProgramAddressSpaceType::Is36Bit:
  943. flag |= Svc::CreateProcessFlag::AddressSpace64BitDeprecated;
  944. code_address = 0x800'0000;
  945. break;
  946. case FileSys::ProgramAddressSpaceType::Is32Bit:
  947. flag |= Svc::CreateProcessFlag::AddressSpace32Bit;
  948. code_address = 0x20'0000;
  949. break;
  950. case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
  951. flag |= Svc::CreateProcessFlag::AddressSpace32BitWithoutAlias;
  952. code_address = 0x20'0000;
  953. break;
  954. }
  955. Svc::CreateProcessParameter params{
  956. .name = {},
  957. .version = {},
  958. .program_id = metadata.GetTitleID(),
  959. .code_address = code_address + GetInteger(aslr_space_start),
  960. .code_num_pages = static_cast<s32>(code_size / PageSize),
  961. .flags = flag,
  962. .reslimit = Svc::InvalidHandle,
  963. .system_resource_num_pages = static_cast<s32>(metadata.GetSystemResourceSize() / PageSize),
  964. };
  965. // Set the process name.
  966. const auto& name = metadata.GetName();
  967. static_assert(sizeof(params.name) <= sizeof(name));
  968. std::memcpy(params.name.data(), name.data(), sizeof(params.name));
  969. // Initialize for application process.
  970. R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit,
  971. KMemoryManager::Pool::Application, aslr_space_start));
  972. // Assign remaining properties.
  973. m_is_hbl = is_hbl;
  974. m_ideal_core_id = metadata.GetMainThreadCore();
  975. // Set up emulation context.
  976. this->InitializeInterfaces();
  977. // We succeeded.
  978. R_SUCCEED();
  979. }
  980. void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
  981. const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
  982. Svc::MemoryPermission permission) {
  983. m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
  984. };
  985. this->GetMemory().WriteBlock(base_addr, code_set.memory.data(), code_set.memory.size());
  986. ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute);
  987. ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read);
  988. ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite);
  989. #ifdef HAS_NCE
  990. if (Settings::IsNceEnabled()) {
  991. auto& buffer = m_kernel.System().DeviceMemory().buffer;
  992. const auto& code = code_set.CodeSegment();
  993. const auto& patch = code_set.PatchSegment();
  994. buffer.Protect(GetInteger(base_addr + code.addr), code.size, true, true, true);
  995. buffer.Protect(GetInteger(base_addr + patch.addr), patch.size, true, true, true);
  996. ReprotectSegment(code_set.PatchSegment(), Svc::MemoryPermission::None);
  997. }
  998. #endif
  999. }
  1000. void KProcess::InitializeInterfaces() {
  1001. this->GetMemory().SetCurrentPageTable(*this);
  1002. #ifdef HAS_NCE
  1003. if (this->Is64Bit() && Settings::IsNceEnabled()) {
  1004. for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  1005. m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i);
  1006. }
  1007. } else
  1008. #endif
  1009. if (this->Is64Bit()) {
  1010. for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  1011. m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic64>(
  1012. m_kernel.System(), m_kernel.IsMulticore(), this,
  1013. static_cast<Core::DynarmicExclusiveMonitor&>(m_kernel.GetExclusiveMonitor()), i);
  1014. }
  1015. } else {
  1016. for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  1017. m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic32>(
  1018. m_kernel.System(), m_kernel.IsMulticore(), this,
  1019. static_cast<Core::DynarmicExclusiveMonitor&>(m_kernel.GetExclusiveMonitor()), i);
  1020. }
  1021. }
  1022. }
  1023. bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) {
  1024. const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
  1025. return wp.type == DebugWatchpointType::None;
  1026. })};
  1027. if (watch == m_watchpoints.end()) {
  1028. return false;
  1029. }
  1030. watch->start_address = addr;
  1031. watch->end_address = addr + size;
  1032. watch->type = type;
  1033. for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
  1034. page += PageSize) {
  1035. m_debug_page_refcounts[page]++;
  1036. this->GetMemory().MarkRegionDebug(page, PageSize, true);
  1037. }
  1038. return true;
  1039. }
  1040. bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) {
  1041. const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
  1042. return wp.start_address == addr && wp.end_address == addr + size && wp.type == type;
  1043. })};
  1044. if (watch == m_watchpoints.end()) {
  1045. return false;
  1046. }
  1047. watch->start_address = 0;
  1048. watch->end_address = 0;
  1049. watch->type = DebugWatchpointType::None;
  1050. for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
  1051. page += PageSize) {
  1052. m_debug_page_refcounts[page]--;
  1053. if (!m_debug_page_refcounts[page]) {
  1054. this->GetMemory().MarkRegionDebug(page, PageSize, false);
  1055. }
  1056. }
  1057. return true;
  1058. }
  1059. Core::Memory::Memory& KProcess::GetMemory() const {
  1060. // TODO: per-process memory
  1061. return m_kernel.System().ApplicationMemory();
  1062. }
  1063. } // namespace Kernel