kern: support immortal processes

This commit is contained in:
Michael Scire 2021-04-07 08:23:21 -07:00 committed by SciresM
parent 256eb92f4c
commit 2f930c2d5f
4 changed files with 27 additions and 17 deletions

View file

@ -70,6 +70,7 @@ namespace ams::kern {
constexpr bool Is64Bit() const { return (m_flags & (1 << 3)); } constexpr bool Is64Bit() const { return (m_flags & (1 << 3)); }
constexpr bool Is64BitAddressSpace() const { return (m_flags & (1 << 4)); } constexpr bool Is64BitAddressSpace() const { return (m_flags & (1 << 4)); }
constexpr bool UsesSecureMemory() const { return (m_flags & (1 << 5)); } constexpr bool UsesSecureMemory() const { return (m_flags & (1 << 5)); }
constexpr bool IsImmortal() const { return (m_flags & (1 << 6)); }
constexpr u32 GetRxAddress() const { return m_rx_address; } constexpr u32 GetRxAddress() const { return m_rx_address; }
constexpr u32 GetRxSize() const { return m_rx_size; } constexpr u32 GetRxSize() const { return m_rx_size; }
@ -117,6 +118,7 @@ namespace ams::kern {
constexpr bool Is64Bit() const { return m_kip_header->Is64Bit(); } constexpr bool Is64Bit() const { return m_kip_header->Is64Bit(); }
constexpr bool Is64BitAddressSpace() const { return m_kip_header->Is64BitAddressSpace(); } constexpr bool Is64BitAddressSpace() const { return m_kip_header->Is64BitAddressSpace(); }
constexpr bool UsesSecureMemory() const { return m_kip_header->UsesSecureMemory(); } constexpr bool UsesSecureMemory() const { return m_kip_header->UsesSecureMemory(); }
constexpr bool IsImmortal() const { return m_kip_header->IsImmortal(); }
bool Attach(u8 *bin) { bool Attach(u8 *bin) {
if (KInitialProcessHeader *header = reinterpret_cast<KInitialProcessHeader *>(bin); header->IsValid()) { if (KInitialProcessHeader *header = reinterpret_cast<KInitialProcessHeader *>(bin); header->IsValid()) {

View file

@ -98,6 +98,7 @@ namespace ams::kern {
SharedMemoryInfoList m_shared_memory_list{}; SharedMemoryInfoList m_shared_memory_list{};
BetaList m_beta_list{}; BetaList m_beta_list{};
bool m_is_suspended{}; bool m_is_suspended{};
bool m_is_immortal{};
bool m_is_jit_debug{}; bool m_is_jit_debug{};
ams::svc::DebugEvent m_jit_debug_event_type{}; ams::svc::DebugEvent m_jit_debug_event_type{};
ams::svc::DebugException m_jit_debug_exception_type{}; ams::svc::DebugException m_jit_debug_exception_type{};
@ -143,7 +144,7 @@ namespace ams::kern {
KProcess() { /* ... */ } KProcess() { /* ... */ }
virtual ~KProcess() { /* ... */ } virtual ~KProcess() { /* ... */ }
Result Initialize(const ams::svc::CreateProcessParameter &params, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool); Result Initialize(const ams::svc::CreateProcessParameter &params, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool, bool immortal);
Result Initialize(const ams::svc::CreateProcessParameter &params, svc::KUserPointer<const u32 *> caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool); Result Initialize(const ams::svc::CreateProcessParameter &params, svc::KUserPointer<const u32 *> caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool);
void Exit(); void Exit();

View file

@ -118,7 +118,7 @@ namespace ams::kern {
MESOSPHERE_ABORT_UNLESS(new_process != nullptr); MESOSPHERE_ABORT_UNLESS(new_process != nullptr);
/* Initialize the process. */ /* Initialize the process. */
MESOSPHERE_R_ABORT_UNLESS(new_process->Initialize(params, pg, reader.GetCapabilities(), reader.GetNumCapabilities(), std::addressof(Kernel::GetSystemResourceLimit()), pool)); MESOSPHERE_R_ABORT_UNLESS(new_process->Initialize(params, pg, reader.GetCapabilities(), reader.GetNumCapabilities(), std::addressof(Kernel::GetSystemResourceLimit()), pool, reader.IsImmortal()));
} }
} }

View file

@ -231,7 +231,7 @@ namespace ams::kern {
return ResultSuccess(); return ResultSuccess();
} }
Result KProcess::Initialize(const ams::svc::CreateProcessParameter &params, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool) { Result KProcess::Initialize(const ams::svc::CreateProcessParameter &params, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool, bool immortal) {
MESOSPHERE_ASSERT_THIS(); MESOSPHERE_ASSERT_THIS();
MESOSPHERE_ASSERT(res_limit != nullptr); MESOSPHERE_ASSERT(res_limit != nullptr);
MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast<size_t>(params.code_num_pages)); MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast<size_t>(params.code_num_pages));
@ -241,6 +241,7 @@ namespace ams::kern {
m_resource_limit = res_limit; m_resource_limit = res_limit;
m_system_resource_address = Null<KVirtualAddress>; m_system_resource_address = Null<KVirtualAddress>;
m_system_resource_num_pages = 0; m_system_resource_num_pages = 0;
m_is_immortal = immortal;
/* Setup page table. */ /* Setup page table. */
/* NOTE: Nintendo passes process ID despite not having set it yet. */ /* NOTE: Nintendo passes process ID despite not having set it yet. */
@ -289,6 +290,7 @@ namespace ams::kern {
/* Set pool and resource limit. */ /* Set pool and resource limit. */
m_memory_pool = pool; m_memory_pool = pool;
m_resource_limit = res_limit; m_resource_limit = res_limit;
m_is_immortal = false;
/* Get the memory sizes. */ /* Get the memory sizes. */
const size_t code_num_pages = params.code_num_pages; const size_t code_num_pages = params.code_num_pages;
@ -406,9 +408,11 @@ namespace ams::kern {
} }
Result KProcess::StartTermination() { Result KProcess::StartTermination() {
/* Finalize the handle table, when we're done. */ /* Finalize the handle table when we're done, if the process isn't immortal. */
ON_SCOPE_EXIT { ON_SCOPE_EXIT {
m_handle_table.Finalize(); if (!m_is_immortal) {
m_handle_table.Finalize();
}
}; };
/* Terminate child threads other than the current one. */ /* Terminate child threads other than the current one. */
@ -416,20 +420,23 @@ namespace ams::kern {
} }
void KProcess::FinishTermination() { void KProcess::FinishTermination() {
/* Release resource limit hint. */ /* Only allow termination to occur if the process isn't immortal. */
if (m_resource_limit != nullptr) { if (!m_is_immortal) {
m_memory_release_hint = this->GetUsedUserPhysicalMemorySize(); /* Release resource limit hint. */
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint); if (m_resource_limit != nullptr) {
} m_memory_release_hint = this->GetUsedUserPhysicalMemorySize();
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint);
}
/* Change state. */ /* Change state. */
{ {
KScopedSchedulerLock sl; KScopedSchedulerLock sl;
this->ChangeState(State_Terminated); this->ChangeState(State_Terminated);
} }
/* Close. */ /* Close. */
this->Close(); this->Close();
}
} }
void KProcess::Exit() { void KProcess::Exit() {