From: Duje Mihanović Date: Tue, 14 Jun 2022 09:23:08 +0000 (+0200) Subject: Use interrupt frame and new double fault handler X-Git-Url: http://git.dujemihanovic.xyz/login.html?a=commitdiff_plain;h=e44e20a9d916a35aaa07dc2cc2b5194600bb742b;p=nameless-os.git Use interrupt frame and new double fault handler --- diff --git a/kernel/arch/x86/irq/interrupt.c b/kernel/arch/x86/irq/interrupt.c index b2abef9..f7cbcdc 100644 --- a/kernel/arch/x86/irq/interrupt.c +++ b/kernel/arch/x86/irq/interrupt.c @@ -5,16 +5,17 @@ #include /* This table will hold pointers to our interrupt handlers. */ -static int (*int_handler_table[256])(void); +static int (*int_handler_table[256])(struct interrupt_frame *); -void int_handler(int interrupt) +void int_handler(struct interrupt_frame *frame) { + int interrupt = frame->interrupt; if (int_handler_table[interrupt] == NULL) { kprint("WARNING: Unhandled interrupt ", 0); kprintb(interrupt); kprint(" occurred!\n", 0); } else { - int ret = (*int_handler_table[interrupt])(); + int ret = (*int_handler_table[interrupt])(frame); if (ret) { kprint("WARNING: Error while handling interrupt ", 0); kprintb(interrupt); @@ -26,7 +27,7 @@ void int_handler(int interrupt) } } -int register_interrupt(int irq, int (*handler)(void)) +int register_interrupt(int irq, int (*handler)(struct interrupt_frame *)) { int_handler_table[irq] = handler; if (irq >= 32 && irq < 48) { diff --git a/kernel/arch/x86/irq/stub.s b/kernel/arch/x86/irq/stub.s index c15969a..e5e43e5 100644 --- a/kernel/arch/x86/irq/stub.s +++ b/kernel/arch/x86/irq/stub.s @@ -7,24 +7,77 @@ extern int_handler int_common: cld + push esp call int_handler - add esp, 4 + add esp, 12 popad iretd %macro INTERRUPT 1 -global int%1 +global int_%1 int_%1: + push dword 0 pushad push dword %1 jmp int_common %endmacro -%assign i 0 -%rep 48 -INTERRUPT i -%assign i i+1 -%endrep +%macro INTERRUPT_ERR 1 +global int_%1 +int_%1: + pushad + push dword %1 + jmp int_common +%endmacro + +INTERRUPT 0 +INTERRUPT 1 +INTERRUPT 2 +INTERRUPT 3 +INTERRUPT 4 +INTERRUPT 5 +INTERRUPT 6 +INTERRUPT 7 +INTERRUPT_ERR 8 +INTERRUPT 9 +INTERRUPT_ERR 10 +INTERRUPT_ERR 11 +INTERRUPT_ERR 12 +INTERRUPT_ERR 13 +INTERRUPT_ERR 14 +INTERRUPT 15 +INTERRUPT 16 +INTERRUPT_ERR 17 +INTERRUPT 18 +INTERRUPT 19 +INTERRUPT 20 +INTERRUPT_ERR 21 +INTERRUPT 22 +INTERRUPT 23 +INTERRUPT 24 +INTERRUPT 25 +INTERRUPT 26 +INTERRUPT 27 +INTERRUPT 28 +INTERRUPT_ERR 29 +INTERRUPT_ERR 30 +INTERRUPT 31 +INTERRUPT 32 +INTERRUPT 33 +INTERRUPT 34 +INTERRUPT 35 +INTERRUPT 36 +INTERRUPT 37 +INTERRUPT 38 +INTERRUPT 39 +INTERRUPT 40 +INTERRUPT 41 +INTERRUPT 42 +INTERRUPT 43 +INTERRUPT 44 +INTERRUPT 45 +INTERRUPT 46 +INTERRUPT 47 ; Define flat table containing addresses of handlers section .rodata diff --git a/kernel/include/arch/x86/irq/idt.h b/kernel/include/arch/x86/irq/idt.h index 501e5cd..f16cf96 100644 --- a/kernel/include/arch/x86/irq/idt.h +++ b/kernel/include/arch/x86/irq/idt.h @@ -2,6 +2,7 @@ #define X86_IDT_H #include +#include #define IDT_VECTOR_COUNT 256 /* our IDT will have 256 vectors */ #define IDT_DESCRIPTOR_SIZE 8 /* each IDT descriptor is 8 bytes long */ diff --git a/kernel/include/arch/x86/irq/interrupt.h b/kernel/include/arch/x86/irq/interrupt.h index fbecdd8..f43b28c 100644 --- a/kernel/include/arch/x86/irq/interrupt.h +++ b/kernel/include/arch/x86/irq/interrupt.h @@ -1,6 +1,22 @@ #ifndef X86_INTERRUPT_H #define X86_INTERRUPT_H -extern int register_interrupt(int irq, int (*handler)(void)); +struct interrupt_frame { + int interrupt; + int edi; + int esi; + int ebp; + int esp; /* before pushad */ + int ebx; + int edx; + int ecx; + int eax; + int err_code; + int eip; + int cs; + int eflags; +}; + +extern int register_interrupt(int irq, int (*handler)(struct interrupt_frame *)); #endif diff --git a/kernel/kernel.c b/kernel/kernel.c index 5a6a82d..8520906 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -34,6 +34,48 @@ void print_e820(struct e820_map *mmap, int mmap_size) } } +/* Small handler for double faults. Will be put elsewhere eventually. */ +int double_fault_handler(struct interrupt_frame *frame) +{ + kprint("PANIC: Double fault occurred!\n", VGA_COLOR_BRIGHT_RED); + kprint("EAX: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->eax); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("EBX: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->ebx); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("ECX: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->ecx); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("EDX: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->edx); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("EBP: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->ebp); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("ESP: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->esp); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("ESI: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->esi); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("EDI: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->edi); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("EIP: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->eip); + kprint("\n", VGA_COLOR_BRIGHT_RED); + kprint("EFLAGS: ", VGA_COLOR_BRIGHT_RED); + kprintd(frame->eflags); + kprint("\n", VGA_COLOR_BRIGHT_RED); + + /* IF has already been cleared for us */ + asm("cli"); +halt: + asm("hlt"); + goto halt; +} + void kmain(struct e820_map *mmap, int mmap_size) { screen_clear(); @@ -50,6 +92,7 @@ void kmain(struct e820_map *mmap, int mmap_size) populate_idtr(&idtr, idt); load_idt(idtr); kprint("Setting up interrupts...\n", 0); + register_interrupt(8, &double_fault_handler); pic_init(0x20, 0x28); pic_mask_all(); asm volatile ("sti");