os

Toy OS
git clone git://git.margiolis.net/os.git
Log | Files | Refs | README | LICENSE

idt.c (5661B)


      1 #include <libc.h>
      2 #include "libk.h"
      3 #include "idt.h"
      4 #include "pic.h"
      5 #include "io.h"
      6 
      7 static void idt_set_gate(struct gate_desc *, void *, u_int, u_int, u_int);
      8 
      9 static struct gate_desc idt[NINT];
     10 static intrhand_t isr[NINT] = { NULL };
     11 
     12 static void
     13 idt_set_gate(struct gate_desc *gd, void *func, u_int sel, u_int dpl, u_int type)
     14 {
     15 	u_int32_t addr;
     16 
     17 	addr = (u_int32_t)func;
     18 	gd->gd_hi = (addr & 0xffff0000) | SEGP | dpl | type;
     19 	gd->gd_lo = (sel << 16) | (addr & 0xffff);
     20 }
     21 
     22 /*
     23  * u_char so `-pedantic` won't complain about taking the
     24  * address of `void`.
     25  */
     26 extern u_char INTVEC(div), INTVEC(dbg), INTVEC(nmsk), INTVEC(bpt), INTVEC(ofl),
     27     INTVEC(bnd), INTVEC(ill), INTVEC(dna), INTVEC(dbl), INTVEC(fpusegm),
     28     INTVEC(tss), INTVEC(missing), INTVEC(stk), INTVEC(prot), INTVEC(page),
     29     INTVEC(rsvd), INTVEC(fpu), INTVEC(align), INTVEC(mchk), INTVEC(simd);
     30 
     31 extern u_char INTVEC(irq0), INTVEC(irq1), INTVEC(irq2), INTVEC(irq3),
     32     INTVEC(irq4), INTVEC(irq5), INTVEC(irq6), INTVEC(irq7), INTVEC(irq8),
     33     INTVEC(irq9), INTVEC(irq10), INTVEC(irq11), INTVEC(irq12), INTVEC(irq13),
     34     INTVEC(irq14), INTVEC(irq15);
     35 
     36 void
     37 idt_init(void)
     38 {
     39 	struct region_desc r_idt;
     40 	int i;
     41 
     42 	for (i = 0; i < NINT; i++)
     43 		idt_set_gate(&idt[i], &INTVEC(rsvd), KCSEL, SEGPL(KPL), SEGIG);
     44 	idt_set_gate(&idt[ 0], &INTVEC(div), KCSEL, SEGPL(KPL), SEGIG);
     45 	idt_set_gate(&idt[ 1], &INTVEC(dbg), KCSEL, SEGPL(KPL), SEGIG);
     46 	idt_set_gate(&idt[ 2], &INTVEC(nmsk), KCSEL, SEGPL(KPL), SEGIG);
     47 	idt_set_gate(&idt[ 3], &INTVEC(bpt), KCSEL, SEGPL(KPL), SEGIG);
     48 	idt_set_gate(&idt[ 4], &INTVEC(ofl), KCSEL, SEGPL(KPL), SEGIG);
     49 	idt_set_gate(&idt[ 5], &INTVEC(bnd), KCSEL, SEGPL(KPL), SEGIG);
     50 	idt_set_gate(&idt[ 6], &INTVEC(ill), KCSEL, SEGPL(KPL), SEGIG);
     51 	idt_set_gate(&idt[ 7], &INTVEC(dna), KCSEL, SEGPL(KPL), SEGIG);
     52 	idt_set_gate(&idt[ 8], &INTVEC(dbl), KCSEL, SEGPL(KPL), SEGIG);
     53 	idt_set_gate(&idt[ 9], &INTVEC(fpusegm), KCSEL, SEGPL(KPL), SEGIG);
     54 	idt_set_gate(&idt[10], &INTVEC(tss), KCSEL, SEGPL(KPL), SEGIG);
     55 	idt_set_gate(&idt[11], &INTVEC(missing), KCSEL, SEGPL(KPL), SEGIG);
     56 	idt_set_gate(&idt[12], &INTVEC(stk), KCSEL, SEGPL(KPL), SEGIG);
     57 	idt_set_gate(&idt[13], &INTVEC(prot), KCSEL, SEGPL(KPL), SEGIG);
     58 	idt_set_gate(&idt[14], &INTVEC(page), KCSEL, SEGPL(KPL), SEGIG);
     59 	idt_set_gate(&idt[15], &INTVEC(rsvd), KCSEL, SEGPL(KPL), SEGIG);
     60 	idt_set_gate(&idt[16], &INTVEC(fpu), KCSEL, SEGPL(KPL), SEGIG);
     61 	idt_set_gate(&idt[17], &INTVEC(align), KCSEL, SEGPL(KPL), SEGIG);
     62 	idt_set_gate(&idt[18], &INTVEC(mchk), KCSEL, SEGPL(KPL), SEGIG);
     63 	idt_set_gate(&idt[19], &INTVEC(simd), KCSEL, SEGPL(KPL), SEGIG);
     64 	/* 20 - 31 are reserved. */
     65 
     66 	pic_remap();
     67 
     68 	idt_set_gate(&idt[32], &INTVEC(irq0), KCSEL, SEGPL(KPL), SEGIG);
     69 	idt_set_gate(&idt[33], &INTVEC(irq1), KCSEL, SEGPL(KPL), SEGIG);
     70 	idt_set_gate(&idt[34], &INTVEC(irq2), KCSEL, SEGPL(KPL), SEGIG);
     71 	idt_set_gate(&idt[35], &INTVEC(irq3), KCSEL, SEGPL(KPL), SEGIG);
     72 	idt_set_gate(&idt[36], &INTVEC(irq4), KCSEL, SEGPL(KPL), SEGIG);
     73 	idt_set_gate(&idt[37], &INTVEC(irq5), KCSEL, SEGPL(KPL), SEGIG);
     74 	idt_set_gate(&idt[38], &INTVEC(irq6), KCSEL, SEGPL(KPL), SEGIG);
     75 	idt_set_gate(&idt[39], &INTVEC(irq7), KCSEL, SEGPL(KPL), SEGIG);
     76 	idt_set_gate(&idt[40], &INTVEC(irq8), KCSEL, SEGPL(KPL), SEGIG);
     77 	idt_set_gate(&idt[41], &INTVEC(irq9), KCSEL, SEGPL(KPL), SEGIG);
     78 	idt_set_gate(&idt[42], &INTVEC(irq10), KCSEL, SEGPL(KPL), SEGIG);
     79 	idt_set_gate(&idt[43], &INTVEC(irq11), KCSEL, SEGPL(KPL), SEGIG);
     80 	idt_set_gate(&idt[44], &INTVEC(irq12), KCSEL, SEGPL(KPL), SEGIG);
     81 	idt_set_gate(&idt[45], &INTVEC(irq13), KCSEL, SEGPL(KPL), SEGIG);
     82 	idt_set_gate(&idt[46], &INTVEC(irq14), KCSEL, SEGPL(KPL), SEGIG);
     83 	idt_set_gate(&idt[47], &INTVEC(irq15), KCSEL, SEGPL(KPL), SEGIG);
     84 
     85 	/*idt_set_gate(&idt[127], &syscall, KCSEL, SEGPL(UPL), SEGIG);*/
     86 
     87 	r_idt.rd_base = (u_int32_t)&idt;
     88 	r_idt.rd_limit = NINT * sizeof(struct gate_desc) - 1;
     89 	__asm__ __volatile("lidt (%0)" : : "r" (&r_idt));
     90 }
     91 
     92 static const char *exceptmsg[32] = {
     93 	"division by zero",
     94 	"debug exception",
     95 	"non maskable interrupt",
     96 	"breakpoint",
     97 	"overflow",
     98 	"out of bounds",
     99 	"invalid opcode",
    100 	"no coprocessor",
    101 	"double fault",
    102 	"coprocessor segment overrun",
    103 	"bad tss",
    104 	"segment not present",
    105 	"stack fault",
    106 	"general protection fault",
    107 	"page fault",
    108 	"15 (reserved)",
    109 	"coprocessor fault",
    110 	"alignment check exception (486+)",
    111 	"machine check exception (pentium/586+)",
    112 	"simd error",
    113 	"20 (reserved)",
    114 	"21 (reserved)",
    115 	"22 (reserved)",
    116 	"23 (reserved)",
    117 	"24 (reserved)",
    118 	"25 (reserved)",
    119 	"26 (reserved)",
    120 	"27 (reserved)",
    121 	"28 (reserved)",
    122 	"29 (reserved)",
    123 	"30 (reserved)",
    124 	"31 (reserved)",
    125 };
    126 
    127 void
    128 intr_handler(struct regs *r)
    129 {
    130 	intrhand_t handler;
    131 
    132 	if ((handler = isr[r->r_intrno]) != NULL)
    133 		handler(r);
    134 	else if (r->r_intrno < ARRLEN(exceptmsg)) {
    135 		dump_regs(r);
    136 		panic("%s: system halted\n", exceptmsg[r->r_intrno]);
    137 	}
    138 	pic_eoi(r->r_intrno);
    139 }
    140 
    141 void
    142 intr_register_handler(int intrno, intrhand_t handler)
    143 {
    144 	if (intrno < 0 || intrno >= NINT)
    145 		panic("invalid interrupt number: %d\n", intrno);
    146 	isr[intrno] = handler;
    147 	pic_mask(intrno, PIC_CLEAR_MASK);
    148 }
    149 
    150 void
    151 dump_regs(struct regs *r)
    152 {
    153 	printf("eax=%#08x\tebx=%#08x\tecx=%#08x\tedx=%#08x\n",
    154 	    r->r_eax, r->r_ebx, r->r_ecx, r->r_edx);
    155 	printf("esi=%#08x\tedi=%#08x\tebp=%#08x\tesp=%#08x\n",
    156 	    r->r_esi, r->r_edi, r->r_ebp, r->r_esp);
    157 	printf("ds=%#04x \t\tes=%#04x \t\tfs=%#04x \t\tgs=%#04x\n",
    158 	    (u_short)r->r_ds, (u_short)r->r_es, (u_short)r->r_fs, (u_short)r->r_gs);
    159 	printf("cs=%#04x \t\tss=%#04x \t\teip=%#08x\teflags=%#08x\n",
    160 	    (u_short)r->r_cs, (u_short)r->r_ss, r->r_eip, r->r_eflags);
    161 	printf("int=%#08x\terr=%#08x\tuesp=%#08x\n",
    162 	    r->r_intrno, r->r_err, r->r_uesp);
    163 }