/* Copyright (C) 2021,2022 fef . All rights reserved. */ #include #include #include #include #include #include #include struct x86_idt_entry x86_idt[X86_INTR_COUNT] __aligned(16); void x86_setup_interrupts(void) { /* make sure all IRQs are masked first */ x86_outb(X86_PORT_PIC1_DATA, 0xff); x86_outb(X86_PORT_PIC2_DATA, 0xff); x86_set_trap_gate(X86_VECT_DE, _x86_isr_divide_error); x86_set_trap_gate(X86_VECT_DB, _x86_isr_debug_exception); x86_set_trap_gate(X86_VECT_NMI, _x86_isr_nmi); x86_set_trap_gate(X86_VECT_BP, _x86_isr_breakpoint); x86_set_trap_gate(X86_VECT_OF, _x86_isr_overflow); x86_set_trap_gate(X86_VECT_BR, _x86_isr_bound_range_exceeded); x86_set_trap_gate(X86_VECT_UD, _x86_isr_invalid_opcode); x86_set_trap_gate(X86_VECT_NM, _x86_isr_device_not_available); x86_set_trap_gate(X86_VECT_DF, _x86_isr_double_fault); x86_set_trap_gate(X86_VECT_TS, _x86_isr_invalid_tss); x86_set_trap_gate(X86_VECT_NP, _x86_isr_segment_not_present); x86_set_trap_gate(X86_VECT_SS, _x86_isr_stack_segment_fault); x86_set_trap_gate(X86_VECT_GP, _x86_isr_general_protection); x86_set_trap_gate(X86_VECT_PF, _x86_isr_page_fault); x86_set_trap_gate(X86_VECT_MF, _x86_isr_x87_fpu_error); x86_set_trap_gate(X86_VECT_AC, _x86_isr_alignment_check); x86_set_trap_gate(X86_VECT_MC, _x86_isr_machine_check); x86_set_trap_gate(X86_VECT_XM, _x86_isr_simd_floating_point_exception); x86_set_trap_gate(X86_VECT_VE, _x86_isr_virtualization_exception); x86_set_trap_gate(X86_VECT_CP, _x86_isr_control_protection_exception); x86_load_idt(); enable_intr(); } void x86_set_gate(u8 vector, void (*handler)(void), u8 flags) { struct x86_idt_entry *entry = &x86_idt[vector]; #ifdef __x86_64__ entry->selector = X86_64_KERN_CS; #else entry->selector = X86_32_KERN_CS; #endif entry->_rsvd0 = 0; entry->attr = flags; entry->offset0 = (uintptr_t)handler & 0xffff; entry->offset1 = ((uintptr_t)handler >> 16) & 0xffff; #ifdef __x86_64__ entry->offset2 = ((uintptr_t)handler >> 32) & 0xffffffff; entry->_rsvd1 = 0; #endif } void x86_set_trap_gate(u8 vector, void (*isr)(void)) { u8 flags = X86_IDT_PRESENT | X86_IDT_GATE_TRAP32 | X86_IDT_DPL(0); if (vector < X86_VECT_IRQ_BASE) x86_set_gate(vector, isr, flags); else kprintf("Tried to assign non-trap vector %d to a trap gate\n", vector); } void x86_set_intr_gate(u8 vector, void (*isr)(void)) { u8 flags = X86_IDT_PRESENT | X86_IDT_GATE_INTR32 | X86_IDT_DPL(0); if (vector < X86_VECT_IRQ_BASE) kprintf("Tried to assign non-interrupt vector %d to an interrupt gate\n", vector); else x86_set_gate(vector, isr, flags); }