From 39a95d402322cd57a3f4faf8c79195a63d2c2f1d Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 11 Oct 2023 09:13:59 -0700 Subject: [PATCH] kern: implement new default application system resource field in KProcess --- .../include/mesosphere/kern_k_process.hpp | 15 +++- .../libmesosphere/source/kern_k_process.cpp | 81 +++++++++++++------ 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 33adfe097..3258d41e2 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -76,6 +76,7 @@ namespace ams::kern { bool m_is_signaled; bool m_is_initialized; bool m_is_application; + bool m_is_default_application_system_resource; char m_name[13]; util::Atomic m_num_running_threads; u32 m_flags; @@ -178,6 +179,8 @@ namespace ams::kern { constexpr bool IsApplication() const { return m_is_application; } + constexpr bool IsDefaultApplicationSystemResource() const { return m_is_default_application_system_resource; } + constexpr bool IsSuspended() const { return m_is_suspended; } constexpr void SetSuspended(bool suspended) { m_is_suspended = suspended; } @@ -280,12 +283,20 @@ namespace ams::kern { void IncrementRunningThreadCount(); void DecrementRunningThreadCount(); + size_t GetRequiredSecureMemorySizeNonDefault() const { + return (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) ? static_cast(m_system_resource)->CalculateRequiredSecureMemorySize() : 0; + } + + size_t GetRequiredSecureMemorySize() const { + return m_system_resource->IsSecureResource() ? static_cast(m_system_resource)->CalculateRequiredSecureMemorySize() : 0; + } + size_t GetTotalSystemResourceSize() const { - return m_system_resource->IsSecureResource() ? static_cast(m_system_resource)->GetSize() : 0; + return (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) ? static_cast(m_system_resource)->GetSize() : 0; } size_t GetUsedSystemResourceSize() const { - return m_system_resource->IsSecureResource() ? static_cast(m_system_resource)->GetUsedSize() : 0; + return (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) ? static_cast(m_system_resource)->GetUsedSize() : 0; } void SetRunningThread(s32 core, KThread *thread, u64 idle_count, u64 switch_count) { diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index d94ced156..9dbd3a4f4 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -263,28 +263,47 @@ namespace ams::kern { MESOSPHERE_ASSERT(res_limit != nullptr); MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast(params.code_num_pages)); - /* Determine is application. */ - const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0; - /* Set members. */ - m_memory_pool = pool; - m_resource_limit = res_limit; - m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource()); - m_is_immortal = immortal; + m_memory_pool = pool; + m_resource_limit = res_limit; + m_is_default_application_system_resource = false; + m_is_immortal = immortal; - /* Open reference to our system resource. */ - m_system_resource->Open(); + /* Setup our system resource. */ + if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) { + /* Create a secure system resource. */ + KSecureSystemResource *secure_resource = KSecureSystemResource::Create(); + R_UNLESS(secure_resource != nullptr, svc::ResultOutOfResource()); + + ON_RESULT_FAILURE { secure_resource->Close(); }; + + /* Initialize the secure resource. */ + R_TRY(secure_resource->Initialize(system_resource_num_pages * PageSize, m_resource_limit, m_memory_pool)); + + /* Set our system resource. */ + m_system_resource = secure_resource; + } else { + /* Use the system-wide system resource. */ + const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication); + m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource()); + + m_is_default_application_system_resource = is_app; + + /* Open reference to the system resource. */ + m_system_resource->Open(); + } + + /* Ensure we clean up our secure resource, if we fail. */ + ON_RESULT_FAILURE { m_system_resource->Close(); }; /* Setup page table. */ - /* NOTE: Nintendo passes process ID despite not having set it yet. */ - /* This goes completely unused, but even so... */ { const auto as_type = static_cast(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask); const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0; R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit)); } - ON_RESULT_FAILURE { m_page_table.Finalize(); }; + ON_RESULT_FAILURE_2 { m_page_table.Finalize(); }; /* Ensure we can insert the code region. */ R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, KMemoryState_Code), svc::ResultInvalidMemoryRegion()); @@ -315,9 +334,10 @@ namespace ams::kern { MESOSPHERE_ASSERT(res_limit != nullptr); /* Set pool and resource limit. */ - m_memory_pool = pool; - m_resource_limit = res_limit; - m_is_immortal = false; + m_memory_pool = pool; + m_resource_limit = res_limit; + m_is_default_application_system_resource = false; + m_is_immortal = false; /* Get the memory sizes. */ const size_t code_num_pages = params.code_num_pages; @@ -348,6 +368,8 @@ namespace ams::kern { const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication); m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource()); + m_is_default_application_system_resource = is_app; + /* Open reference to the system resource. */ m_system_resource->Open(); } @@ -356,8 +378,6 @@ namespace ams::kern { ON_RESULT_FAILURE { m_system_resource->Close(); }; /* Setup page table. */ - /* NOTE: Nintendo passes process ID despite not having set it yet. */ - /* This goes completely unused, but even so... */ { const auto as_type = static_cast(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask); const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0; @@ -848,7 +868,7 @@ namespace ams::kern { size_t KProcess::GetUsedUserPhysicalMemorySize() const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; - const size_t sec_size = m_system_resource->IsSecureResource() ? static_cast(m_system_resource)->CalculateRequiredSecureMemorySize() : 0; + const size_t sec_size = this->GetRequiredSecureMemorySizeNonDefault(); return norm_size + other_size + sec_size; } @@ -856,13 +876,20 @@ namespace ams::kern { size_t KProcess::GetTotalUserPhysicalMemorySize() const { /* Get the amount of free and used size. */ const size_t free_size = m_resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax); - const size_t used_size = this->GetUsedUserPhysicalMemorySize(); const size_t max_size = m_max_process_memory; + /* Determine used size. */ + /* NOTE: This does *not* check this->IsDefaultApplicationSystemResource(), unlike GetUsedUserPhysicalMemorySize(). */ + const size_t norm_size = m_page_table.GetNormalMemorySize(); + const size_t other_size = m_code_size + m_main_thread_stack_size; + const size_t sec_size = this->GetRequiredSecureMemorySize(); + const size_t used_size = norm_size + other_size + sec_size; + + /* NOTE: These function calls will recalculate, introducing a race...it is unclear why Nintendo does it this way. */ if (used_size + free_size > max_size) { return max_size; } else { - return free_size + used_size; + return free_size + this->GetUsedUserPhysicalMemorySize(); } } @@ -876,14 +903,20 @@ namespace ams::kern { size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const { /* Get the amount of free and used size. */ const size_t free_size = m_resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax); - const size_t used_size = this->GetUsedUserPhysicalMemorySize(); - const size_t sec_size = m_system_resource->IsSecureResource() ? static_cast(m_system_resource)->CalculateRequiredSecureMemorySize() : 0; const size_t max_size = m_max_process_memory; + /* Determine used size. */ + /* NOTE: This does *not* check this->IsDefaultApplicationSystemResource(), unlike GetUsedUserPhysicalMemorySize(). */ + const size_t norm_size = m_page_table.GetNormalMemorySize(); + const size_t other_size = m_code_size + m_main_thread_stack_size; + const size_t sec_size = this->GetRequiredSecureMemorySize(); + const size_t used_size = norm_size + other_size + sec_size; + + /* NOTE: These function calls will recalculate, introducing a race...it is unclear why Nintendo does it this way. */ if (used_size + free_size > max_size) { - return max_size - sec_size; + return max_size - this->GetRequiredSecureMemorySizeNonDefault(); } else { - return free_size + used_size - sec_size; + return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(); } }