add a proper kernel panic
This commit is contained in:
parent
6fc7608c35
commit
aee4e55fdd
@ -34,16 +34,6 @@
|
|||||||
else { __call_assert_fail("TODO at %s, line %d: %s", __FILE__, __LINE__, message); } \
|
else { __call_assert_fail("TODO at %s, line %d: %s", __FILE__, __LINE__, message); } \
|
||||||
} while (0)
|
} 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
|
#ifdef ___weird_hack_to_put_something_at_end_of_file
|
||||||
#undef ___weird_hack_to_put_something_at_end_of_file
|
#undef ___weird_hack_to_put_something_at_end_of_file
|
||||||
#endif
|
#endif
|
17
kernel/include/panic/Panic.h
Normal file
17
kernel/include/panic/Panic.h
Normal 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)
|
@ -6,6 +6,7 @@
|
|||||||
#include "interrupts/Interrupts.h"
|
#include "interrupts/Interrupts.h"
|
||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "misc/hang.h"
|
#include "misc/hang.h"
|
||||||
|
#include "panic/Panic.h"
|
||||||
#include "std/stdio.h"
|
#include "std/stdio.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include "trace/StackTracer.h"
|
#include "trace/StackTracer.h"
|
||||||
@ -15,22 +16,24 @@ extern "C" void common_handler(Context* context)
|
|||||||
ASSERT(Interrupts::is_in_handler());
|
ASSERT(Interrupts::is_in_handler());
|
||||||
if (context->number >= 0x20 && context->number < 0x30)
|
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
|
// one
|
||||||
IRQ::interrupt_handler(context);
|
IRQ::interrupt_handler(context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (context->number == 13)
|
if (context->number == 13)
|
||||||
{
|
{
|
||||||
kerrorln("General protection fault at RIP %lx, cs %ld, ss %ld, RSP %lx, error code %ld", context->rip,
|
Interrupts::disable();
|
||||||
context->cs, context->ss, context->rsp, context->error_code);
|
|
||||||
kinfoln("Stack trace:");
|
|
||||||
|
|
||||||
StackTracer tracer(context->rbp);
|
if (context->cs == 0x8) { int_panic(context, "GPF in kernel task"); }
|
||||||
tracer.trace_with_ip(context->rip);
|
|
||||||
if (context->cs == 0x8) { PANIC("Fatal: GPF in kernel task"); }
|
|
||||||
else
|
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();
|
Interrupts::ensure_handler();
|
||||||
Scheduler::task_misbehave(context);
|
Scheduler::task_misbehave(context);
|
||||||
}
|
}
|
||||||
@ -38,30 +41,22 @@ extern "C" void common_handler(Context* context)
|
|||||||
if (context->number == 14)
|
if (context->number == 14)
|
||||||
{
|
{
|
||||||
Interrupts::disable();
|
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);
|
if (context->cs == 0x8) { int_panic(context, "Page fault in kernel task"); }
|
||||||
tracer.trace_with_ip(context->rip);
|
|
||||||
|
|
||||||
if (context->cs == 0x8) { PANIC("Fatal: Page fault in kernel task"); }
|
|
||||||
else
|
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();
|
Interrupts::ensure_handler();
|
||||||
Scheduler::task_misbehave(context);
|
Scheduler::task_misbehave(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (context->number == 8)
|
if (context->number == 8) { int_panic(context, "Double fault, halting"); }
|
||||||
{
|
|
||||||
kerrorln("Double fault, halting");
|
|
||||||
kinfoln("Stack trace:");
|
|
||||||
|
|
||||||
StackTracer tracer(context->rbp);
|
|
||||||
tracer.trace_with_ip(context->rip);
|
|
||||||
|
|
||||||
hang();
|
|
||||||
}
|
|
||||||
if (context->number == 48)
|
if (context->number == 48)
|
||||||
{
|
{
|
||||||
Interrupts::ensure_handler();
|
Interrupts::ensure_handler();
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "misc/PCITypes.h"
|
#include "misc/PCITypes.h"
|
||||||
#include "misc/reboot.h"
|
#include "misc/reboot.h"
|
||||||
|
#include "panic/Panic.h"
|
||||||
#include "rand/Mersenne.h"
|
#include "rand/Mersenne.h"
|
||||||
#include "render/Framebuffer.h"
|
#include "render/Framebuffer.h"
|
||||||
#include "render/TextRenderer.h"
|
#include "render/TextRenderer.h"
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#define MODULE "stack"
|
#define MODULE "stack"
|
||||||
|
|
||||||
#include "assert.h"
|
#include "panic/Panic.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
extern "C" void __stack_chk_fail()
|
extern "C" void __stack_chk_fail()
|
||||||
{
|
{
|
||||||
PANIC("Stack smashing detected");
|
panic("Stack smashing detected");
|
||||||
}
|
}
|
34
kernel/src/panic/Panic.asm
Normal file
34
kernel/src/panic/Panic.asm
Normal 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
|
75
kernel/src/panic/Panic.cpp
Normal file
75
kernel/src/panic/Panic.cpp
Normal 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);
|
||||||
|
}
|
@ -7,6 +7,7 @@
|
|||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "misc/hang.h"
|
#include "misc/hang.h"
|
||||||
|
#include "panic/Panic.h"
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include "thread/PIT.h"
|
#include "thread/PIT.h"
|
||||||
@ -147,7 +148,7 @@ void Scheduler::reap_tasks()
|
|||||||
do {
|
do {
|
||||||
if (task->state == task->Exited)
|
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 == base_task) { base_task = task->next_task; }
|
||||||
else if (task == end_task) { end_task = task->prev_task; }
|
else if (task == end_task) { end_task = task->prev_task; }
|
||||||
if (!reap_base)
|
if (!reap_base)
|
||||||
|
Loading…
Reference in New Issue
Block a user