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 }