You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.7 KiB
C

/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
#include <arch/cpufunc.h>
#include <arch/interrupt.h>
#include <arch/port.h>
#include <arch/segment.h>
#include <arch/trap.h>
#include <gay/kprintf.h>
#include <gay/types.h>
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);
}