diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 4a45ade8a..dcc66f7d5 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -113,6 +113,7 @@ namespace ams::kern { u64 m_running_thread_idle_counts[cpu::NumCores]; u64 m_running_thread_switch_counts[cpu::NumCores]; KThread *m_pinned_threads[cpu::NumCores]; + s64 m_exit_tag; util::Atomic m_cpu_time; util::Atomic m_num_process_switches; util::Atomic m_num_thread_switches; @@ -142,11 +143,11 @@ namespace ams::kern { m_pinned_threads[core_id] = nullptr; } public: - explicit KProcess() : m_is_initialized(false) { /* ... */ } + explicit KProcess() : m_is_initialized(false), m_exit_tag(-1ll) { /* ... */ } Result Initialize(const ams::svc::CreateProcessParameter ¶ms, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool, bool immortal); Result Initialize(const ams::svc::CreateProcessParameter ¶ms, svc::KUserPointer caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool); - void Exit(); + void Exit(s64 exit_tag); constexpr const char *GetName() const { return m_name; } @@ -155,10 +156,13 @@ namespace ams::kern { constexpr u64 GetProcessId() const { return m_process_id; } constexpr State GetState() const { return m_state; } + + constexpr s64 GetExitTag() const { return m_exit_tag; } constexpr u64 GetCoreMask() const { return m_capabilities.GetCoreMask(); } constexpr u64 GetPhysicalCoreMask() const { return m_capabilities.GetPhysicalCoreMask(); } constexpr u64 GetPriorityMask() const { return m_capabilities.GetPriorityMask(); } + constexpr u32 GetIntendedKernelMajorVersion() const { return m_capabilities.GetIntendedKernelMajorVersion(); } constexpr s32 GetIdealCoreId() const { return m_ideal_core_id; } constexpr void SetIdealCoreId(s32 core_id) { m_ideal_core_id = core_id; } @@ -184,7 +188,7 @@ namespace ams::kern { constexpr bool IsSuspended() const { return m_is_suspended; } constexpr void SetSuspended(bool suspended) { m_is_suspended = suspended; } - Result Terminate(); + Result Terminate(s64 exit_tag); constexpr bool IsTerminated() const { return m_state == State_Terminated; @@ -410,6 +414,10 @@ namespace ams::kern { this->NotifyAvailable(); } } + + void SetExitTag(s64 exit_tag) { + m_exit_tag = exit_tag; + } ALWAYS_INLINE Result InitializeHandleTable(s32 size) { /* Try to initialize the handle table. */ diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp index 949fd45ba..09cbac7b7 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_target_system.hpp @@ -26,6 +26,7 @@ namespace ams::kern { private: struct KTargetSystemData { bool is_not_debug_mode; + bool is_not_debug_mode2; bool disable_debug_logging; bool disable_user_exception_handlers; bool disable_debug_memory_fill; @@ -37,6 +38,7 @@ namespace ams::kern { static inline constinit bool s_is_uninitialized = true; static inline constinit const volatile KTargetSystemData s_data = { .is_not_debug_mode = false, + .is_not_debug_mode2 = false, .disable_debug_logging = false, .disable_user_exception_handlers = false, .disable_debug_memory_fill = false, @@ -48,6 +50,7 @@ namespace ams::kern { static ALWAYS_INLINE void SetInitialized() { s_is_uninitialized = false; } public: static ALWAYS_INLINE bool IsDebugMode() { return !(s_is_uninitialized | s_data.is_not_debug_mode); } + static ALWAYS_INLINE bool IsDebugMode2() { return !(s_is_uninitialized | s_data.is_not_debug_mode2); } static ALWAYS_INLINE bool IsDebugLoggingEnabled() { return !(s_is_uninitialized | s_data.disable_debug_logging); } static ALWAYS_INLINE bool IsUserExceptionHandlersEnabled() { return !(s_is_uninitialized | s_data.disable_user_exception_handlers); } static ALWAYS_INLINE bool IsDebugMemoryFillEnabled() { return !(s_is_uninitialized | s_data.disable_debug_memory_fill); } diff --git a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp index 4839349da..36d7f9b2a 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp @@ -220,6 +220,8 @@ namespace ams::kern::arch::arm64::cpu { virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override { MESOSPHERE_UNUSED(interrupt_id); + /* TODO: 23.0.0+ now yields here while m_target_cores doesn't have the current core id bit set. */ + /* Evaluate if we should do the same. */ this->ProcessOperation(); m_target_cores &= ~(1ul << GetCurrentCoreId()); return nullptr; diff --git a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp index 712ac7bd7..bfa6165a0 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_exception_handlers.cpp @@ -381,7 +381,7 @@ namespace ams::kern::arch::arm64 { } /* Exit the current process. */ - cur_process.Exit(); + cur_process.Exit(-1ll); } } @@ -548,7 +548,7 @@ namespace ams::kern::arch::arm64 { MESOSPHERE_EXCEPTION_LOG("Exception occurred. "); /* Exit the current process. */ - GetCurrentProcess().Exit(); + GetCurrentProcess().Exit(-1ll); } /* NOTE: This function is called from ASM. */ 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 2cc6f0f81..20aa5eaa2 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 @@ -411,7 +411,10 @@ namespace ams::kern::board::nintendo::nx { { /* Set whether we're in debug mode. */ { - ts->is_not_debug_mode = !GetConfigBool(smc::ConfigItem::IsDebugMode); + ts->is_not_debug_mode = !GetConfigBool(smc::ConfigItem::IsDebugMode); + + /* TODO: 23.0.0+ split debug mode into 2 fields. Implement this properly for better accuracy. */ + ts->is_not_debug_mode2 = ts->is_not_debug_mode; /* If we're not in debug mode, we don't want to initialize uart logging. */ ts->disable_debug_logging = ts->is_not_debug_mode; diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_secure_monitor.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_secure_monitor.cpp index d55eb2c70..bd603f9e4 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_secure_monitor.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_secure_monitor.cpp @@ -223,6 +223,8 @@ namespace ams::kern::board::nintendo::nx::smc { KScopedInterruptDisable di; /* Ensure we successfully show the error. */ + /* NOTE: On 23.0.0+ the SMC result is discarded. */ + /* The function now ends with an unconditional infinite loop and interrupts are never restored. */ MESOSPHERE_ABORT_UNLESS(ShowErrorImpl(color)); } diff --git a/libraries/libmesosphere/source/kern_k_debug_base.cpp b/libraries/libmesosphere/source/kern_k_debug_base.cpp index 7150c8a4e..3e71fde77 100644 --- a/libraries/libmesosphere/source/kern_k_debug_base.cpp +++ b/libraries/libmesosphere/source/kern_k_debug_base.cpp @@ -417,7 +417,7 @@ namespace ams::kern { /* Terminate the process. */ /* NOTE: This result is seemingly-intentionally not checked by Nintendo. */ - static_cast(target->Terminate()); + static_cast(target->Terminate(-1ll)); R_SUCCEED(); } diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 0bdcaab85..35648a37a 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -465,7 +465,7 @@ namespace ams::kern { } } - void KProcess::Exit() { + void KProcess::Exit(s64 exit_tag) { MESOSPHERE_ASSERT_THIS(); /* Determine whether we need to start terminating. */ @@ -480,6 +480,7 @@ namespace ams::kern { MESOSPHERE_ASSERT(m_state != State_Terminated); if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_DebugBreak) { this->ChangeState(State_Terminating); + this->SetExitTag(exit_tag); needs_terminate = true; } } @@ -500,7 +501,7 @@ namespace ams::kern { MESOSPHERE_PANIC("Thread survived call to exit"); } - Result KProcess::Terminate() { + Result KProcess::Terminate(s64 exit_tag) { MESOSPHERE_ASSERT_THIS(); /* Determine whether we need to start terminating */ @@ -516,6 +517,7 @@ namespace ams::kern { if (m_state == State_Running || m_state == State_RunningAttached || m_state == State_Crashed || m_state == State_DebugBreak) { this->ChangeState(State_Terminating); + this->SetExitTag(exit_tag); needs_terminate = true; } } @@ -783,7 +785,7 @@ namespace ams::kern { MESOSPHERE_ASSERT(m_num_running_threads.Load() > 0); if (const auto prev = m_num_running_threads--; prev == 1) { - static_cast(this->Terminate()); + static_cast(this->Terminate(-1ll)); } } diff --git a/libraries/libmesosphere/source/kern_k_session_request.cpp b/libraries/libmesosphere/source/kern_k_session_request.cpp index a40611949..12acaee0e 100644 --- a/libraries/libmesosphere/source/kern_k_session_request.cpp +++ b/libraries/libmesosphere/source/kern_k_session_request.cpp @@ -28,6 +28,8 @@ namespace ams::kern { } else { /* Allocate dynamic mappings as necessary. */ if (m_dynamic_mappings == nullptr) { + /* 23.0.0+ now checks for IsDynamicResourceLimitsEnabled before allocating from slab heap. */ + R_UNLESS(KTargetSystem::IsDynamicResourceLimitsEnabled(), svc::ResultOutOfMemory()); m_dynamic_mappings = DynamicMappings::Allocate(); R_UNLESS(m_dynamic_mappings != nullptr, svc::ResultOutOfMemory()); } diff --git a/libraries/libmesosphere/source/svc/kern_svc_exception.cpp b/libraries/libmesosphere/source/svc/kern_svc_exception.cpp index 667646455..797b0d979 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_exception.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_exception.cpp @@ -70,7 +70,7 @@ namespace ams::kern::svc { } /* Exit the current process. */ - GetCurrentProcess().Exit(); + GetCurrentProcess().Exit(-1ll); } } diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 982719d41..83e2dc3e7 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -25,8 +25,9 @@ namespace ams::kern::svc { return (0 <= core_id && core_id < static_cast(cpu::NumVirtualCores)); } - void ExitProcess() { - GetCurrentProcess().Exit(); + void ExitProcess(int64_t exit_tag) { + const uint32_t intended_kernel_major_version = GetCurrentProcess().GetIntendedKernelMajorVersion(); + GetCurrentProcess().Exit(intended_kernel_major_version <= 26 ? -1ll : exit_tag); MESOSPHERE_PANIC("Process survived call to exit"); } @@ -357,7 +358,7 @@ namespace ams::kern::svc { R_RETURN(process->Run(priority, static_cast(aligned_stack_size))); } - Result TerminateProcess(ams::svc::Handle process_handle) { + Result TerminateProcess(ams::svc::Handle process_handle, int64_t exit_tag) { /* Get the target process. */ KProcess *process = GetCurrentProcess().GetHandleTable().GetObject(process_handle).ReleasePointerUnsafe(); R_UNLESS(process != nullptr, svc::ResultInvalidHandle()); @@ -367,13 +368,13 @@ namespace ams::kern::svc { ON_SCOPE_EXIT { process->Close(); }; /* Terminate the process. */ - R_TRY(process->Terminate()); + R_TRY(process->Terminate(exit_tag)); } else { /* We're terminating ourselves. Close our reference immediately. */ process->Close(); /* Exit. */ - ExitProcess(); + ExitProcess(exit_tag); } R_SUCCEED(); @@ -411,6 +412,20 @@ namespace ams::kern::svc { } } break; + case ams::svc::ProcessInfoType_Unknown1: + { + /* TODO: 23.0.0+ added a new process info type. Figure out what this is. */ + /* For now just call it an exit tag since it's only set during Exit or Terminate. */ + int64_t exit_tag; + { + KScopedLightLock proc_lk(process->GetStateLock()); + + exit_tag = process->GetExitTag(); + } + + *out = exit_tag; + } + break; default: R_THROW(svc::ResultInvalidEnumValue()); } @@ -423,7 +438,9 @@ namespace ams::kern::svc { /* ============================= 64 ABI ============================= */ void ExitProcess64() { - return ExitProcess(); + /* TODO: 23.0.0+ changed the actual SVC handler. */ + /* For now just pass the default value for the exit tag. */ + return ExitProcess(-1ll); } Result GetProcessId64(uint64_t *out_process_id, ams::svc::Handle process_handle) { @@ -443,7 +460,9 @@ namespace ams::kern::svc { } Result TerminateProcess64(ams::svc::Handle process_handle) { - R_RETURN(TerminateProcess(process_handle)); + /* TODO: 23.0.0+ changed the actual SVC handler. */ + /* For now just pass the default value for the exit tag. */ + R_RETURN(TerminateProcess(process_handle, -1ll)); } Result GetProcessInfo64(int64_t *out_info, ams::svc::Handle process_handle, ams::svc::ProcessInfoType info_type) { @@ -453,7 +472,9 @@ namespace ams::kern::svc { /* ============================= 64From32 ABI ============================= */ void ExitProcess64From32() { - return ExitProcess(); + /* TODO: 23.0.0+ changed the actual SVC handler. */ + /* For now just pass the default value for the exit tag. */ + return ExitProcess(-1ll); } Result GetProcessId64From32(uint64_t *out_process_id, ams::svc::Handle process_handle) { @@ -473,7 +494,9 @@ namespace ams::kern::svc { } Result TerminateProcess64From32(ams::svc::Handle process_handle) { - R_RETURN(TerminateProcess(process_handle)); + /* TODO: 23.0.0+ changed the actual SVC handler. */ + /* For now just pass the default value for the exit tag. */ + R_RETURN(TerminateProcess(process_handle, -1ll)); } Result GetProcessInfo64From32(int64_t *out_info, ams::svc::Handle process_handle, ams::svc::ProcessInfoType info_type) { diff --git a/libraries/libmesosphere/source/svc/kern_svc_secure_monitor_call.cpp b/libraries/libmesosphere/source/svc/kern_svc_secure_monitor_call.cpp index 9300a576d..8723b7da7 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_secure_monitor_call.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_secure_monitor_call.cpp @@ -28,6 +28,8 @@ namespace ams::kern::svc { /* ============================= 64 ABI ============================= */ void CallSecureMonitor64(ams::svc::lp64::SecureMonitorArguments *args) { + /* TODO: 23.0.0+ added a second argument to CallSecureMonitorFromUser. */ + /* On NX, CallSecureMonitor64 always passes 0 for this argument. */ KSystemControl::CallSecureMonitorFromUser(args); } diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 96a18a721..52e105ed3 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -388,6 +388,7 @@ namespace ams::svc { /* Process types. */ enum ProcessInfoType : u32 { ProcessInfoType_ProcessState = 0, + ProcessInfoType_Unknown1 = 1, }; enum ProcessState : u32 {