/* Copyright (C) 2021,2022 fef . All rights reserved. */ #pragma once #define _ARCH_INTERRUPT_H_ /** @brief Total number of interrupt lines on x86. */ #define X86_INTR_COUNT 256 /* * These are all reserved interrupt/exception vector numbers for x86 Protected * and Long Mode. Taken from the Intel SDM vol 3, sec 6.3.1, tbl 6-1. */ /** @brief Divide Error */ #define X86_VECT_DE 0 /** @brief Debug Exception */ #define X86_VECT_DB 1 /** @brief Nonmaskable Interrupt */ #define X86_VECT_NMI 2 /** @brief Breakpoint */ #define X86_VECT_BP 3 /** @brief Overflow */ #define X86_VECT_OF 4 /** @brief BOUND Range Exceeded */ #define X86_VECT_BR 5 /** @brief Invalid Opcode (Undefined Opcode) */ #define X86_VECT_UD 6 /** @brief Device Not Available (No Math Coprocessor) */ #define X86_VECT_NM 7 /** @brief Double Fault */ #define X86_VECT_DF 8 /* 9 is reserved (Coprocessor Segment Overrun) */ /** @brief Invalid TSS */ #define X86_VECT_TS 10 /** @brief Segment Not Present */ #define X86_VECT_NP 11 /** @brief Stack-Segment Fault */ #define X86_VECT_SS 12 /** @brief General Protection */ #define X86_VECT_GP 13 /** @brief Page Fault */ #define X86_VECT_PF 14 /* 15 is reserved */ /** @brief x87 FPU Floating Point Error (Math Fault) */ #define X86_VECT_MF 16 /** @brief Alignment Check */ #define X86_VECT_AC 17 /** @brief Machine Check */ #define X86_VECT_MC 18 /** @brief SIMD Floating-Point Exception */ #define X86_VECT_XM 19 /** @brief Virtualization Exception */ #define X86_VECT_VE 20 /** @brief Control Protection Exception */ #define X86_VECT_CP 21 /* 22-31 are Intel reserved, IRQs start at 32 */ /** @brief First interrupt vector number for IRQs */ #define X86_VECT_IRQ_BASE 32 /** @brief Interrupt vector number for IRQ `n` */ #define X86_VECT_IRQ(n) (X86_VECT_IRQ_BASE + (n)) #ifndef _ASM_SOURCE #include #include #ifdef __x86_64__ #include #else #include #endif /** * @brief A single entry in the Interrupt Descriptor Table as laid out in hardware. * Luckily, this is not quite as deranged as the GDT layout. */ struct x86_idt_entry { u16 offset0; /**< @brief ptr to handler, bits 0:15 */ u16 selector; /**< @brief GDT selector, use kernel code segment */ u8 _rsvd0; /**< @brief always 0 */ u8 attr; #define X86_IDT_GATE_TASK32 0x5u #define X86_IDT_GATE_INTR16 0x6u #define X86_IDT_GATE_TRAP16 0x7u #define X86_IDT_GATE_INTR32 0xeu #define X86_IDT_GATE_TRAP32 0xfu #define X86_IDT_STORAGE (1u << 4) /* 0 for interrupt/trap, 1 for system gate */ #define X86_IDT_DPL(x) (((x) & 3u) << 5) #define X86_IDT_PRESENT (1u << 7) u16 offset1; /**< @brief ptr to handler, bits 16:31 */ #ifdef __x86_64__ u32 offset2; u32 _rsvd1; /**< @brief always zero */ #endif } __packed; extern struct x86_idt_entry x86_idt[X86_INTR_COUNT]; /** * @brief Set a gate handler in the Interrupt Descriptor Table. * * @param vector Vector number in the IDT * @param handler Address of the handler function * @param flags Flags for the IDT entry */ void x86_set_gate(u8 vector, void (*handler)(void), u8 flags); /** * @brief Set a trap gate handler in the Interrupt Descriptor table. * * @param vector Vector number in the IDT * @param isr Address of the interrupt service routine */ void x86_set_trap_gate(u8 vector, void (*isr)(void)); void x86_set_intr_gate(u8 vector, void (*isr)(void)); /** @brief Set up the IDT and load it into IDTR. */ void x86_setup_interrupts(void); /** @brief Internal routine performing the actual LIDT instruction. */ extern void x86_load_idt(void); #endif /* not _ASM_SOURCE */