From e200dfb48c138e2346f31a0656b92ac7097dafc2 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 9 Oct 2024 15:12:46 -0700 Subject: [PATCH] kern: move KTargetSystem into .rodata, split init/verify --- .../nintendo/nx/kern_k_system_control.hpp | 1 + .../mesosphere/kern_k_system_control_base.hpp | 1 + .../mesosphere/kern_k_target_system.hpp | 49 +++++++++-------- .../nintendo/nx/kern_k_system_control.cpp | 53 +++++++++++++++---- .../source/kern_k_system_control_base.cpp | 29 +++------- .../source/kern_kernel_instantiations.cpp | 4 ++ 6 files changed, 83 insertions(+), 54 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp index a0cfce5a1..8e1829849 100644 --- a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp +++ b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_system_control.hpp @@ -45,6 +45,7 @@ namespace ams::kern::board::nintendo::nx { }; public: /* Initialization. */ + static NOINLINE void ConfigureKTargetSystem(); static NOINLINE void InitializePhase1(); static NOINLINE void InitializePhase2(); static NOINLINE u32 GetCreateProcessMemoryPool(); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp index bb1c1ff0f..ab3a18c5b 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp @@ -69,6 +69,7 @@ namespace ams::kern { static NOINLINE void InitializePhase1Base(u64 seed); public: /* Initialization. */ + static NOINLINE void ConfigureKTargetSystem(); static NOINLINE void InitializePhase1(); static NOINLINE void InitializePhase2(); static NOINLINE u32 GetCreateProcessMemoryPool(); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp index 87b72c0fa..24220bed0 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp @@ -24,29 +24,36 @@ namespace ams::kern { friend class KSystemControlBase; friend class KSystemControl; private: - static inline constinit bool s_is_debug_mode; - static inline constinit bool s_enable_debug_logging; - static inline constinit bool s_enable_user_exception_handlers; - static inline constinit bool s_enable_debug_memory_fill; - static inline constinit bool s_enable_user_pmu_access; - static inline constinit bool s_enable_kernel_debugging; - static inline constinit bool s_enable_dynamic_resource_limits; + struct KTargetSystemData { + bool is_debug_mode; + bool enable_debug_logging; + bool enable_user_exception_handlers; + bool enable_debug_memory_fill; + bool enable_user_pmu_access; + bool enable_kernel_debugging; + bool enable_dynamic_resource_limits; + }; private: - static ALWAYS_INLINE void SetIsDebugMode(bool en) { s_is_debug_mode = en; } - static ALWAYS_INLINE void EnableDebugLogging(bool en) { s_enable_debug_logging = en; } - static ALWAYS_INLINE void EnableUserExceptionHandlers(bool en) { s_enable_user_exception_handlers = en; } - static ALWAYS_INLINE void EnableDebugMemoryFill(bool en) { s_enable_debug_memory_fill = en; } - static ALWAYS_INLINE void EnableUserPmuAccess(bool en) { s_enable_user_pmu_access = en; } - static ALWAYS_INLINE void EnableKernelDebugging(bool en) { s_enable_kernel_debugging = en; } - static ALWAYS_INLINE void EnableDynamicResourceLimits(bool en) { s_enable_dynamic_resource_limits = en; } + static inline constinit bool s_is_initialized = false; + static inline constinit const volatile KTargetSystemData s_data = { + .is_debug_mode = true, + .enable_debug_logging = true, + .enable_user_exception_handlers = true, + .enable_debug_memory_fill = true, + .enable_user_pmu_access = true, + .enable_kernel_debugging = true, + .enable_dynamic_resource_limits = false, + }; + private: + static ALWAYS_INLINE void SetInitialized() { s_is_initialized = true; } public: - static ALWAYS_INLINE bool IsDebugMode() { return s_is_debug_mode; } - static ALWAYS_INLINE bool IsDebugLoggingEnabled() { return s_enable_debug_logging; } - static ALWAYS_INLINE bool IsUserExceptionHandlersEnabled() { return s_enable_user_exception_handlers; } - static ALWAYS_INLINE bool IsDebugMemoryFillEnabled() { return s_enable_debug_memory_fill; } - static ALWAYS_INLINE bool IsUserPmuAccessEnabled() { return s_enable_user_pmu_access; } - static ALWAYS_INLINE bool IsKernelDebuggingEnabled() { return s_enable_kernel_debugging; } - static ALWAYS_INLINE bool IsDynamicResourceLimitsEnabled() { return s_enable_dynamic_resource_limits; } + static ALWAYS_INLINE bool IsDebugMode() { return s_is_initialized && s_data.is_debug_mode; } + static ALWAYS_INLINE bool IsDebugLoggingEnabled() { return s_is_initialized && s_data.enable_debug_logging; } + static ALWAYS_INLINE bool IsUserExceptionHandlersEnabled() { return s_is_initialized && s_data.enable_user_exception_handlers; } + static ALWAYS_INLINE bool IsDebugMemoryFillEnabled() { return s_is_initialized && s_data.enable_debug_memory_fill; } + static ALWAYS_INLINE bool IsUserPmuAccessEnabled() { return s_is_initialized && s_data.enable_user_pmu_access; } + static ALWAYS_INLINE bool IsKernelDebuggingEnabled() { return s_is_initialized && s_data.enable_kernel_debugging; } + static ALWAYS_INLINE bool IsDynamicResourceLimitsEnabled() { return s_is_initialized && s_data.enable_dynamic_resource_limits; } }; } \ No newline at end of file diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index 52a894d1c..8050f78e0 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -26,7 +26,7 @@ namespace ams::kern::board::nintendo::nx { constexpr size_t SecureSizeMax = util::AlignDown(512_MB - 1, SecureAlignment); /* Global variables for panic. */ - constinit bool g_call_smc_on_panic; + constinit const volatile bool g_call_smc_on_panic = false; /* Global variables for secure memory. */ constinit KSpinLock g_secure_applet_lock; @@ -401,34 +401,67 @@ namespace ams::kern::board::nintendo::nx { } /* System Initialization. */ - void KSystemControl::InitializePhase1() { + void KSystemControl::ConfigureKTargetSystem() { /* Configure KTargetSystem. */ + volatile auto *ts = const_cast(std::addressof(KTargetSystem::s_data)); { /* Set IsDebugMode. */ { - KTargetSystem::SetIsDebugMode(GetConfigBool(smc::ConfigItem::IsDebugMode)); + ts->is_debug_mode = GetConfigBool(smc::ConfigItem::IsDebugMode); /* If debug mode, we want to initialize uart logging. */ - KTargetSystem::EnableDebugLogging(KTargetSystem::IsDebugMode()); + ts->enable_debug_logging = ts->is_debug_mode; } /* Set Kernel Configuration. */ { const auto kernel_config = util::BitPack32{GetConfigU32(smc::ConfigItem::KernelConfiguration)}; - KTargetSystem::EnableDebugMemoryFill(kernel_config.Get()); - KTargetSystem::EnableUserExceptionHandlers(kernel_config.Get()); - KTargetSystem::EnableDynamicResourceLimits(!kernel_config.Get()); - KTargetSystem::EnableUserPmuAccess(kernel_config.Get()); + ts->enable_debug_memory_fill = kernel_config.Get(); + ts->enable_user_exception_handlers = kernel_config.Get(); + ts->enable_dynamic_resource_limits = !kernel_config.Get(); + ts->enable_user_pmu_access = kernel_config.Get(); - g_call_smc_on_panic = kernel_config.Get(); + /* Configure call smc on panic. */ + *const_cast(std::addressof(g_call_smc_on_panic)) = kernel_config.Get(); } /* Set Kernel Debugging. */ { /* NOTE: This is used to restrict access to SvcKernelDebug/SvcChangeKernelTraceState. */ /* Mesosphere may wish to not require this, as we'd ideally keep ProgramVerification enabled for userland. */ - KTargetSystem::EnableKernelDebugging(GetConfigBool(smc::ConfigItem::DisableProgramVerification)); + ts->enable_kernel_debugging = GetConfigBool(smc::ConfigItem::DisableProgramVerification); + } + } + } + + void KSystemControl::InitializePhase1() { + /* Enable KTargetSystem. */ + KTargetSystem::SetInitialized(); + + /* Check KTargetSystem was configured correctly. */ + { + /* Check IsDebugMode. */ + { + MESOSPHERE_ABORT_UNLESS(KTargetSystem::IsDebugMode() == GetConfigBool(smc::ConfigItem::IsDebugMode)); + MESOSPHERE_ABORT_UNLESS(KTargetSystem::IsDebugLoggingEnabled() == GetConfigBool(smc::ConfigItem::IsDebugMode)); + } + + /* Check Kernel Configuration. */ + { + const auto kernel_config = util::BitPack32{GetConfigU32(smc::ConfigItem::KernelConfiguration)}; + + MESOSPHERE_ABORT_UNLESS(KTargetSystem::IsDebugMemoryFillEnabled() == kernel_config.Get()); + MESOSPHERE_ABORT_UNLESS(KTargetSystem::IsUserExceptionHandlersEnabled() == kernel_config.Get()); + MESOSPHERE_ABORT_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled() == !kernel_config.Get()); + MESOSPHERE_ABORT_UNLESS(KTargetSystem::IsUserPmuAccessEnabled() == kernel_config.Get()); + + MESOSPHERE_ABORT_UNLESS(g_call_smc_on_panic == kernel_config.Get()); + } + + /* Check Kernel Debugging. */ + { + MESOSPHERE_ABORT_UNLESS(KTargetSystem::IsKernelDebuggingEnabled() == GetConfigBool(smc::ConfigItem::DisableProgramVerification)); } } diff --git a/libraries/libmesosphere/source/kern_k_system_control_base.cpp b/libraries/libmesosphere/source/kern_k_system_control_base.cpp index fe0b56996..025ec4f9c 100644 --- a/libraries/libmesosphere/source/kern_k_system_control_base.cpp +++ b/libraries/libmesosphere/source/kern_k_system_control_base.cpp @@ -124,31 +124,14 @@ namespace ams::kern { } /* System Initialization. */ + void KSystemControlBase::ConfigureKTargetSystem() { + /* By default, use the default config set in the KTargetSystem header. */ + } + void KSystemControlBase::InitializePhase1() { - /* Configure KTargetSystem. */ + /* Enable KTargetSystem. */ { - /* Set IsDebugMode. */ - { - KTargetSystem::SetIsDebugMode(true); - - /* If debug mode, we want to initialize uart logging. */ - KTargetSystem::EnableDebugLogging(true); - } - - /* Set Kernel Configuration. */ - { - KTargetSystem::EnableDebugMemoryFill(false); - KTargetSystem::EnableUserExceptionHandlers(true); - KTargetSystem::EnableDynamicResourceLimits(true); - KTargetSystem::EnableUserPmuAccess(false); - } - - /* Set Kernel Debugging. */ - { - /* NOTE: This is used to restrict access to SvcKernelDebug/SvcChangeKernelTraceState. */ - /* Mesosphere may wish to not require this, as we'd ideally keep ProgramVerification enabled for userland. */ - KTargetSystem::EnableKernelDebugging(true); - } + KTargetSystem::SetInitialized(); } /* Initialize random and resource limit. */ diff --git a/mesosphere/kernel/source/kern_kernel_instantiations.cpp b/mesosphere/kernel/source/kern_kernel_instantiations.cpp index 6adff0754..d01ddd151 100644 --- a/mesosphere/kernel/source/kern_kernel_instantiations.cpp +++ b/mesosphere/kernel/source/kern_kernel_instantiations.cpp @@ -111,4 +111,8 @@ namespace ams::kern { KThread &Kernel::GetMainThread(s32 core_id) { return g_main_threads.m_arr[core_id]; } KThread &Kernel::GetIdleThread(s32 core_id) { return g_idle_threads.m_arr[core_id]; } + __attribute__((constructor)) void ConfigureKTargetSystem() { + KSystemControl::ConfigureKTargetSystem(); + } + }