add a proper kernel panic

This commit is contained in:
apio 2022-09-25 16:56:00 +02:00
parent 6fc7608c35
commit aee4e55fdd
8 changed files with 150 additions and 37 deletions

View File

@ -34,16 +34,6 @@
else { __call_assert_fail("TODO at %s, line %d: %s", __FILE__, __LINE__, message); } \
} while (0)
#define PANIC(message) \
do { \
Task* cur_task = Scheduler::current_task(); \
if (cur_task) \
{ \
__call_assert_fail("PANIC in task %ld at %s, line %d: %s", cur_task->id, __FILE__, __LINE__, message); \
} \
else { __call_assert_fail("PANIC at %s, line %d: %s", __FILE__, __LINE__, message); } \
} while (0)
#ifdef ___weird_hack_to_put_something_at_end_of_file
#undef ___weird_hack_to_put_something_at_end_of_file
#endif

View File

@ -0,0 +1,17 @@
#pragma once
#include "interrupts/Context.h"
#ifdef __cplusplus
extern "C"
{
#endif
[[noreturn]] void __do_int_panic(Context* context, const char* file, int line, const char* message);
[[noreturn]] void __do_panic(Context* context, const char* message);
[[noreturn]] void __panic(const char* message);
#ifdef __cplusplus
}
#endif
#define panic(message) asm volatile("cli\npush $16\npushq %%rsp\npushfq\npush $8\ncall __panic" : : "D"(message))
#define int_panic(context, message) __do_int_panic(context, __FILE__, __LINE__, message)

View File

@ -6,6 +6,7 @@
#include "interrupts/Interrupts.h"
#include "log/Log.h"
#include "misc/hang.h"
#include "panic/Panic.h"
#include "std/stdio.h"
#include "thread/Scheduler.h"
#include "trace/StackTracer.h"
@ -15,22 +16,24 @@ extern "C" void common_handler(Context* context)
ASSERT(Interrupts::is_in_handler());
if (context->number >= 0x20 && context->number < 0x30)
{
Interrupts::ensure_handler(); // restore the "in interrupt flag" if an interrupt happened in the middle of this
Interrupts::ensure_handler(); // restore the "in-interrupt flag" if an interrupt happened in the middle of this
// one
IRQ::interrupt_handler(context);
return;
}
if (context->number == 13)
{
kerrorln("General protection fault at RIP %lx, cs %ld, ss %ld, RSP %lx, error code %ld", context->rip,
context->cs, context->ss, context->rsp, context->error_code);
kinfoln("Stack trace:");
Interrupts::disable();
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
if (context->cs == 0x8) { PANIC("Fatal: GPF in kernel task"); }
if (context->cs == 0x8) { int_panic(context, "GPF in kernel task"); }
else
{
kerrorln("General protection fault at RIP %lx, cs %ld, ss %ld, RSP %lx, error code %ld", context->rip,
context->cs, context->ss, context->rsp, context->error_code);
kinfoln("Stack trace:");
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
Interrupts::ensure_handler();
Scheduler::task_misbehave(context);
}
@ -38,30 +41,22 @@ extern "C" void common_handler(Context* context)
if (context->number == 14)
{
Interrupts::disable();
kerrorln("Page fault in %s (RIP %lx), while trying to access %lx, error code %ld",
context->cs == 8 ? "ring 0" : "ring 3", context->rip, context->cr2, context->error_code);
kinfoln("Stack trace:");
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
if (context->cs == 0x8) { PANIC("Fatal: Page fault in kernel task"); }
if (context->cs == 0x8) { int_panic(context, "Page fault in kernel task"); }
else
{
kerrorln("Page fault in ring 3 (RIP %lx), while trying to access %lx, error code %ld", context->rip,
context->cr2, context->error_code);
kinfoln("Stack trace:");
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
Interrupts::ensure_handler();
Scheduler::task_misbehave(context);
}
}
if (context->number == 8)
{
kerrorln("Double fault, halting");
kinfoln("Stack trace:");
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
hang();
}
if (context->number == 8) { int_panic(context, "Double fault, halting"); }
if (context->number == 48)
{
Interrupts::ensure_handler();

View File

@ -21,6 +21,7 @@
#include "memory/VMM.h"
#include "misc/PCITypes.h"
#include "misc/reboot.h"
#include "panic/Panic.h"
#include "rand/Mersenne.h"
#include "render/Framebuffer.h"
#include "render/TextRenderer.h"

View File

@ -1,9 +1,9 @@
#define MODULE "stack"
#include "assert.h"
#include "panic/Panic.h"
#include <stdint.h>
extern "C" void __stack_chk_fail()
{
PANIC("Stack smashing detected");
panic("Stack smashing detected");
}

View File

@ -0,0 +1,34 @@
extern __do_panic
global __panic
__panic:
push BYTE 0 ; interrupt number
push BYTE 0 ; error code
push rax
push rbx
push rcx
push rdx
push rbp
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov r8, cr2
push r8
mov rsi, rdi
mov rdi, rsp
call __do_panic
cli
loop:
hlt
jmp loop

View File

@ -0,0 +1,75 @@
#define MODULE "panic"
#include "panic/Panic.h"
#include "interrupts/IDT.h"
#include "io/PIC.h"
#include "log/Log.h"
#include "misc/MSR.h"
#include "std/stdio.h"
#include "thread/Scheduler.h"
#include "trace/StackTracer.h"
static void dump_registers(Context* context)
{
printf("-- Registers: \n");
printf("rax: %lx, rbx: %lx, rcx: %lx, rdx: %lx\n", context->rax, context->rbx, context->rcx, context->rdx);
printf("rsi: %lx, rdi: %lx, rsp: %lx, rbp: %lx\n", context->rsi, context->rdi, context->rsp, context->rbp);
printf("r8: %lx, r9: %lx, r10: %lx, r11: %lx\n", context->r8, context->r9, context->r10, context->r11);
printf("r12: %lx, r13: %lx, r14: %lx, r15: %lx\n", context->r12, context->r13, context->r14, context->r15);
printf("rip: %lx, cs: %lx, ss: %lx\n", context->rip, context->cs, context->ss);
printf("rflags: %lx, cr2: %lx\n", context->rflags, context->cr2);
printf("ia32_efer: %lx\n", MSR::read_from(IA32_EFER_MSR));
}
[[noreturn]] static void __panic_stub(Context* context)
{
dump_registers(context);
printf("-- Stack trace:\n");
StackTracer tracer(context->rbp);
tracer.trace_with_ip(context->rip);
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.");
while (1) asm volatile("hlt");
}
extern "C" [[noreturn]] void __do_int_panic(Context* context, const char* file, int line, const char* message)
{
asm volatile("cli");
if (context->number >= 0x20 && context->number < 0x30) { PIC::send_eoi(context->irq_number); }
Task* task;
if ((task = Scheduler::current_task()))
{
kerrorln("Kernel panic in task %ld, at %s, line %d: %s", task->id, file, line, message);
}
else { kerrorln("Kernel panic at %s, line %d: %s", file, line, message); }
__panic_stub(context);
}
extern "C" [[noreturn]] void __do_panic(Context* context, const char* message)
{
Task* task;
if ((task = Scheduler::current_task())) { kerrorln("Kernel panic in task %ld: %s", task->id, message); }
else { kerrorln("Kernel panic: %s", message); }
__panic_stub(context);
}

View File

@ -7,6 +7,7 @@
#include "memory/MemoryManager.h"
#include "memory/VMM.h"
#include "misc/hang.h"
#include "panic/Panic.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "thread/PIT.h"
@ -147,7 +148,7 @@ void Scheduler::reap_tasks()
do {
if (task->state == task->Exited)
{
if (task == base_task && task == end_task) { PANIC("Last task exited"); }
if (task == base_task && task == end_task) { panic("Last task exited"); }
else if (task == base_task) { base_task = task->next_task; }
else if (task == end_task) { end_task = task->prev_task; }
if (!reap_base)