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
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 */
|