diff --git a/kernel/arch/x86_64/isr.asm b/kernel/arch/x86_64/isr.asm index 6df5da1..809e9a4 100644 --- a/kernel/arch/x86_64/isr.asm +++ b/kernel/arch/x86_64/isr.asm @@ -16,7 +16,9 @@ bits 64 section .text global isr_stub_table +global irq_stub_table extern exception_handler +extern irq_dispatch ; Vectors without a CPU error code: normalize with a dummy 0. %macro ISR_NOERR 1 @@ -105,3 +107,91 @@ isr_stub_table: 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 + +; --------------------------------------------------------------------------- +; Nadir IRQ stubs: vectors 32-47 (remapped 8259 IRQs 0-15) -> irq_dispatch. +; +; Same Ring 0 / CPL 0 entry context as the exception stubs above: the CPU +; entered with IF cleared (interrupt gate), no privilege change, so only +; RIP/CS/RFLAGS were pushed. IRQs never carry a CPU error code, so every +; stub normalizes with a dummy 0 exactly like ISR_NOERR, keeping the +; [vector, error] layout — and thus struct interrupt_frame — identical to +; the exception path. Field order must stay in sync with include/idt.h. +; The EOI is sent by the C dispatcher (pic_eoi), not here, so a future +; per-IRQ EOI policy only touches C. -mno-red-zone keeps pushes safe. + +section .text +%macro IRQ_NOERR 1 +global isr_stub_%1 +isr_stub_%1: + push 0 + push %1 + jmp irq_common +%endmacro + +IRQ_NOERR 32 +IRQ_NOERR 33 +IRQ_NOERR 34 +IRQ_NOERR 35 +IRQ_NOERR 36 +IRQ_NOERR 37 +IRQ_NOERR 38 +IRQ_NOERR 39 +IRQ_NOERR 40 +IRQ_NOERR 41 +IRQ_NOERR 42 +IRQ_NOERR 43 +IRQ_NOERR 44 +IRQ_NOERR 45 +IRQ_NOERR 46 +IRQ_NOERR 47 + +; Common IRQ entry: save GPRs, call void irq_dispatch(frame in RDI), +; restore GPRs, drop [vector, error], return to the interrupted code. +; Unlike isr_common (which halts), this path must iretq: IRQs are +; resumable. Interrupts stay disabled throughout (IF=0 on entry via an +; interrupt gate; irq_dispatch runs with IF cleared; iretq restores the +; caller's RFLAGS). +irq_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 irq_dispatch + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax + add rsp, 16 + iretq + +section .rodata +align 8 +irq_stub_table: + dq isr_stub_32, isr_stub_33, isr_stub_34, isr_stub_35 + dq isr_stub_36, isr_stub_37, isr_stub_38, isr_stub_39 + dq isr_stub_40, isr_stub_41, isr_stub_42, isr_stub_43 + dq isr_stub_44, isr_stub_45, isr_stub_46, isr_stub_47