From b3e6571586ededd4e12a2d796b6a79efeb8d0728 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 14 Feb 2020 04:01:09 -0800 Subject: [PATCH] kern: improve panic output --- libraries/libmesosphere/source/kern_panic.cpp | 101 +++++++++++++----- 1 file changed, 74 insertions(+), 27 deletions(-) diff --git a/libraries/libmesosphere/source/kern_panic.cpp b/libraries/libmesosphere/source/kern_panic.cpp index eb58d853c..a60e88093 100644 --- a/libraries/libmesosphere/source/kern_panic.cpp +++ b/libraries/libmesosphere/source/kern_panic.cpp @@ -29,33 +29,81 @@ namespace ams::kern { namespace { - size_t g_panic_count = 0; + constexpr std::array NegativeArray = [] { + std::array arr = {}; + for (size_t i = 0; i < arr.size(); i++) { + arr[i] = -1; + } + return arr; + }(); + + std::atomic g_next_ticket = 0; + std::atomic g_current_ticket = 0; + + std::array g_core_tickets = NegativeArray; + + s32 GetCoreTicket() { + const s32 core_id = GetCurrentCoreId(); + if (g_core_tickets[core_id] == -1) { + g_core_tickets[core_id] = 2 * g_next_ticket.fetch_add(1); + } + return g_core_tickets[core_id]; + } + + void WaitCoreTicket() { + const s32 expected = GetCoreTicket(); + const s32 desired = expected + 1; + s32 compare = g_current_ticket; + do { + if (compare == desired) { + break; + } + compare = expected; + } while (!g_current_ticket.compare_exchange_weak(compare, desired)); + } + + void ReleaseCoreTicket() { + const s32 expected = GetCoreTicket() + 1; + const s32 desired = expected + 1; + s32 compare = g_current_ticket; + do { + if (compare != expected) { + break; + } + } while (!g_current_ticket.compare_exchange_weak(compare, desired)); + } [[gnu::unused]] void PrintCurrentState() { - if (g_panic_count == 1) { - g_panic_count++; + /* Wait for it to be our turn to print. */ + WaitCoreTicket(); - MESOSPHERE_RELEASE_LOG("Base Address: %p\n", _start); + const s32 core_id = GetCurrentCoreId(); + MESOSPHERE_RELEASE_LOG("Core[%d] Current State:\n", core_id); - /* TODO: Dump register state. */ + /* TODO: Dump register state. */ - #ifdef ATMOSPHERE_ARCH_ARM64 - MESOSPHERE_RELEASE_LOG("Backtrace:\n"); - uintptr_t fp = reinterpret_cast(__builtin_frame_address(0)); - for (size_t i = 0; i < 32 && fp && util::IsAligned(fp, 0x10) && cpu::GetPhysicalAddressWritable(nullptr, fp, true); i++) { - struct { - uintptr_t fp; - uintptr_t lr; - } *stack_frame = reinterpret_cast(fp); - MESOSPHERE_RELEASE_LOG(" [%02zx]: %p\n", i, reinterpret_cast(stack_frame->lr)); - fp = stack_frame->fp; - } - #endif - } + #ifdef ATMOSPHERE_ARCH_ARM64 + MESOSPHERE_RELEASE_LOG(" Backtrace:\n"); + uintptr_t fp = reinterpret_cast(__builtin_frame_address(0)); + for (size_t i = 0; i < 32 && fp && util::IsAligned(fp, 0x10) && cpu::GetPhysicalAddressWritable(nullptr, fp, true); i++) { + struct { + uintptr_t fp; + uintptr_t lr; + } *stack_frame = reinterpret_cast(fp); + MESOSPHERE_RELEASE_LOG(" [%02zx]: %p\n", i, reinterpret_cast(stack_frame->lr)); + fp = stack_frame->fp; + } + #endif + + MESOSPHERE_RELEASE_LOG("\n"); + + /* Allow the next core to print. */ + ReleaseCoreTicket(); } NORETURN void StopSystem() { #ifdef MESOSPHERE_BUILD_FOR_DEBUGGING + /* Print the current core. */ PrintCurrentState(); #endif @@ -66,16 +114,15 @@ namespace ams::kern { NORETURN WEAK_SYMBOL void Panic(const char *file, int line, const char *format, ...) { #ifdef MESOSPHERE_BUILD_FOR_DEBUGGING - if (g_panic_count == 0) { - g_panic_count++; + /* Wait for it to be our turn to print. */ + WaitCoreTicket(); - ::std::va_list vl; - va_start(vl, format); - MESOSPHERE_RELEASE_LOG("KernelPanic (Core %d): %s:%d\n", GetCurrentCoreId(), file, line); - MESOSPHERE_RELEASE_VLOG(format, vl); - MESOSPHERE_RELEASE_LOG("\n"); - va_end(vl); - } + ::std::va_list vl; + va_start(vl, format); + MESOSPHERE_RELEASE_LOG("Core[%d]: Kernel Panic at %s:%d\n", GetCurrentCoreId(), file, line); + MESOSPHERE_RELEASE_VLOG(format, vl); + MESOSPHERE_RELEASE_LOG("\n"); + va_end(vl); #endif StopSystem();