From e95bdb55cd0becbdd983865d959e437365f6d759 Mon Sep 17 00:00:00 2001 From: "Pierre-Emmanuel Gob." Date: Fri, 18 Sep 2026 12:02:27 +0200 Subject: [PATCH] exception stubs --- kernel/arch/x86_64/isr.asm | 107 +++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 kernel/arch/x86_64/isr.asm diff --git a/kernel/arch/x86_64/isr.asm b/kernel/arch/x86_64/isr.asm new file mode 100644 index 0000000..6df5da1 --- /dev/null +++ b/kernel/arch/x86_64/isr.asm @@ -0,0 +1,107 @@ +; Nadir exception stubs: vectors 0-31 -> exception_handler. +; +; Runs in 64-bit long mode at Ring 0 (CPL 0). Entered by the CPU with +; IF cleared (interrupt gate); no privilege change, so the CPU pushed +; RIP/CS/RFLAGS plus an error code only on vectors 8, 10-14, 17, 21. +; Fault behavior: a fault here (before the IDT is loaded, or inside the +; handler) triple-faults. Never returns: the C handler halts. +; +; Contract with include/idt.h `struct interrupt_frame`: each stub leaves +; [vector, error] on the stack (pushing a dummy 0 where the CPU did not), +; then isr_common pushes the 15 GPRs and calls the C handler with RDI +; pointing at the frame. Field order must stay in sync. Interrupts stay +; disabled; -mno-red-zone makes the pushes safe. + +bits 64 +section .text + +global isr_stub_table +extern exception_handler + +; Vectors without a CPU error code: normalize with a dummy 0. +%macro ISR_NOERR 1 +global isr_stub_%1 +isr_stub_%1: + push 0 + push %1 + jmp isr_common +%endmacro + +; Vectors where the CPU already pushed an error code: only push the vector. +%macro ISR_ERR 1 +global isr_stub_%1 +isr_stub_%1: + push %1 + jmp isr_common +%endmacro + +ISR_NOERR 0 +ISR_NOERR 1 +ISR_NOERR 2 +ISR_NOERR 3 +ISR_NOERR 4 +ISR_NOERR 5 +ISR_NOERR 6 +ISR_NOERR 7 +ISR_ERR 8 +ISR_NOERR 9 +ISR_ERR 10 +ISR_ERR 11 +ISR_ERR 12 +ISR_ERR 13 +ISR_ERR 14 +ISR_NOERR 15 +ISR_NOERR 16 +ISR_ERR 17 +ISR_NOERR 18 +ISR_NOERR 19 +ISR_NOERR 20 +ISR_ERR 21 +ISR_NOERR 22 +ISR_NOERR 23 +ISR_NOERR 24 +ISR_NOERR 25 +ISR_NOERR 26 +ISR_NOERR 27 +ISR_NOERR 28 +ISR_NOERR 29 +ISR_NOERR 30 +ISR_NOERR 31 + +; Common entry: save GPRs, call void exception_handler(frame in RDI), halt +; if it ever returns (it must not). +isr_common: + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + mov rdi, rsp + call exception_handler + ; Unreachable in practice; park the CPU if the handler returns. + cli +.hang: + hlt + jmp .hang + +section .rodata +align 8 +isr_stub_table: + dq isr_stub_0, isr_stub_1, isr_stub_2, isr_stub_3 + dq isr_stub_4, isr_stub_5, isr_stub_6, isr_stub_7 + dq isr_stub_8, isr_stub_9, isr_stub_10, isr_stub_11 + dq isr_stub_12, isr_stub_13, isr_stub_14, isr_stub_15 + dq isr_stub_16, isr_stub_17, isr_stub_18, isr_stub_19 + dq isr_stub_20, isr_stub_21, isr_stub_22, isr_stub_23 + dq isr_stub_24, isr_stub_25, isr_stub_26, isr_stub_27 + dq isr_stub_28, isr_stub_29, isr_stub_30, isr_stub_31