Orion
Barry Importing existing Orion kernel d41a53c (3 years, 3 months ago)
/*
* 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);
}