diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_trace.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_trace.hpp index b1d9e3221..8fe1b836f 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_trace.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_trace.hpp @@ -32,10 +32,17 @@ namespace ams::kern { class KTrace { public: enum Type { - Type_SvcEntry0 = 3, - Type_SvcEntry1 = 4, - Type_SvcExit0 = 5, - Type_SvcExit1 = 6, + Type_ThreadSwitch = 1, + + Type_SvcEntry0 = 3, + Type_SvcEntry1 = 4, + Type_SvcExit0 = 5, + Type_SvcExit1 = 6, + Type_Interrupt = 7, + + Type_ScheduleUpdate = 11, + + Type_CoreMigration = 14, }; private: static bool s_is_active; @@ -65,6 +72,18 @@ namespace ams::kern { } \ }) +#define MESOSPHERE_KTRACE_PUSH_RECORD(TYPE, ...) \ + ({ \ + if constexpr (::ams::kern::IsKTraceEnabled) { \ + if (::ams::kern::KTrace::IsActive()) { \ + ::ams::kern::KTrace::PushRecord(TYPE, ## __VA_ARGS__); \ + } \ + } \ + }) + +#define MESOSPHERE_KTRACE_THREAD_SWITCH(NEXT) \ + MESOSPHERE_KTRACE_PUSH_RECORD(::ams::kern::KTrace::Type_ThreadSwitch, (NEXT)->GetId()) + #define MESOSPHERE_KTRACE_SVC_ENTRY(SVC_ID, PARAM0, PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6, PARAM7) \ ({ \ if constexpr (::ams::kern::IsKTraceEnabled) { \ @@ -84,3 +103,12 @@ namespace ams::kern { } \ } \ }) + +#define MESOSPHERE_KTRACE_INTERRUPT(ID) \ + MESOSPHERE_KTRACE_PUSH_RECORD(::ams::kern::KTrace::Type_Interrupt, ID) + +#define MESOSPHERE_KTRACE_SCHEDULE_UPDATE(CORE, PREV, NEXT) \ + MESOSPHERE_KTRACE_PUSH_RECORD(::ams::kern::KTrace::Type_ScheduleUpdate, CORE, (PREV)->GetId(), (NEXT)->GetId()) + +#define MESOSPHERE_KTRACE_CORE_MIGRATION(THREAD_ID, PREV, NEXT, REASON) \ + MESOSPHERE_KTRACE_PUSH_RECORD(::ams::kern::KTrace::Type_CoreMigration, THREAD_ID, PREV, NEXT, REASON) diff --git a/libraries/libmesosphere/source/arch/arm64/kern_k_interrupt_manager.cpp b/libraries/libmesosphere/source/arch/arm64/kern_k_interrupt_manager.cpp index cda867fe5..51b2a4b36 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_k_interrupt_manager.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_k_interrupt_manager.cpp @@ -111,6 +111,9 @@ namespace ams::kern::arch::arm64 { const u32 raw_irq = this->interrupt_controller.GetIrq(); const s32 irq = KInterruptController::ConvertRawIrq(raw_irq); + /* Trace the interrupt. */ + MESOSPHERE_KTRACE_INTERRUPT(irq); + /* If the IRQ is spurious, we don't need to reschedule. */ if (irq < 0) { return false; diff --git a/libraries/libmesosphere/source/arch/arm64/svc/kern_svc_handlers_asm.s b/libraries/libmesosphere/source/arch/arm64/svc/kern_svc_handlers_asm.s index fc8fb5058..db0692c6f 100644 --- a/libraries/libmesosphere/source/arch/arm64/svc/kern_svc_handlers_asm.s +++ b/libraries/libmesosphere/source/arch/arm64/svc/kern_svc_handlers_asm.s @@ -86,18 +86,20 @@ _ZN3ams4kern4arch5arm6412SvcHandler64Ev: /* If we should, trace the svc entry. */ #if defined(MESOSPHERE_BUILD_FOR_TRACING) - sub sp, sp, #0x40 + sub sp, sp, #0x50 stp x0, x1, [sp, #(8 * 0)] stp x2, x3, [sp, #(8 * 2)] stp x4, x5, [sp, #(8 * 4)] stp x6, x7, [sp, #(8 * 6)] + str x11, [sp, #(8 * 8)] mov x0, sp bl _ZN3ams4kern3svc13TraceSvcEntryEPKm ldp x0, x1, [sp, #(8 * 0)] ldp x2, x3, [sp, #(8 * 2)] ldp x4, x5, [sp, #(8 * 4)] ldp x6, x7, [sp, #(8 * 6)] - add sp, sp, #0x40 + ldr x11, [sp, #(8 * 8)] + add sp, sp, #0x50 #endif /* Invoke the SVC handler. */ @@ -294,18 +296,20 @@ _ZN3ams4kern4arch5arm6412SvcHandler32Ev: /* If we should, trace the svc entry. */ #if defined(MESOSPHERE_BUILD_FOR_TRACING) - sub sp, sp, #0x40 + sub sp, sp, #0x50 stp x0, x1, [sp, #(8 * 0)] stp x2, x3, [sp, #(8 * 2)] stp x4, x5, [sp, #(8 * 4)] stp x6, x7, [sp, #(8 * 6)] + str x19, [sp, #(8 * 8)] mov x0, sp bl _ZN3ams4kern3svc13TraceSvcEntryEPKm ldp x0, x1, [sp, #(8 * 0)] ldp x2, x3, [sp, #(8 * 2)] ldp x4, x5, [sp, #(8 * 4)] ldp x6, x7, [sp, #(8 * 6)] - add sp, sp, #0x40 + ldr x19, [sp, #(8 * 8)] + add sp, sp, #0x50 #endif /* Invoke the SVC handler. */ diff --git a/libraries/libmesosphere/source/kern_k_resource_limit.cpp b/libraries/libmesosphere/source/kern_k_resource_limit.cpp index 7261919be..5ef2e04b5 100644 --- a/libraries/libmesosphere/source/kern_k_resource_limit.cpp +++ b/libraries/libmesosphere/source/kern_k_resource_limit.cpp @@ -31,7 +31,7 @@ namespace ams::kern { for (size_t i = 0; i < util::size(this->limit_values); i++) { this->limit_values[i] = 0; this->current_values[i] = 0; - this->current_hints[i] = 0; + this->current_hints[i] = 0; } */ } @@ -123,7 +123,7 @@ namespace ams::kern { if (this->current_values[which] + value <= this->limit_values[which]) { this->current_values[which] += value; - this->current_hints[which] += value; + this->current_hints[which] += value; return true; } diff --git a/libraries/libmesosphere/source/kern_k_scheduler.cpp b/libraries/libmesosphere/source/kern_k_scheduler.cpp index 233515868..87da6e765 100644 --- a/libraries/libmesosphere/source/kern_k_scheduler.cpp +++ b/libraries/libmesosphere/source/kern_k_scheduler.cpp @@ -99,6 +99,8 @@ namespace ams::kern { } } + MESOSPHERE_KTRACE_SCHEDULE_UPDATE(this->core_id, (prev_highest_thread != nullptr ? prev_highest_thread : this->idle_thread), (highest_thread != nullptr ? highest_thread : this->idle_thread)); + this->state.highest_priority_thread = highest_thread; this->state.needs_scheduling = true; return (1ul << this->core_id); @@ -163,6 +165,7 @@ namespace ams::kern { /* The suggested thread isn't bound to its core, so we can migrate it! */ suggested->SetActiveCore(core_id); priority_queue.ChangeCore(suggested_core, suggested); + MESOSPHERE_KTRACE_CORE_MIGRATION(suggested->GetId(), suggested_core, core_id, 1); top_threads[core_id] = suggested; cores_needing_scheduling |= Kernel::GetScheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); break; @@ -188,6 +191,7 @@ namespace ams::kern { /* Perform the migration. */ suggested->SetActiveCore(core_id); priority_queue.ChangeCore(candidate_core, suggested); + MESOSPHERE_KTRACE_CORE_MIGRATION(suggested->GetId(), candidate_core, core_id, 2); top_threads[core_id] = suggested; cores_needing_scheduling |= Kernel::GetScheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); break; @@ -253,6 +257,8 @@ namespace ams::kern { this->prev_thread = nullptr; } + MESOSPHERE_KTRACE_THREAD_SWITCH(next_thread); + /* Switch the current process, if we're switching processes. */ if (KProcess *next_process = next_thread->GetOwnerProcess(); next_process != cur_process) { /* MESOSPHERE_LOG("!!! PROCESS SWITCH !!! %s -> %s\n", cur_process != nullptr ? cur_process->GetName() : nullptr, next_process != nullptr ? next_process->GetName() : nullptr); */ @@ -496,6 +502,7 @@ namespace ams::kern { if (running_on_suggested_core == nullptr || running_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) { suggested->SetActiveCore(core_id); priority_queue.ChangeCore(suggested_core, suggested, true); + MESOSPHERE_KTRACE_CORE_MIGRATION(suggested->GetId(), suggested_core, core_id, 3); IncrementScheduledCount(suggested); break; } else { @@ -549,6 +556,7 @@ namespace ams::kern { /* Migrate the current thread to core -1. */ cur_thread.SetActiveCore(-1); priority_queue.ChangeCore(core_id, std::addressof(cur_thread)); + MESOSPHERE_KTRACE_CORE_MIGRATION(cur_thread.GetId(), core_id, -1, 4); IncrementScheduledCount(std::addressof(cur_thread)); /* If there's nothing scheduled, we can try to perform a migration. */ @@ -563,6 +571,7 @@ namespace ams::kern { if (top_on_suggested_core == nullptr || top_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) { suggested->SetActiveCore(core_id); priority_queue.ChangeCore(suggested_core, suggested); + MESOSPHERE_KTRACE_CORE_MIGRATION(suggested->GetId(), suggested_core, core_id, 5); IncrementScheduledCount(suggested); } diff --git a/libraries/libmesosphere/source/kern_k_server_port.cpp b/libraries/libmesosphere/source/kern_k_server_port.cpp index 965f7972a..da8482577 100644 --- a/libraries/libmesosphere/source/kern_k_server_port.cpp +++ b/libraries/libmesosphere/source/kern_k_server_port.cpp @@ -28,8 +28,11 @@ namespace ams::kern { void KServerPort::CleanupSessions() { /* Ensure our preconditions are met. */ - MESOSPHERE_ASSERT(this->IsLight() || this->session_list.empty()); - MESOSPHERE_ASSERT(!this->IsLight() || this->light_session_list.empty()); + if (this->IsLight()) { + MESOSPHERE_ASSERT(this->session_list.empty()); + } else { + MESOSPHERE_ASSERT(this->light_session_list.empty()); + } /* Cleanup the session list. */ while (true) {