Files
kern/kernel/src/isr.c
T

123 lines
3.3 KiB
C

#include <kernel.h>
#include <string.h>
#include <system.h>
#include <errno.h>
#include <idt.h>
#include <isr.h>
isr_handler_ptr irq_handlers[ISR_COUNT];
const char* exceptions[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point",
"Virtualization",
"Control Protection",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
void pic_disable(void) {
outb(0x21, 0xFF); iowait();
outb(0xA1, 0xFF); iowait();
}
void pic_remap(void) {
outb(0x20, 0x11); iowait();
outb(0xA0, 0x11); iowait();
outb(0x21, 0x20); iowait();
outb(0xA1, 0x28); iowait();
outb(0x21, 0x04); iowait();
outb(0xA1, 0x02); iowait();
outb(0x21, 0x01); iowait();
outb(0xA1, 0x01); iowait();
outb(0x21, 0x00); iowait();
outb(0xA1, 0x00); iowait();
// pic_disable(); For APIC
}
int isr_init(void) {
memset(irq_handlers, 0, sizeof(irq_handlers));
idt_init();
for (int i = 0; i < 48; i++) {
// First 32 IRSs are exceptions (traps) and the next 16 are hardware interrupts
idt_set_gate(i, isr_redirect_table[i], i < 32 ? IDT_FLAG_TRAP : IDT_FLAG_INT, 0);
}
idt_set_gate(0x02, isr_redirect_table[2], IDT_FLAG_TRAP, 2); // Use IST2 for NMIs
idt_set_gate(0x03, isr_redirect_table[3], IDT_FLAG_USER, 0); // Allow breakpoints
idt_set_gate(0x08, isr_redirect_table[8], IDT_FLAG_TRAP, 1); // Use IST1 for Double Faults
idt_set_gate(0x80, isr128, IDT_FLAG_USER, 0); // Syscall
pic_remap();
// TODO: apic_init();
sti();
return SUCCESS;
}
void isr_register(uint8_t i, isr_handler_ptr handler) {
if (i >= ISR_COUNT) return; // secutiry B)
irq_handlers[i] = handler;
}
void isr_send_eoi(uint8_t irq) {
if (irq >= 8) outb(0xA0, 0x20);
outb(0x20, 0x20);
}
// TODO: Write fault handlers and make this more robust
void isr_handle_interrupt(size_t rsp) {
struct isr_int_frame* iframe = (void*)rsp;
if (iframe->interrupt < 32) {
pr_emerg("Register Dump:\n");
pr_emerg("\tRAX: %016lu RBX: %016lu RCX: %016lx\n", iframe->rax, iframe->rbx, iframe->rcx);
pr_emerg("\tRDX: %016lu RSI: %016lu RDI: %016lx\n", iframe->rdx, iframe->rsi, iframe->rdi);
pr_emerg("\tR08: %016lu R09: %016lu R10: %016lx\n", iframe->r8, iframe->r9, iframe->r10);
pr_emerg("\tR11: %016lu R12: %016lu R13: %016lx\n", iframe->r11, iframe->r12, iframe->r13);
pr_emerg("\tR14: %016lu R15: %016lu DS/ES: %016lx\n", iframe->r14, iframe->r15, iframe->ds);
pr_emerg("\tRBP: %016lu RSP: %016lu SS: %016lx\n", iframe->rbp, iframe->user_rsp, iframe->user_ss);
pr_emerg("\tRIP: %016lu RFLAGS: %016lx CS: %016lx\n", iframe->rip, iframe->rflags, iframe->cs);
if (iframe->error) pr_emerg("Error code: 0x%lx\n", iframe->error);
panic(exceptions[iframe->interrupt]);
} else if (iframe->interrupt >= 32 && iframe->interrupt < 48) {
// ISRs 32-47 - Hardware interrupts
uint8_t irq = iframe->interrupt - 32;
isr_send_eoi(irq);
if (irq_handlers[irq]) irq_handlers[irq](iframe);
} else if (iframe->interrupt == 128) {
// ISR 128 - System call
pr_notice("SYSCALL!\n");
}
}