diff --git a/kernel/src/arch/x86_64/CPU.asm b/kernel/src/arch/x86_64/CPU.asm index 329f576f..f59fca57 100644 --- a/kernel/src/arch/x86_64/CPU.asm +++ b/kernel/src/arch/x86_64/CPU.asm @@ -1,8 +1,3 @@ -section .data -global __divisor -__divisor: - dd 0 - section .text global enable_sse enable_sse: @@ -77,6 +72,8 @@ load_tr: %endmacro extern arch_interrupt_entry +extern arch_double_fault +extern arch_machine_check _asm_interrupt_entry: push rax @@ -120,4 +117,36 @@ _asm_interrupt_entry: iretq -ISR 0 ; divide by zero \ No newline at end of file +ISR 0 ; divide by zero (#DE) +ISR 1 ; debug (#DB) +ISR 2 ; non-maskable interrupt +ISR 3 ; breakpoint (#BP) +ISR 4 ; overflow (#OF) +ISR 5 ; bound range exceeded (#BR) +ISR 6 ; invalid opcode (#UD) +ISR 7 ; device not available (#NM) + +global _isr8 +_isr8: ; double fault (#DF) + jmp arch_double_fault + ud2 ; we aren't even pushing a return address for arch_double_fault, this is truly UNREACHABLE + +; ISR 9 obsolete +ISR_ERROR 10 ; invalid tss (#TS) +ISR_ERROR 11 ; segment not present (#NP) +ISR_ERROR 12 ; stack-segment fault (#SS) +ISR_ERROR 13 ; general protection fault (#GP) +ISR_ERROR 14 ; page fault (#PF) +; ISR 15 reserved +ISR 16 ; x87 floating-point exception (#MF) +ISR_ERROR 17 ; alignment check (#AC) + +global _isr18 +_isr18: ; machine check (#MC) + jmp arch_machine_check + ud2 ; same as above + +ISR 19 ; SIMD floating-point exception (#XM) +ISR 20 ; virtualization exception (#VE) +ISR_ERROR 21 ; control-protection exception (#CP) +; ISR 22-31 reserved \ No newline at end of file diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 941f464f..e5144ed8 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -162,10 +162,50 @@ static void idt_add_handler(short num, void* handler, u8 type_attr) #define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate) INT(0); +INT(1); +INT(2); +INT(3); +INT(4); +INT(5); +INT(6); +INT(7); +INT(8); +INT(10); +INT(11); +INT(12); +INT(13); +INT(14); +INT(16); +INT(17); +INT(18); +INT(19); +INT(20); +INT(21); static void setup_idt() { - TRAP(0); // divide by zero + memset(idt, 0, sizeof(idt)); + + TRAP(0); + TRAP(1); + TRAP(2); + TRAP(3); + TRAP(4); + TRAP(5); + TRAP(6); + TRAP(7); + TRAP(8); + TRAP(10); + TRAP(11); + TRAP(12); + TRAP(13); + TRAP(14); + TRAP(16); + TRAP(17); + TRAP(18); + TRAP(19); + TRAP(20); + TRAP(21); static IDTR idtr; idtr.limit = 0x0FFF; @@ -175,14 +215,40 @@ static void setup_idt() // Interrupt handling +#define FIXME_UNHANDLED_INTERRUPT(name) \ + Serial::println("FIXME(interrupt): " name); \ + CPU::efficient_halt(); + +extern "C" void handle_x86_exception([[maybe_unused]] Registers* regs) +{ + switch (regs->isr) + { + case 0: FIXME_UNHANDLED_INTERRUPT("Division by zero"); + case 1: FIXME_UNHANDLED_INTERRUPT("Debug interrupt"); + case 2: FIXME_UNHANDLED_INTERRUPT("NMI (Non-maskable interrupt)"); + case 3: FIXME_UNHANDLED_INTERRUPT("Breakpoint"); + case 4: FIXME_UNHANDLED_INTERRUPT("Overflow"); + case 5: FIXME_UNHANDLED_INTERRUPT("Bound range exceeded"); + case 6: FIXME_UNHANDLED_INTERRUPT("Invalid opcode"); + case 7: FIXME_UNHANDLED_INTERRUPT("Device not available"); + case 10: FIXME_UNHANDLED_INTERRUPT("Invalid TSS"); + case 11: FIXME_UNHANDLED_INTERRUPT("Segment not present"); + case 12: FIXME_UNHANDLED_INTERRUPT("Stack-segment fault"); + case 13: FIXME_UNHANDLED_INTERRUPT("General protection fault"); + case 14: FIXME_UNHANDLED_INTERRUPT("Page fault"); + case 16: FIXME_UNHANDLED_INTERRUPT("x87 floating-point exception"); + case 17: FIXME_UNHANDLED_INTERRUPT("Alignment check"); + case 19: FIXME_UNHANDLED_INTERRUPT("SIMD floating-point exception"); + case 20: FIXME_UNHANDLED_INTERRUPT("Virtualization exception"); + case 21: FIXME_UNHANDLED_INTERRUPT("Control-protection exception"); + default: FIXME_UNHANDLED_INTERRUPT("Reserved exception or #DF/#MC, which shouldn't call handle_x86_exception"); + } +} + // Called from _asm_interrupt_entry extern "C" void arch_interrupt_entry(Registers* regs) { - if (regs->isr < 32) - { - Serial::println("Exception catched! Halting."); - CPU::efficient_halt(); - } + if (regs->isr < 32) handle_x86_exception(regs); else { Serial::println("IRQ catched! Halting."); @@ -190,6 +256,18 @@ extern "C" void arch_interrupt_entry(Registers* regs) } } +extern "C" [[noreturn]] void arch_double_fault() +{ + Serial::println("ERROR: Catched double fault"); + CPU::efficient_halt(); +} + +extern "C" [[noreturn]] void arch_machine_check() +{ + Serial::println("ERROR: Machine check failed"); + CPU::efficient_halt(); +} + // Generic CPU code static bool test_nx() diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index a7be3ce5..deec4804 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -84,11 +84,9 @@ extern "C" [[noreturn]] void _start() Serial::println("Successfully unmapped address"); - extern int __divisor; // divisor is defined as 0, we do it this way so the compiler doesn't catch it (this is - // testing exception handling) - [[maybe_unused]] volatile int div_rc = 4 / __divisor; + *ptr = 16; - Serial::println("ERROR: Still here after division by zero"); + Serial::println("ERROR: Still here after page fault"); CPU::efficient_halt(); } \ No newline at end of file