Orion
Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)diff --git a/proc/idt.c b/proc/idt.c new file mode 100644 index 0000000..a1552c2 --- /dev/null +++ b/proc/idt.c @@ -0,0 +1,148 @@ +/* + * This file deals with the Interrupt Descriptor Table. It creates a simple + * IDT, with hard-coded handler functions. It is these handler functions that + * can run custom handlers, registered at runtime. This file does not deal with + * dispatching messages/signals to processes on an interrupt. + */ + +#include <stdint.h> +#include <string.h> +#include "proc.h" +#include "../mem/heap.h" +#include "../mem/frame.h" +#include "../screen.h" + +/* Structure for IDT entry */ +static struct IDTEntry { + uint16_t offsetLower, selector; + uint8_t zero, typeAttr; + uint16_t offsetHigher; +} __attribute__((packed)) *IDT; + +void load_idt(uint32_t ptr[2]); +/* Exceptions */ +void exc0(void); +void exc1(void); +void exc2(void); +void exc3(void); +void exc4(void); +void exc5(void); +void exc6(void); +void exc7(void); +void exc8(void); +void exc9(void); +void exc10(void); +void exc11(void); +void exc12(void); +void exc13(void); +void exc14(void); +void exc15(void); +void exc16(void); +void exc17(void); +void exc18(void); +void exc19(void); +void exc20(void); +void exc30(void); +void exc128(void); /* syscall */ +/* Interrutps */ +void irq0(void); +void irq1(void); +void irq2(void); +void irq3(void); +void irq4(void); +void irq5(void); +void irq6(void); +void irq7(void); +void irq8(void); +void irq9(void); +void irq10(void); +void irq11(void); +void irq12(void); +void irq13(void); +void irq14(void); +void irq15(void); + +extern void (**exceptions)(InterruptFrame *); +extern void (**interrupts)(InterruptFrame *); + +/* Install an IDT entry */ +static void +install_idt_entry(uint8_t num, uint32_t addr) +{ + IDT[num].offsetLower = addr & 0xFFFF; + IDT[num].selector = 0x08; + IDT[num].zero = 0; + IDT[num].typeAttr = 0x8E | 0x60; /* Allowed from ring 3 */ + IDT[num].offsetHigher = addr >> 16; +} + +/* Initialise the IDT */ +void +init_idt(void) +{ + IDT = (void *) alloc_frames(1); + + /* Install exceptions */ + install_idt_entry(0, (uint32_t) exc0); + install_idt_entry(1, (uint32_t) exc1); + install_idt_entry(2, (uint32_t) exc2); + install_idt_entry(3, (uint32_t) exc3); + install_idt_entry(4, (uint32_t) exc4); + install_idt_entry(5, (uint32_t) exc5); + install_idt_entry(6, (uint32_t) exc6); + install_idt_entry(7, (uint32_t) exc7); + install_idt_entry(8, (uint32_t) exc8); + install_idt_entry(9, (uint32_t) exc9); + install_idt_entry(10, (uint32_t) exc10); + install_idt_entry(11, (uint32_t) exc11); + install_idt_entry(12, (uint32_t) exc12); + install_idt_entry(13, (uint32_t) exc13); + install_idt_entry(14, (uint32_t) exc14); + install_idt_entry(15, (uint32_t) exc15); + install_idt_entry(16, (uint32_t) exc16); + install_idt_entry(17, (uint32_t) exc17); + install_idt_entry(18, (uint32_t) exc18); + install_idt_entry(19, (uint32_t) exc19); + install_idt_entry(20, (uint32_t) exc20); + install_idt_entry(30, (uint32_t) exc30); + + /* Install interrutps */ + install_idt_entry(32, (uint32_t) irq0); + install_idt_entry(33, (uint32_t) irq1); + install_idt_entry(34, (uint32_t) irq2); + install_idt_entry(35, (uint32_t) irq3); + install_idt_entry(36, (uint32_t) irq4); + install_idt_entry(37, (uint32_t) irq5); + install_idt_entry(38, (uint32_t) irq6); + install_idt_entry(39, (uint32_t) irq7); + install_idt_entry(40, (uint32_t) irq8); + install_idt_entry(41, (uint32_t) irq9); + install_idt_entry(42, (uint32_t) irq10); + install_idt_entry(43, (uint32_t) irq11); + install_idt_entry(44, (uint32_t) irq12); + install_idt_entry(45, (uint32_t) irq13); + install_idt_entry(46, (uint32_t) irq14); + install_idt_entry(47, (uint32_t) irq15); + + /* Install syscall handler */ + install_idt_entry(128, (uint32_t) exc128); + + exceptions = (void (**)(InterruptFrame *)) (IDT + 256); + interrupts = (void (**)(InterruptFrame *)) (exceptions + 32); + memset(exceptions, 0, 1024); + + kprintf("Loaded IDT @ %#.8x, Exceptions @ %#.8x, Interrupts @ %#.8x", + IDT, exceptions, interrupts); +} + +/* Load the IDT */ +void +cpu_load_idt(void) +{ + uint32_t idtAddr, idtPtr[2]; + idtAddr = (uint32_t) IDT; + idtPtr[0] = sizeof(struct IDTEntry) * 256; + idtPtr[0] += (idtAddr & 0xFFFF) << 16; + idtPtr[1] = idtAddr >> 16; + load_idt(idtPtr); +}