From 22852599dff741cea114c7d8cd9c1b32e11225ec Mon Sep 17 00:00:00 2001 From: Tom-on64 Date: Sun, 29 Mar 2026 20:39:06 +0200 Subject: [PATCH] Added register dump to panic() and colors to printk() --- kernel/include/isr.h | 1 + kernel/include/kernel.h | 7 ++++--- kernel/src/bootloader.c | 4 ++-- kernel/src/isr.c | 27 ++++++++++++++------------- kernel/src/kmain.c | 12 ++++++------ kernel/src/paging.c | 2 +- kernel/src/panic.c | 27 +++++++++++++++++++++------ kernel/src/pmm.c | 2 +- kernel/src/printk.c | 16 +++++++++++++++- kernel/src/ssp.c | 2 +- 10 files changed, 66 insertions(+), 34 deletions(-) diff --git a/kernel/include/isr.h b/kernel/include/isr.h index 18f5c06..ee79e9f 100644 --- a/kernel/include/isr.h +++ b/kernel/include/isr.h @@ -3,6 +3,7 @@ #include +#define EXCEPTION_COUNT 32 #define ISR_COUNT 16 // Interrupt frame (ie. what's on the stack on interrupt) diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h index cc5b8be..1baa28c 100644 --- a/kernel/include/kernel.h +++ b/kernel/include/kernel.h @@ -73,15 +73,16 @@ int vprintk(const char* fmt, va_list ap); #define pr_alert(fmt, ...) printk(KERN_ALERT fmt, ##__VA_ARGS__) #define pr_crit(fmt, ...) printk(KERN_CRIT fmt, ##__VA_ARGS__) #define pr_error(fmt, ...) printk(KERN_ERROR fmt, ##__VA_ARGS__) -#define pr_warning(fmt, ...) printk(KERN_WARNING fmt, ##__VA_ARGS__) +#define pr_warn(fmt, ...) printk(KERN_WARNING fmt, ##__VA_ARGS__) #define pr_notice(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__) #define pr_info(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) #define pr_debug(fmt, ...) printk(KERN_DEBUG fmt, ##__VA_ARGS__) #define PANIC_MSG_BUFSZ 1024 -void panic(const char* fmt, ...) __noreturn __cold __printf(1, 2); -void vpanic(const char* fmt, va_list ap)__noreturn __cold; +struct isr_int_frame; +void panic(struct isr_int_frame* regs, const char* fmt, ...) __noreturn __cold __printf(2, 3); +void vpanic(struct isr_int_frame* regs, const char *fmt, va_list ap) __noreturn __cold; extern uintptr_t __kernel_start, __kernel_text_start, __kernel_rodata_start, __kernel_data_start; extern uintptr_t __kernel_end, __kernel_text_end, __kernel_rodata_end, __kernel_data_end; diff --git a/kernel/src/bootloader.c b/kernel/src/bootloader.c index 6c785d9..2d25763 100644 --- a/kernel/src/bootloader.c +++ b/kernel/src/bootloader.c @@ -30,7 +30,7 @@ static struct limine_executable_file_request lim_exe_req = struct bootloader bootloader = { 0 }; int boot_init(void) { - if (LIMINE_BASE_REVISION_SUPPORTED(lim_base_revision) == false) panic("Unsupported Limine base revision."); + if (LIMINE_BASE_REVISION_SUPPORTED(lim_base_revision) == false) panic(NULL, "Unsupported Limine base revision."); struct limine_paging_mode_response* lim_paging_res = lim_paging_req.response; struct limine_executable_address_response* lim_kaddr_res = lim_kaddr_req.response; @@ -39,7 +39,7 @@ int boot_init(void) { struct limine_framebuffer_response* lim_fbuf_res = lim_fbuf_req.response; struct limine_executable_file_response* lim_exe_res = lim_exe_req.response; - if (lim_paging_res->mode != LIMINE_PAGING_MODE_X86_64_4LVL) panic("Expected 4 level paging."); + if (lim_paging_res->mode != LIMINE_PAGING_MODE_X86_64_4LVL) panic(NULL, "Expected 4 level paging."); bootloader.hhdm_offset = lim_hhdm_res->offset; bootloader.kernel_phys_base = lim_kaddr_res->physical_base; bootloader.kernel_virt_base = lim_kaddr_res->virtual_base; diff --git a/kernel/src/isr.c b/kernel/src/isr.c index dd321f9..41864df 100644 --- a/kernel/src/isr.c +++ b/kernel/src/isr.c @@ -5,6 +5,7 @@ #include #include +isr_handler_ptr exception_handlers[EXCEPTION_COUNT]; isr_handler_ptr irq_handlers[ISR_COUNT]; const char* exceptions[] = { @@ -62,6 +63,7 @@ void pic_remap(void) { } int isr_init(void) { + memset(exception_handlers, 0, sizeof(exception_handlers)); memset(irq_handlers, 0, sizeof(irq_handlers)); idt_init(); @@ -98,25 +100,24 @@ void isr_handle_interrupt(size_t rsp) { struct isr_int_frame* iframe = (void*)rsp; if (iframe->interrupt < 32) { - pr_emerg("Register Dump:\n"); - pr_emerg("\tRAX: %016lx RBX: %016lx RCX: %016lx\n", iframe->rax, iframe->rbx, iframe->rcx); - pr_emerg("\tRDX: %016lx RSI: %016lx RDI: %016lx\n", iframe->rdx, iframe->rsi, iframe->rdi); - pr_emerg("\tR08: %016lx R09: %016lx R10: %016lx\n", iframe->r8, iframe->r9, iframe->r10); - pr_emerg("\tR11: %016lx R12: %016lx R13: %016lx\n", iframe->r11, iframe->r12, iframe->r13); - pr_emerg("\tR14: %016lx R15: %016lx DS/ES: %016lx\n", iframe->r14, iframe->r15, iframe->ds); - pr_emerg("\tRBP: %016lx RSP: %016lx SS: %016lx\n", iframe->rbp, iframe->user_rsp, iframe->user_ss); - pr_emerg("\tRIP: %016lx RFLAGS: %016lx CS: %016lx\n", iframe->rip, iframe->rflags, iframe->cs); + if (exception_handlers[iframe->interrupt]) { + exception_handlers[iframe->interrupt](iframe); + return; + } - if (iframe->error) pr_emerg("Error code: 0x%lx\n", iframe->error); - panic(exceptions[iframe->interrupt]); + panic(iframe, "Unhandled %s exception, err 0x%lx", exceptions[iframe->interrupt], iframe->error); } else if (iframe->interrupt >= 32 && iframe->interrupt < 48) { - // ISRs 32-47 - Hardware interrupts uint8_t irq = iframe->interrupt - 32; - isr_send_eoi(irq); + if (irq_handlers[irq]) irq_handlers[irq](iframe); - } else if (iframe->interrupt == 128) { + else pr_warn("Unhandled IRQ #%d\n", irq); + + isr_send_eoi(irq); + } else if (iframe->interrupt == 0x80) { // ISR 128 - System call pr_notice("SYSCALL!\n"); + } else { + pr_warn("Unknown interrupt vector: %lu", iframe->interrupt); } } diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 02fae78..ce69377 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -13,10 +13,10 @@ void _start(void) { int err = 0; // Serial console for debugging - if ((err = serial_init(COM1)) < 0) panic("Failed to initialize Serial driver. (%d)", err); + if ((err = serial_init(COM1)) < 0) panic(NULL, "Failed to initialize Serial driver. (%d)", err); // Load structures from bootloader - if ((err = boot_init()) < 0) panic("Failed to parse bootloader structures. (%d)", err); + if ((err = boot_init()) < 0) panic(NULL, "Failed to parse bootloader structures. (%d)", err); // CPUID thingy :p uint32_t eax = 0; @@ -25,12 +25,12 @@ void _start(void) { pr_info("[kernel] CPUID_GETVENDORID: %s\n", s); // System init - if ((err = gdt_init()) < 0) panic("Failed to initalize GDT. (%d)", err); - if ((err = isr_init()) < 0) panic("Failed to initalize ISRs. (%d)", err); + if ((err = gdt_init()) < 0) panic(NULL, "Failed to initalize GDT. (%d)", err); + if ((err = isr_init()) < 0) panic(NULL, "Failed to initalize ISRs. (%d)", err); // Memory management - if ((err = pmm_init()) < 0) panic("Failed to initalize Physical Memory Manager. (%d)", err); - if ((err = pag_init()) < 0) panic("Failed to initalize Paging. (%d)", err); + if ((err = pmm_init()) < 0) panic(NULL, "Failed to initalize Physical Memory Manager. (%d)", err); + if ((err = pag_init()) < 0) panic(NULL, "Failed to initalize Paging. (%d)", err); // The most important function in the world. splash(); diff --git a/kernel/src/paging.c b/kernel/src/paging.c index 328f96b..98d89bf 100644 --- a/kernel/src/paging.c +++ b/kernel/src/paging.c @@ -40,7 +40,7 @@ int pag_init(void) { case LIMINE_MEMMAP_FRAMEBUFFER: flags = PTE_FLAG_WRITE | PTE_FLAG_PWT; break; case LIMINE_MEMMAP_RESERVED_MAPPED: flags = 0; break; default: - pr_warning( + pr_warn( "[pag] %p - %p: Unknown memmap type %lu. Will remain unmapped.\n", (void*)entry->base, (void*)entry->base + entry->length, entry->type ); diff --git a/kernel/src/panic.c b/kernel/src/panic.c index a0e9fad..82ae73b 100644 --- a/kernel/src/panic.c +++ b/kernel/src/panic.c @@ -2,10 +2,25 @@ #include #include #include +#include #include static int crashing = 0; +void panic_regs_dump(struct isr_int_frame* regs) { + if (regs == NULL) return; + + pr_emerg("Register Dump:\n"); + pr_emerg("\tRAX: %016lx RBX: %016lx RCX: %016lx\n", regs->rax, regs->rbx, regs->rcx); + pr_emerg("\tRDX: %016lx RSI: %016lx RDI: %016lx\n", regs->rdx, regs->rsi, regs->rdi); + pr_emerg("\tR08: %016lx R09: %016lx R10: %016lx\n", regs->r8, regs->r9, regs->r10); + pr_emerg("\tR11: %016lx R12: %016lx R13: %016lx\n", regs->r11, regs->r12, regs->r13); + pr_emerg("\tR14: %016lx R15: %016lx DS/ES: %016lx\n", regs->r14, regs->r15, regs->ds); + pr_emerg("\tRBP: %016lx RSP: %016lx SS: %016lx\n", regs->rbp, regs->user_rsp, regs->user_ss); + pr_emerg("\tRIP: %016lx RFLAGS: %016lx CS: %016lx\n", regs->rip, regs->rflags, regs->cs); + pr_emerg("\n"); +} + void panic_call_trace(void) { uintptr_t* rbp; __asm__ volatile ("movq %%rbp, %0" : "=r"(rbp)); @@ -22,16 +37,17 @@ void panic_call_trace(void) { rbp = (uintptr_t*)*rbp; } + pr_emerg("\n"); } -void panic(const char *fmt, ...) { +void panic(struct isr_int_frame* regs, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - vpanic(fmt, ap); + vpanic(regs, fmt, ap); va_end(ap); } -void vpanic(const char *fmt, va_list ap) { +void vpanic(struct isr_int_frame* regs, const char *fmt, va_list ap) { static char buf[PANIC_MSG_BUFSZ]; size_t len; @@ -44,11 +60,10 @@ void vpanic(const char *fmt, va_list ap) { if (len && buf[len - 1] == '\n') buf[len - 1] = '\0'; pr_emerg("--- [ Kernel panic: %s ] ---\n\n", buf); - pr_emerg("%lu / %lu pages free.\n\n", pmm_free_pages, pmm_total_pages); + panic_regs_dump(regs); panic_call_trace(); - - pr_emerg("\n--- [ End kernel panic: %s ] ---\n", buf); + pr_emerg("--- [ End kernel panic: %s ] ---\n", buf); // We can add some kind of LED blink or smth later :) for (;;) __asm__ volatile ("hlt"); diff --git a/kernel/src/pmm.c b/kernel/src/pmm.c index aa4b746..282d678 100644 --- a/kernel/src/pmm.c +++ b/kernel/src/pmm.c @@ -49,7 +49,7 @@ void* pmm_alloc() { if (pmm_head == NULL) return ERR_PTR(-ENOMEM); uint64_t* addr = pmm_head; - if ((uintptr_t)addr % PAGE_SIZE != 0) panic("pmm_head corrupted."); + if ((uintptr_t)addr % PAGE_SIZE != 0) panic(NULL, "pmm_head corrupted."); pmm_head = (uint64_t*)(*addr); pmm_free_pages--; diff --git a/kernel/src/printk.c b/kernel/src/printk.c index 27c2fbc..4a7ae18 100644 --- a/kernel/src/printk.c +++ b/kernel/src/printk.c @@ -22,7 +22,21 @@ int vprintk(const char* fmt, va_list ap) { if (loglevel > console_loglevel) return 0; + // Loglevel colors + switch (loglevel) { + case LOGLEVEL_EMERG: debugf("\x1b[1;31m"); break; // bold red + case LOGLEVEL_ALERT: debugf("\x1b[1;31m"); break; // bold red + case LOGLEVEL_CRIT: debugf("\x1b[31m"); break; // red + case LOGLEVEL_ERROR: debugf("\x1b[31m"); break; // red + case LOGLEVEL_WARNING: debugf("\x1b[33m"); break; // yellow + case LOGLEVEL_NOTICE: debugf("\x1b[34m"); break; // green + case LOGLEVEL_INFO: debugf("\x1b[37m"); break; // white + case LOGLEVEL_DEBUG: debugf("\x1b[2;32m"); break; // green + } + // TODO: debugf("[%4d.%6d] ", seconds, milliseconds); - return vdebugf(fmt, ap); + int ret = vdebugf(fmt, ap); + debugf("\x1b[0m"); + return ret; } diff --git a/kernel/src/ssp.c b/kernel/src/ssp.c index 6b18123..ef29446 100644 --- a/kernel/src/ssp.c +++ b/kernel/src/ssp.c @@ -10,6 +10,6 @@ uintptr_t __stack_chk_guard = STACK_CHK_GUARD; __noreturn void __stack_chk_fail(void) { - panic("Stack smashing detected!"); + panic(NULL, "Stack smashing detected!"); }