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
|
section .text
|
||||||
global enable_sse
|
global enable_sse
|
||||||
enable_sse:
|
enable_sse:
|
||||||
@ -77,6 +72,8 @@ load_tr:
|
|||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
extern arch_interrupt_entry
|
extern arch_interrupt_entry
|
||||||
|
extern arch_double_fault
|
||||||
|
extern arch_machine_check
|
||||||
|
|
||||||
_asm_interrupt_entry:
|
_asm_interrupt_entry:
|
||||||
push rax
|
push rax
|
||||||
@ -120,4 +117,36 @@ _asm_interrupt_entry:
|
|||||||
|
|
||||||
iretq
|
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)
|
#define TRAP(x) idt_add_handler(x, (void*)_isr##x, IDT_TA_TrapGate)
|
||||||
|
|
||||||
INT(0);
|
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()
|
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;
|
static IDTR idtr;
|
||||||
idtr.limit = 0x0FFF;
|
idtr.limit = 0x0FFF;
|
||||||
@ -175,14 +215,40 @@ static void setup_idt()
|
|||||||
|
|
||||||
// Interrupt handling
|
// 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
|
// Called from _asm_interrupt_entry
|
||||||
extern "C" void arch_interrupt_entry(Registers* regs)
|
extern "C" void arch_interrupt_entry(Registers* regs)
|
||||||
{
|
{
|
||||||
if (regs->isr < 32)
|
if (regs->isr < 32) handle_x86_exception(regs);
|
||||||
{
|
|
||||||
Serial::println("Exception catched! Halting.");
|
|
||||||
CPU::efficient_halt();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serial::println("IRQ catched! Halting.");
|
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
|
// Generic CPU code
|
||||||
|
|
||||||
static bool test_nx()
|
static bool test_nx()
|
||||||
|
@ -84,11 +84,9 @@ extern "C" [[noreturn]] void _start()
|
|||||||
|
|
||||||
Serial::println("Successfully unmapped address");
|
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
|
*ptr = 16;
|
||||||
// testing exception handling)
|
|
||||||
[[maybe_unused]] volatile int div_rc = 4 / __divisor;
|
|
||||||
|
|
||||||
Serial::println("ERROR: Still here after division by zero");
|
Serial::println("ERROR: Still here after page fault");
|
||||||
|
|
||||||
CPU::efficient_halt();
|
CPU::efficient_halt();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user