CFLAGS = -g -fgnu89-inline -Ikernel/include -Ikernel/include/arch/x86 -ffreestanding -DGIT_COMMIT=\"$(GIT_REV)\"
-KERNEL_OBJ = kernel/entry.o kernel/arch/x86/halt.o kernel/arch/x86/tty/tty.o kernel/drivers/irq/i8259a.o kernel/arch/x86/irq/idt.o kernel/arch/x86/irq/sample_handler.o kernel/kernel.o
+KERNEL_OBJ = kernel/entry.o kernel/arch/x86/halt.o kernel/arch/x86/tty/tty.o kernel/drivers/irq/i8259a.o kernel/arch/x86/irq/idt.o kernel/arch/x86/irq/interrupt.o kernel/arch/x86/irq/stub.o kernel/kernel.o
BOOTLOADER_OBJ = boot/x86/mbr boot/x86/vbr-fat32 boot/x86/stage3/LOADER.BIN boot/x86/stage3/loader.elf
asm volatile ("lidt %0": : "m" (idtr));
}
-void idt_set_descriptor(struct idt_descriptor *idt, uint8_t vector, uint16_t segment, uint32_t offset, uint8_t type, uint8_t dpl)
+void idt_set_descriptor(struct idt_descriptor *idt, uint8_t vector, uint16_t segment, void (*offset)(void), uint8_t type, uint8_t dpl)
{
struct idt_descriptor *descriptor = &idt[vector];
- descriptor->offset_1 = offset & 0xFFFF;
+ descriptor->offset_1 = (uint32_t) offset & 0xFFFF;
descriptor->segsel = segment;
descriptor->unused = 0;
descriptor->type = type;
descriptor->dpl = dpl;
descriptor->present = 1;
- descriptor->offset_2 = offset >> 16;
+ descriptor->offset_2 = (uint32_t) offset >> 16;
}
inline void populate_idtr(struct idtr *idtr, struct idt_descriptor *idt)
--- /dev/null
+#include <irq/idt.h>
+#include <irq/interrupt.h>
+#include <tty.h>
+#include <stddef.h>
+#include <irq/i8259a.h>
+
+/* This table will hold pointers to our interrupt handlers. */
+static int (*int_handler_table[256])(void);
+
+void int_handler(int interrupt)
+{
+ if (int_handler_table[interrupt] == NULL) {
+ kprint("WARNING: Unhandled interrupt ", 0);
+ kprintb(interrupt);
+ kprint(" occurred!\n", 0);
+ } else {
+ int ret = (*int_handler_table[interrupt])();
+ if (ret) {
+ kprint("WARNING: Error while handling interrupt ", 0);
+ kprintb(interrupt);
+ kprint("!\n", 0);
+ }
+ }
+ if (interrupt >= 0x20) {
+ pic_send_eoi(interrupt - 0x20);
+ }
+}
+
+int register_interrupt(int irq, int (*handler)(void))
+{
+ int_handler_table[irq] = handler;
+ if (irq >= 32 && irq < 48) {
+ pic_unmask(irq-32);
+ }
+ return 0;
+}
+++ /dev/null
-#include <tty.h>
-#include <irq/i8259a.h>
-#include <io.h>
-#include <stdint.h>
-#include <mm/paging.h>
-#include <panic.h>
-
-typedef uint32_t uword_t;
-
-struct interrupt_frame {
- uword_t ip;
- uword_t cs;
- uword_t flags;
-};
-
-struct fault_frame {
- struct pf_errcode error_code;
- uintptr_t eip;
- uint16_t cs;
- uint32_t eflags;
-};
-
-struct abort_frame;
-
-__attribute__((interrupt))
-void keyb_handler(struct interrupt_frame *frame)
-{
- pic_send_eoi(1);
- kprint("Got a keyboard interrupt!\n", 0);
- inb(0x60);
- int a = *(int *) (0xa0000000);
-}
-
-__attribute__((interrupt))
-void pf_handler(struct fault_frame *frame)
-{
- int address;
- struct pf_errcode errcode = frame->error_code;
- asm ("mov %%cr2, %0": "=a" (address));
- kprint("A page fault occurred!\n", VGA_COLOR_BRIGHT_RED);
- kprint("Faulting address: ", 0);
- kprintd(address);
- kprint("\n", 0);
- if (!errcode.p) {
- kprint("Address points to non-mapped page\n", 0);
- }
- if (errcode.wr) {
- kprint("Fault occurred while writing to memory\n", 0);
- } else {
- kprint("Fault occurred while reading from memory\n", 0);
- }
- if (errcode.id) {
- kprint("Fault occurred while fetching instruction\n", 0);
- }
- PANIC("page fault");
-}
-
-__attribute__((interrupt))
-void double_fault(struct abort_frame *frame)
-{
- PANIC("double fault");
-}
-
--- /dev/null
+; Stubs for interrupt handlers
+
+bits 32
+section .text
+
+extern int_handler
+
+int_common:
+ cld
+ call int_handler
+ add esp, 4
+ popad
+ iretd
+
+%macro INTERRUPT 1
+global int%1
+int_%1:
+ pushad
+ push dword %1
+ jmp int_common
+%endmacro
+
+%assign i 0
+%rep 48
+INTERRUPT i
+%assign i i+1
+%endrep
+
+; Define flat table containing addresses of handlers
+section .rodata
+global _int_handler_table
+_int_handler_table:
+ %macro INT 1
+ dd int_%1
+ %endmacro
+
+ %assign i 0
+ %rep 48
+ INT i
+ %assign i i+1
+ %endrep
uint32_t base; /* starting address of IDT */
} __attribute__((packed));
-extern void idt_set_descriptor(struct idt_descriptor *idt, uint8_t vector, uint16_t segment, uint32_t offset, uint8_t type, uint8_t dpl);
+extern void idt_set_descriptor(struct idt_descriptor *idt, uint8_t vector, uint16_t segment, void (*offset)(void), uint8_t type, uint8_t dpl);
extern inline void load_idt(struct idtr idtr);
extern inline void populate_idtr(struct idtr *idtr, struct idt_descriptor *idt);
--- /dev/null
+#ifndef X86_INTERRUPT_H
+#define X86_INTERRUPT_H
+
+extern int register_interrupt(int irq, int (*handler)(void));
+
+#endif
#include <tty.h>
#include <io.h>
#include <irq/idt.h>
+#include <irq/interrupt.h>
#include <irq/i8259a.h>
#include <stdint.h>
#include <mm/paging.h>
-struct abort_frame;
-struct interrupt_frame;
-struct fault_frame;
-extern void double_fault(struct abort_frame *frame);
-extern void keyb_handler(struct interrupt_frame *frame);
-extern void pf_handler(struct fault_frame *frame);
-static struct idt_descriptor idt[256] __attribute__((aligned(0x10)));
-static struct idtr idtr __attribute__((aligned(0x10)));
+struct idt_descriptor idt[256] __attribute__((aligned(0x10)));
+struct idtr idtr __attribute__((aligned(0x10)));
+extern void (*_int_handler_table[48])(void);
struct e820_map {
uint64_t base;
kprint("BIOS memory map:\n", 0);
print_e820(mmap, mmap_size);
kprint("Preparing IDT...\n", 0);
- idt_set_descriptor(idt, 8, 0x8, (uint32_t) double_fault, IDT_INTERRUPT_GATE, 0x0);
- idt_set_descriptor(idt, 14, 0x8, (uint32_t) pf_handler, IDT_INTERRUPT_GATE, 0x0);
- idt_set_descriptor(idt, 33, 0x8, (uint32_t) keyb_handler, IDT_INTERRUPT_GATE, 0x0);
+ for (int i=0; i<48; i++) {
+ idt_set_descriptor(idt, i, 0x8, _int_handler_table[i], IDT_INTERRUPT_GATE, 0);
+ }
kprint("IDT prepared, loading...\n", 0);
populate_idtr(&idtr, idt);
load_idt(idtr);
- kprint("IDT loaded, enabling interrupts...\n", 0);
+ kprint("Setting up interrupts...\n", 0);
pic_init(0x20, 0x28);
pic_mask_all();
- pic_unmask(1);
asm volatile ("sti");
kprint("All done\n", 0);
while(1);