kern: generate fatal error on panic
This commit is contained in:
@@ -27,6 +27,11 @@ namespace ams::result::impl {
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
/* NOTE: This is not exposed via a header, but is referenced via assembly. */
|
||||
/* NOTE: Nintendo does not save register contents on panic; we use this */
|
||||
/* to generate an atmosphere fatal report on panic. */
|
||||
constinit KExceptionContext g_panic_exception_contexts[cpu::NumCores];
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr std::array<s32, cpu::NumCores> NegativeArray = [] {
|
||||
@@ -73,18 +78,38 @@ namespace ams::kern {
|
||||
} while (!g_current_ticket.compare_exchange_weak(compare, desired));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE KExceptionContext *GetPanicExceptionContext(int core_id) {
|
||||
#if defined(MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP)
|
||||
return std::addressof(g_panic_exception_contexts[core_id]);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
[[gnu::unused]] void PrintCurrentState() {
|
||||
/* Wait for it to be our turn to print. */
|
||||
WaitCoreTicket();
|
||||
|
||||
const s32 core_id = GetCurrentCoreId();
|
||||
/* Get the current exception context. */
|
||||
const s32 core_id = GetCurrentCoreId();
|
||||
const auto *core_ctx = GetPanicExceptionContext(core_id);
|
||||
|
||||
/* Print the state. */
|
||||
MESOSPHERE_RELEASE_LOG("Core[%d] Current State:\n", core_id);
|
||||
|
||||
/* TODO: Dump register state. */
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
/* Print registers. */
|
||||
if (core_ctx != nullptr) {
|
||||
MESOSPHERE_RELEASE_LOG(" Registers:\n");
|
||||
for (size_t i = 0; i < util::size(core_ctx->x); ++i) {
|
||||
MESOSPHERE_RELEASE_LOG(" X[%02zx]: %p\n", i, reinterpret_cast<void *>(core_ctx->x[i]));
|
||||
}
|
||||
MESOSPHERE_RELEASE_LOG(" SP: %p\n", reinterpret_cast<void *>(core_ctx->x[30]));
|
||||
}
|
||||
|
||||
/* Print backtrace. */
|
||||
MESOSPHERE_RELEASE_LOG(" Backtrace:\n");
|
||||
uintptr_t fp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
|
||||
uintptr_t fp = core_ctx != nullptr ? core_ctx->x[29] : reinterpret_cast<uintptr_t>(__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;
|
||||
@@ -107,12 +132,12 @@ namespace ams::kern {
|
||||
PrintCurrentState();
|
||||
#endif
|
||||
|
||||
KSystemControl::StopSystem();
|
||||
KSystemControl::StopSystem(GetPanicExceptionContext(GetCurrentCoreId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NORETURN WEAK_SYMBOL void Panic(const char *file, int line, const char *format, ...) {
|
||||
NORETURN void PanicImpl(const char *file, int line, const char *format, ...) {
|
||||
#ifdef MESOSPHERE_BUILD_FOR_DEBUGGING
|
||||
/* Wait for it to be our turn to print. */
|
||||
WaitCoreTicket();
|
||||
@@ -133,7 +158,7 @@ namespace ams::kern {
|
||||
StopSystem();
|
||||
}
|
||||
|
||||
NORETURN WEAK_SYMBOL void Panic() {
|
||||
NORETURN void PanicImpl() {
|
||||
StopSystem();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user