Provide stubbed handlers for many more x86 exceptions
I am now officially a big-boy OS developer, I read the Intel manuals for this!! (Not that the OSDev wiki doesn't have the information, but it was missing descriptions for some more obscure exceptions)
This commit is contained in:
parent
860f13cd7e
commit
109de54822
@ -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
|
||||
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
|
@ -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()
|
||||
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user