diff --git a/kernel/src/panic/Panic.cpp b/kernel/src/panic/Panic.cpp index a0d35b6b..32d86893 100644 --- a/kernel/src/panic/Panic.cpp +++ b/kernel/src/panic/Panic.cpp @@ -13,6 +13,26 @@ #include "thread/Scheduler.h" #include "trace/StackTracer.h" +static bool g_is_in_panic = false; +static bool g_is_in_double_panic = false; + +static void panic_prepare_keyboard_triple_fault() +{ + PIC::enable_master(0b11111101); // enable keyboard only + PIC::enable_slave(0b11111111); + + IDTR idtr; + idtr.limit = 0x0000; + idtr.offset = 0x0000; + asm volatile( + "lidt %0" + : + : "m"( + idtr)); // when an interrupt arrives, triple-fault (the only interrupt that should come is the keyboard one) + + asm volatile("sti"); +} + void dump_registers(Context* context) { kinfoln("-- Registers:"); @@ -25,6 +45,32 @@ void dump_registers(Context* context) kinfoln("ia32_efer: %lx", MSR::read_from(IA32_EFER_MSR)); } +void fatal_dump_registers(Context* context) +{ + printf("-- Possibly Relevant Registers:\n"); + printf("rbp: %lx, rsp: %lx, rip: %lx, cs: %lx, ss: %lx, rflags: %lx, cr2: %lx\n", context->rbp, context->rsp, + context->rip, context->cs, context->ss, context->rflags, context->cr2); +} + +[[noreturn]] void __panic_fatal_stub(Context* context) +{ + if (context) fatal_dump_registers(context); + printf("-- No stack trace available\n"); + + KernelLog::enable_log_backend(Backend::Console); + KernelLog::toggle_log_backend( + Backend::Console); // disable console logging, as we can page fault while writing to the framebuffer. + + Scheduler::current_task()->id = 0; // we're panicking, we don't even care anymore. This is so KernelLog shows + // (kernel) instead of (taskname: PID) in the log. + + panic_prepare_keyboard_triple_fault(); + + printf("Press any key to restart.\n"); + + while (1) asm volatile("hlt"); +} + [[noreturn]] void __panic_stub(Context* context) { VMM::switch_back_to_kernel_address_space(); @@ -50,21 +96,7 @@ void dump_registers(Context* context) } else { kinfoln("-- No stack trace available"); } - PIC::enable_master(0b11111101); // enable keyboard only - PIC::enable_slave(0b11111111); - - IDTR idtr; - idtr.limit = 0x0000; - idtr.offset = 0x0000; - asm volatile( - "lidt %0" - : - : "m"( - idtr)); // when an interrupt arrives, triple-fault (the only interrupt that should come is the keyboard one) - - asm volatile("sti"); - - kinfoln("Press any key to restart."); + panic_prepare_keyboard_triple_fault(); while (1) asm volatile("hlt"); } @@ -73,6 +105,22 @@ extern "C" [[noreturn]] bool __do_int_panic(Context* context, const char* file, { asm volatile("cli"); + if (g_is_in_double_panic) + { + panic_prepare_keyboard_triple_fault(); + while (1) asm volatile("hlt"); + } + + if (g_is_in_panic) + { + g_is_in_double_panic = true; + printf("Kernel panic while panicking (showing vital information only) at %s, line %d: %s\n", file, line, + message); + __panic_fatal_stub(context); + } + + g_is_in_panic = true; + KernelLog::enable_log_backend(Backend::Console); TextRenderer::reset(); @@ -95,6 +143,22 @@ extern "C" [[noreturn]] bool __do_panic(const char* file, int line, const char* { asm volatile("cli"); + if (g_is_in_double_panic) + { + panic_prepare_keyboard_triple_fault(); + while (1) asm volatile("hlt"); + } + + if (g_is_in_panic) + { + g_is_in_double_panic = true; + printf("Kernel panic while panicking (showing vital information only) at %s, line %d: %s\n", file, line, + message); + __panic_fatal_stub(nullptr); + } + + g_is_in_panic = true; + KernelLog::enable_log_backend(Backend::Console); TextRenderer::reset();