os

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

idt.c (5663B)


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