BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / blob / d3f787c50eda2dadb77ae216aef1f0bd0a686ae3 / kernel / idt.c

// Related

Nucleus

Barry Initialise ACPI later acd0915 (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 <nucleus/panic.h>
#include <nucleus/memory.h>
#include <nucleus/cpu.h>
#include <io.h>
#include "desc.h"

/* Structure for an IDT Entry */
static struct IDTEntry {
	uint16_t offsetLower, selector;
	uint8_t zero, typeAttr;
	uint16_t offsetHigher;
} __attribute__((packed)) *IDT;

void (**exceptions)(struct InterruptFrame *, uint32_t);
void (**interrupts)(struct InterruptFrame *);

/* Install an IDT Entry */
static void
install_idt_entry(uint8_t num, void *addr)
{
	IDT[num].offsetLower = (uintptr_t) addr & 0xFFFF;
	IDT[num].selector = 0x08;
	IDT[num].zero = 0;
	IDT[num].typeAttr = 0x8E | 0x60; /* Allowed from ring 3 */
	IDT[num].offsetHigher = (uintptr_t) addr >> 16;
}

/* First level generic exception handler */
static void
exc_handler(int num, struct InterruptFrame *frame, uint32_t err)
{
	asm volatile("cli");

	if (!exceptions[num]) {
		panic("Failed to handle exception %d (%#.8x)",
		      num, err);
	}

	ASSERT(exceptions[num]);
	exceptions[num](frame, err);

	/* Send APIC EOI */
	if (apic)
		LAPIC(0xB0) = 0;

	asm volatile("sti");
}

/* First level generic interrupt handler */
static void
int_handler(int num, struct InterruptFrame *frame)
{
	asm volatile("cli");

	if (interrupts[num - 32])
		interrupts[num - 32](frame);

	/* Send EOI */
	if (num >= 32 + 8)
		outb(0xA0, 0x20);
	outb(0x20, 0x20);
	/* Send APIC EOI*/
	if (apic)
		LAPIC(0xB0) = 0;

	asm volatile("sti");
}

/* Exceptions */
__attribute__((interrupt))
static void
exc0(struct InterruptFrame *frame)
{
	exc_handler(0, frame, 0);
}
__attribute__((interrupt))
static void
exc1(struct InterruptFrame *frame)
{
	exc_handler(1, frame, 0);
}
__attribute__((interrupt))
static void
exc2(struct InterruptFrame *frame)
{
	exc_handler(2, frame, 0);
}
__attribute__((interrupt))
static void
exc3(struct InterruptFrame *frame)
{
	exc_handler(3, frame, 0);
}
__attribute__((interrupt))
static void
exc4(struct InterruptFrame *frame)
{
	exc_handler(4, frame, 0);
}
__attribute__((interrupt))
static void
exc5(struct InterruptFrame *frame)
{
	exc_handler(5, frame, 0);
}
__attribute__((interrupt))
static void
exc6(struct InterruptFrame *frame)
{
	exc_handler(6, frame, 0);
}
__attribute__((interrupt))
static void
exc7(struct InterruptFrame *frame)
{
	exc_handler(7, frame, 0);
}
__attribute__((interrupt))
static void
exc8(struct InterruptFrame *frame, uint32_t err)
{
	exc_handler(8, frame, err);
}
__attribute__((interrupt))
static void
exc9(struct InterruptFrame *frame)
{
	exc_handler(9, frame, 0);
}
__attribute__((interrupt))
static void
exc10(struct InterruptFrame *frame, uint32_t err)
{
	exc_handler(10, frame, err);
}
__attribute__((interrupt))
static void
exc11(struct InterruptFrame *frame, uint32_t err)
{
	exc_handler(11, frame, err);
}
__attribute__((interrupt))
static void
exc12(struct InterruptFrame *frame, uint32_t err)
{
	exc_handler(12, frame, err);
}
__attribute__((interrupt))
static void
exc13(struct InterruptFrame *frame, uint32_t err)
{
	exc_handler(13, frame, err);
}
__attribute__((interrupt))
static void
exc14(struct InterruptFrame *frame, uint32_t err)
{
	exc_handler(14, frame, err);
}
__attribute__((interrupt))
static void
exc15(struct InterruptFrame *frame)
{
	exc_handler(15, frame, 0);
}
__attribute__((interrupt))
static void
exc16(struct InterruptFrame *frame)
{
	exc_handler(16, frame, 0);
}
__attribute__((interrupt))
static void
exc17(struct InterruptFrame *frame, uint32_t err)
{
	exc_handler(17, frame, err);
}
__attribute__((interrupt))
static void
exc18(struct InterruptFrame *frame)
{
	exc_handler(18, frame, 0);
}
__attribute__((interrupt))
static void
exc19(struct InterruptFrame *frame)
{
	exc_handler(19, frame, 0);
}
__attribute__((interrupt))
static void
exc20(struct InterruptFrame *frame)
{
	exc_handler(20, frame, 0);
}
__attribute__((interrupt))
static void
exc30(struct InterruptFrame *frame)
{
	exc_handler(30, frame, 0);
}
__attribute__((interrupt))
static void
exc128(struct InterruptFrame *frame)
{
	exc_handler(128, frame, 0);
}

/* Interrupts */
__attribute__((interrupt))
static void
int0(struct InterruptFrame *frame)
{
	int_handler(32, frame);
}
__attribute__((interrupt))
static void
int1(struct InterruptFrame *frame)
{
	int_handler(33, frame);
}
__attribute__((interrupt))
static void
int2(struct InterruptFrame *frame)
{
	int_handler(34, frame);
}
__attribute__((interrupt))
static void
int3(struct InterruptFrame *frame)
{
	int_handler(35, frame);
}
__attribute__((interrupt))
static void
int4(struct InterruptFrame *frame)
{
	int_handler(36, frame);
}
__attribute__((interrupt))
static void
int5(struct InterruptFrame *frame)
{
	int_handler(37, frame);
}
__attribute__((interrupt))
static void
int6(struct InterruptFrame *frame)
{
	int_handler(38, frame);
}
__attribute__((interrupt))
static void
int7(struct InterruptFrame *frame)
{
	int_handler(39, frame);
}
__attribute__((interrupt))
static void
int8(struct InterruptFrame *frame)
{
	int_handler(40, frame);
}
__attribute__((interrupt))
static void
int9(struct InterruptFrame *frame)
{
	int_handler(41, frame);
}
__attribute__((interrupt))
static void
int10(struct InterruptFrame *frame)
{
	int_handler(42, frame);
}
__attribute__((interrupt))
static void
int11(struct InterruptFrame *frame)
{
	int_handler(43, frame);
}
__attribute__((interrupt))
static void
int12(struct InterruptFrame *frame)
{
	int_handler(44, frame);
}
__attribute__((interrupt))
static void
int13(struct InterruptFrame *frame)
{
	int_handler(45, frame);
}
__attribute__((interrupt))
static void
int14(struct InterruptFrame *frame)
{
	int_handler(46, frame);
}
__attribute__((interrupt))
static void
int15(struct InterruptFrame *frame)
{
	int_handler(47, frame);
}

/* Initialise the IDT */
void
init_idt(void)
{
	IDT = (void *) alloc_frame();

	/* Install exceptions */
	install_idt_entry(0, exc0);
	install_idt_entry(1, exc1);
	install_idt_entry(2, exc2);
	install_idt_entry(3, exc3);
	install_idt_entry(4, exc4);
	install_idt_entry(5, exc5);
	install_idt_entry(6, exc6);
	install_idt_entry(7, exc7);
	install_idt_entry(8, exc8);
	install_idt_entry(9, exc9);
	install_idt_entry(10, exc10);
	install_idt_entry(11, exc11);
	install_idt_entry(12, exc12);
	install_idt_entry(13, exc13);
	install_idt_entry(14, exc14);
	install_idt_entry(15, exc15);
	install_idt_entry(16, exc16);
	install_idt_entry(17, exc17);
	install_idt_entry(18, exc18);
	install_idt_entry(19, exc19);
	install_idt_entry(20, exc20);
	install_idt_entry(30, exc30);

	/* Install interrupts */
	install_idt_entry(32, int0);
	install_idt_entry(33, int1);
	install_idt_entry(34, int2);
	install_idt_entry(35, int3);
	install_idt_entry(36, int4);
	install_idt_entry(37, int5);
	install_idt_entry(38, int6);
	install_idt_entry(39, int7);
	install_idt_entry(40, int8);
	install_idt_entry(41, int9);
	install_idt_entry(42, int10);
	install_idt_entry(43, int11);
	install_idt_entry(44, int12);
	install_idt_entry(45, int13);
	install_idt_entry(46, int14);
	install_idt_entry(47, int15);

	/* Install system call handler */
	install_idt_entry(128, exc128);

	exceptions = (void *) (IDT + 256);
	interrupts = (void *) (exceptions + 32);
	memset(exceptions, 0, 1024);
}

/* Load the IDT */
void
cpu_load_idt(void)
{
	struct DescRecord ptr = {
		.limit = sizeof(struct IDTEntry) * 256,
		.base = (uintptr_t) IDT,
	};
	asm volatile("lidt %0" :: "m" (ptr));
}

/* Register an exception handler */
void
register_exception(int num, exc_handler_t addr)
{
	if (num >= 0 && num < 32)
		exceptions[num] = addr;
}

/* Register an interrupt handler */
void
register_interrupt(int num, int_handler_t addr)
{
	if (num >= 0 && num < 224)
		interrupts[num] = addr;
}