os

Toy OS
git clone git://git.christosmarg.xyz
Log | Files | Refs | README | LICENSE

idt.c (4543B)


      1 #include "extern.h"
      2 #include "idt.h"
      3 #include "port.h"
      4 
      5 #define N_INT 256
      6 #define KERN_CODESEG 0x08
      7 
      8 static void idt_set_gate(uint8_t, uint32_t);
      9 
     10 static struct idt_gate idt[N_INT];
     11 static void *isr[16] = {NULL};
     12 /* Exception messages for the first 32 interrupts. */
     13 static const char *except[] = {
     14 	"Division By Zero Exception",
     15 	"Debug Exception",
     16 	"Non Maskable Interrupt Exception",
     17 	"Breakpoint Exception",
     18 	"Into Detected Overflow Exception",
     19 	"Out of Bounds Exception",
     20 	"Invalid Opcode Exception",
     21 	"No Coprocessor Exception",
     22 	"Double Fault Exception",
     23 	"Coprocessor Segment Overrun Exception",
     24 	"Bad TSS Exception",
     25 	"Segment Not Present Exception",
     26 	"Stack Fault Exception",
     27 	"General Protection Fault Exception",
     28 	"Page Fault Exception",
     29 	"Unknown Interrupt Exception",
     30 	"Coprocessor Fault Exception",
     31 	"Alignment Check Exception (486+)",
     32 	"Machine Check Exception (Pentium/586+)",
     33 	"Reserved Exception",
     34 	"Reserved Exception",
     35 	"Reserved Exception",
     36 	"Reserved Exception",
     37 	"Reserved Exception",
     38 	"Reserved Exception",
     39 	"Reserved Exception",
     40 	"Reserved Exception",
     41 	"Reserved Exception",
     42 	"Reserved Exception",
     43 	"Reserved Exception",
     44 	"Reserved Exception",
     45 	"Reserved Exception",
     46 };
     47 
     48 static void
     49 idt_set_gate(uint8_t n, uint32_t ptr)
     50 {
     51 	idt[n].off_lo = ptr & 0xffff;
     52 	idt[n].sel = KERN_CODESEG;
     53 	idt[n].zero = 0;
     54 	/* The gate is present and is running in kernel mode. */
     55 	idt[n].flags = 0x8e;
     56 	idt[n].off_hi = (ptr >> 16) & 0xffff;
     57 }
     58 
     59 void
     60 idt_init(void)
     61 {
     62 	struct idt_reg {
     63 		uint16_t limit;	/* IDT size in bytes. */
     64 		uint32_t base;	/* Points at `idt[0]`. */
     65 	} __attribute__((packed)) idtr;
     66 
     67 	(void)memset(&idt, 0, sizeof(idt));
     68 
     69 	/* Set up exception interrupts. */
     70 	idt_set_gate(0, (uint32_t)ex0);
     71 	idt_set_gate(1, (uint32_t)ex1);
     72 	idt_set_gate(2, (uint32_t)ex2);
     73 	idt_set_gate(3, (uint32_t)ex3);
     74 	idt_set_gate(4, (uint32_t)ex4);
     75 	idt_set_gate(5, (uint32_t)ex5);
     76 	idt_set_gate(6, (uint32_t)ex6);
     77 	idt_set_gate(7, (uint32_t)ex7);
     78 	idt_set_gate(8, (uint32_t)ex8);
     79 	idt_set_gate(9, (uint32_t)ex9);
     80 	idt_set_gate(10, (uint32_t)ex10);
     81 	idt_set_gate(11, (uint32_t)ex11);
     82 	idt_set_gate(12, (uint32_t)ex12);
     83 	idt_set_gate(13, (uint32_t)ex13);
     84 	idt_set_gate(14, (uint32_t)ex14);
     85 	idt_set_gate(15, (uint32_t)ex15);
     86 	idt_set_gate(16, (uint32_t)ex16);
     87 	idt_set_gate(17, (uint32_t)ex17);
     88 	idt_set_gate(18, (uint32_t)ex18);
     89 	idt_set_gate(19, (uint32_t)ex19);
     90 	idt_set_gate(20, (uint32_t)ex20);
     91 	idt_set_gate(21, (uint32_t)ex21);
     92 	idt_set_gate(22, (uint32_t)ex22);
     93 	idt_set_gate(23, (uint32_t)ex23);
     94 	idt_set_gate(24, (uint32_t)ex24);
     95 	idt_set_gate(25, (uint32_t)ex25);
     96 	idt_set_gate(26, (uint32_t)ex26);
     97 	idt_set_gate(27, (uint32_t)ex27);
     98 	idt_set_gate(28, (uint32_t)ex28);
     99 	idt_set_gate(29, (uint32_t)ex29);
    100 	idt_set_gate(30, (uint32_t)ex30);
    101 	idt_set_gate(31, (uint32_t)ex31);
    102 
    103 	/* Remap the PIC */
    104 	/* TODO: explain.*/
    105 	outb(P_PIC1_CMD, 0x11);
    106 	outb(P_PIC2_CMD, 0x11);
    107 	outb(P_PIC1_DATA, 0x20);
    108 	outb(P_PIC2_DATA, 0x28);
    109 	outb(P_PIC1_DATA, 0x04);
    110 	outb(P_PIC2_DATA, 0x02);
    111 	outb(P_PIC1_DATA, 0x01);
    112 	outb(P_PIC2_DATA, 0x01);
    113 	outb(P_PIC1_DATA, 0x00);
    114 	outb(P_PIC2_DATA, 0x00);
    115 
    116 	/* Set up IRQs */
    117 	idt_set_gate(32, (uint32_t)irq0);
    118 	idt_set_gate(33, (uint32_t)irq1);
    119 	idt_set_gate(34, (uint32_t)irq2);
    120 	idt_set_gate(35, (uint32_t)irq3);
    121 	idt_set_gate(36, (uint32_t)irq4);
    122 	idt_set_gate(37, (uint32_t)irq5);
    123 	idt_set_gate(38, (uint32_t)irq6);
    124 	idt_set_gate(39, (uint32_t)irq7);
    125 	idt_set_gate(40, (uint32_t)irq8);
    126 	idt_set_gate(41, (uint32_t)irq9);
    127 	idt_set_gate(42, (uint32_t)irq10);
    128 	idt_set_gate(43, (uint32_t)irq11);
    129 	idt_set_gate(44, (uint32_t)irq12);
    130 	idt_set_gate(45, (uint32_t)irq13);
    131 	idt_set_gate(46, (uint32_t)irq14);
    132 	idt_set_gate(47, (uint32_t)irq15);
    133 
    134 	/* https://wiki.osdev.org/Interrupt_Descriptor_Table#Location_and_Size */
    135 	idtr.base = (uint32_t)&idt;
    136 	idtr.limit = N_INT * sizeof(struct idt_gate) - 1;
    137 	__asm__ __volatile__ ("lidtl (%0)" : : "r" (&idtr));
    138 }
    139 
    140 void
    141 int_handler(struct reg *r)
    142 {
    143 	void (*handler)(struct reg *);
    144 
    145 	/*
    146 	 * We'll call the handler only if the interrupt number is > 32,
    147 	 * which means that we're dealing with an IRQ and not an exception.
    148 	 */
    149 	if (r->intno >= 32 && (handler = isr[r->intno - 32]) != NULL)
    150 		handler(r);
    151 	/* Entries below index 32 in the IDT are exceptions, we need to hang. */
    152 	else if (r->intno < 32) {
    153 		tty_write(except[r->intno]);
    154 		tty_write(". System halted...\n");
    155 		__asm__ __volatile__ ("hlt");
    156 	}
    157 	if (r->intno >= 40)
    158 		outb(P_PIC2_CMD, 0x20);
    159 	outb(P_PIC1_CMD, 0x20);
    160 }
    161 
    162 void
    163 int_add_handler(uint8_t intno, void (*handler)(struct reg *r))
    164 {
    165 	isr[intno] = handler;
    166 }