kern: generate fatal error on panic

This commit is contained in:
Michael Scire
2020-09-16 16:44:31 -07:00
committed by SciresM
parent 76957e502d
commit 4acdc899f5
11 changed files with 296 additions and 53 deletions

View File

@@ -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();
}