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.

128 lines
3.5 KiB
C

/* Copyright (C) 2021,2022 fef <owo@fef.moe>. 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 <gay/cdefs.h>
#include <gay/types.h>
#ifdef __x86_64__
#include <amd64/interrupt.h>
#else
#include <i386/interrupt.h>
#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 */