kernel/interrupts.c (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#include "drivers/console.h"
#include "sched/sched.h"
#include "interrupts.h"
#include "pic.h"
#include "core.h"
#include "pit.h"
#define array_sizeof(array) (sizeof(array)/sizeof(array[0]))
#define MAKE_IDT_ENTRY(func, selector, type) { \
(uint16_t)(func), \
(uint16_t)(selector), \
0, \
(uint8_t)(type), \
(uint16_t)(0xC000) \
}
INTERRUPT(default_isr, frame) {
(void)frame;
printk("interrupt was issued\n");
}
INTERRUPT(breakpoint_isr, frame) {
(void)frame;
printk("BREAKPOINT WAS HIT\n");
}
EXCEPTION(double_fault_isr, frame, error_code) {
(void)frame;
(void)error_code;
kpanic("CRITICAL: DOUBLE FAULT");
}
EXCEPTION(gpf_isr, frame, error_code) {
kfault("CRITICAL: GENERAL PROTECTION FAULT", frame, error_code);
}
INTERRUPT(pic1_handler, frame) {
(void)frame;
printk("PIC1 INTERRUPT\n");
pic1_eoi();
}
INTERRUPT(pic2_handler, frame) {
(void)frame;
printk("PIC2 INTERRUPT\n");
pic2_eoi();
}
IDT_ENTRY IDT[INTERRUPT_COUNT];
void install_interrupt(int num, void* func, uint16_t selector, uint8_t type) {
IDT[num].offset_0 = (uint16_t)((uint32_t)func);
IDT[num].selector = selector;
IDT[num].__zero = 0;
IDT[num].type_attr = type;
IDT[num].offset_16 = (uint16_t)((uint32_t)(func) >> 16);
}
struct {
uint16_t limit;
void* offset;
}__attribute__((packed)) IDT_DESC = {
sizeof(IDT),
IDT
};
int interrupts_init(void) {
for (uint32_t i = 0; i < INTERRUPT_COUNT; i++) {
if (i == 0x03) {
install_interrupt(i, breakpoint_isr, 0x18, INT_GATE);
} else if (i == 0x08) {
install_interrupt(i, double_fault_isr, 0x18, INT_GATE);
} else if (i == 0x0d) {
install_interrupt(i, gpf_isr, 0x18, INT_GATE);
} else if (i >= 0x21 && i < 0x28) {
install_interrupt(i, pic1_handler, 0x18, INT_GATE);
} else if (i >= 0x28 && i < 0x30) {
install_interrupt(i, pic2_handler, 0x18, INT_GATE);
} else {
install_interrupt(i, default_isr, 0x18, INT_GATE);
}
}
__asm__ volatile (
"lidt (%0)\n" : :
"m" (IDT_DESC)
);
return 1;
}