fault.c (7716B)
1 /* Copyright 1998-1999, Brian J. Swetland. All rights reserved. 2 ** Distributed under the terms of the OpenBLT License 3 */ 4 5 #include <i386/io.h> 6 #include "kernel.h" 7 #include "memory.h" 8 #include "smp.h" 9 #include "init.h" 10 #include "port.h" 11 #include "task.h" 12 #include "aspace.h" 13 #include "resource.h" 14 #include "pager.h" 15 #include "i386.h" 16 17 #define noHALT_ON_FAULT 18 #define DEBUG_ON_FAULT 19 #define noCRASH_ON_FAULT 20 21 static char *etable[] = { 22 "Divide-by-zero", 23 "Debug Exception", 24 "NMI", 25 "Breakpoint", 26 "INTO", 27 "BOUNDS", 28 "Invalid Opcode", 29 "Device Not Available", 30 "Double-fault", 31 "Coprocessor segment overrun", 32 "Invalid TSS fault", 33 "Segment Not Present", 34 "Stack Exception", 35 "General Protection", 36 "Page Fault", 37 "*reserved*", 38 "Floating-point error", 39 "Alignment Check", 40 "Machine Check" 41 }; 42 43 typedef void (*ehfunc)(); 44 45 static void __fault(uint32 number, regs r, uint32 eip, uint32 cs, 46 uint32 eflags); 47 static void __faultE(uint32 number, regs r, uint32 error, uint32 eip, uint32 cs, 48 uint32 eflags); 49 50 ehfunc ehfunctab[] = 51 { __fault, __fault, __fault, __fault, 52 __fault, __fault, __fault, __fault, 53 __faultE, __fault, __faultE, __faultE, 54 __faultE, __faultE, __faultE /*page_fault*/, __fault, 55 __fault, __fault, __fault }; 56 57 extern unsigned char *screen; 58 59 task_t *irq_task_map[16]; 60 61 void k_debugger(regs *r, uint32 eip, uint32 cs, uint32 eflags); 62 void terminate(void); 63 64 void print_regs(regs *r, uint32 eip, uint32 cs, uint32 eflags) 65 { 66 kprintf(" EAX = %x EBX = %x ECX = %x EDX = %x", 67 r->eax, r->ebx, r->ecx, r->edx); 68 kprintf(" EBP = %x ESP = %x ESI = %x EDI = %x", 69 r->ebp, r->esp, r->esi, r->edi); 70 kprintf("EFLAGS = %x CS = %x EIP = %x", 71 eflags, cs, eip); 72 } 73 74 void user_debug(regs *r, uint32 *eip, uint32 *eflags) 75 { 76 #if 1 77 return; 78 #else 79 int src,p,sz; 80 task_t *t0; 81 uchar buf[16]; 82 uint32 code; 83 84 p = port_create(0, "debug control"); 85 86 /* wake all blocking objects */ 87 while((t0 = list_detach_head(¤t->rsrc.queue))) task_wake(t0,ERR_RESOURCE); 88 89 kprintf("Waiting on debug control port (%d)... ",p); 90 current->team = kernel_team; // XXX hack 91 92 while((sz = port_recv(p, &src, buf, 16, &code)) >= 0){ 93 } 94 kprintf("debug control error %d\n",sz); 95 96 #endif 97 } 98 99 100 static void __faultE(uint32 number, 101 regs r, uint32 error, 102 uint32 eip, uint32 cs, uint32 eflags) 103 { 104 uint32 _cr2, _cr3; 105 106 kprintf(""); 107 kprintf("*** Exception 0x%X* (%s)",number,etable[number]); 108 #ifdef __SMP__ 109 if (smp_configured) 110 kprintf (" on cpu#%d", smp_my_cpu ()); 111 #endif 112 print_regs(&r, eip, cs, eflags); 113 114 asm("mov %%cr2, %0":"=r" (_cr2)); 115 asm("mov %%cr3, %0":"=r" (_cr3)); 116 kprintf(" cr2 = %x cr3 = %x error = %x",_cr2,_cr3,error); 117 kprintf(""); 118 kprintf("Task %d (%s) crashed.",current->rsrc.id,current->rsrc.name); 119 120 if((cs & 0xFFF8) == SEL_UCODE) user_debug(&r, &eip, &eflags); 121 122 #ifdef DEBUG_ON_FAULT 123 current->flags = tDEAD; 124 k_debugger(&r, eip, cs, eflags); 125 #endif 126 127 #ifdef HALT_ON_FAULT 128 asm("hlt"); 129 #endif 130 131 terminate(); 132 } 133 134 static void __fault(uint32 number, 135 regs r, 136 uint32 eip, uint32 cs, uint32 eflags) 137 { 138 139 kprintf(""); 140 kprintf("*** Exception 0x%X (%s)",number,etable[number]); 141 print_regs(&r, eip, cs, eflags); 142 143 kprintf(""); 144 kprintf("Task %d (%s) crashed.",current->rsrc.id,current->rsrc.name); 145 146 if((cs & 0xFFF8) == SEL_UCODE) user_debug(&r, &eip, &eflags); 147 148 #ifdef DEBUG_ON_FAULT 149 if(number != 2){ 150 current->flags = tDEAD; 151 } 152 k_debugger(&r, eip, cs, eflags); 153 #endif 154 #ifdef HALT_ON_FAULT 155 asm("hlt"); 156 #endif 157 if(number != 2){ 158 terminate(); 159 } 160 } 161 162 void irq_dispatch(regs r, uint32 number) 163 { 164 mask_irq(number); 165 if(irq_task_map[number]){ 166 if(irq_task_map[number]->flags == tSLEEP_IRQ){ 167 preempt(irq_task_map[number],ERR_NONE); 168 } 169 } 170 } 171 172 int kernel_timer = 0; 173 174 unsigned char x[] = { '-', '-', '\\', '\\', '|', '|', '/', '/' }; 175 176 void pulse (void) 177 { 178 #ifndef __SMP__ 179 screen[0] = x[kernel_timer%8]; 180 screen[1] = 7; 181 #else 182 screen[smp_my_cpu () * 2] = x[kernel_timer%8]; 183 screen[smp_my_cpu () * 2 + 1] = 7; 184 #endif 185 } 186 187 void timer_irq(regs r, uint32 eip, uint32 cs, uint32 eflags) 188 { 189 task_t *task; 190 kernel_timer++; 191 192 while((task = rsrc_queue_peek(timer_queue))){ 193 if(task->wait_time <= kernel_timer){ 194 task = rsrc_dequeue(timer_queue); 195 rsrc_enqueue(run_queue, task); 196 } else { 197 break; 198 } 199 } 200 #ifdef PULSE 201 pulse (); 202 #endif 203 swtch(); 204 } 205 206 extern void __null_irq(void); 207 extern void __timer_irq(void); 208 extern void __kbd_irq(void); 209 extern void __syscall(void); 210 211 #define EX(n) extern void __ex##n(void); 212 EX(0); EX(1); EX(2); EX(3); EX(4); EX(5); EX(6); EX(7); EX(8); EX(9); 213 EX(10); EX(11); EX(12); EX(13); EX(14); EX(15); EX(16); EX(17); EX(18); 214 215 #define IQ(n) extern void __irq##n(void); 216 IQ(1); IQ(2); IQ(3); IQ(4); IQ(5); IQ(6); IQ(7); IQ(8); IQ(9); 217 IQ(10); IQ(11); IQ(12); IQ(13); IQ(14); IQ(15); 218 219 extern void __ipi_cf (void), __ipi_tlb (void), __ipi_pte (void), 220 __ipi_resched (void), __ipi_stop (void); 221 222 static void set_irq(uint32 *IDT, int n, void *func) 223 { 224 IDT[2*n+1] = (((uint32) func) & 0xFFFF0000) | 0x00008E00; 225 IDT[2*n] = (((uint32) func) & 0x0000FFFF) | (SEL_KCODE << 16); 226 } 227 228 static void set_irqU(uint32 *IDT, int n, void *func) 229 { 230 IDT[2*n+1] = (((uint32) func) & 0xFFFF0000) | 0x00008E00 | 0x00006000; 231 IDT[2*n] = (((uint32) func) & 0x0000FFFF) | (SEL_KCODE << 16); 232 } 233 234 void __init__ init_idt(uint32 *IDT) 235 { 236 int i; 237 for(i=0;i<16;i++) irq_task_map[i] = NULL; 238 239 set_irq(IDT,0x00,__ex0); 240 set_irq(IDT,0x01,__ex1); 241 set_irq(IDT,0x02,__ex2); 242 set_irq(IDT,0x03,__ex3); 243 set_irq(IDT,0x04,__ex4); 244 set_irq(IDT,0x05,__ex5); 245 set_irq(IDT,0x06,__ex6); 246 set_irq(IDT,0x07,__ex7); 247 set_irq(IDT,0x08,__ex8); 248 set_irq(IDT,0x09,__ex9); 249 set_irq(IDT,0x0A,__ex10); 250 set_irq(IDT,0x0B,__ex11); 251 set_irq(IDT,0x0C,__ex12); 252 set_irq(IDT,0x0D,__ex13); 253 set_irq(IDT,0x0E,__ex14); 254 set_irq(IDT,0x0F,__ex15); 255 set_irq(IDT,0x10,__ex16); 256 set_irq(IDT,0x11,__ex17); 257 set_irq(IDT,0x12,__ex18); 258 259 set_irqU(IDT,0x20,__syscall); 260 261 set_irq(IDT,0x30,__timer_irq); 262 set_irq(IDT,0x31,__irq1); 263 set_irq(IDT,0x32,__irq2); 264 set_irq(IDT,0x33,__irq3); 265 set_irq(IDT,0x34,__irq4); 266 set_irq(IDT,0x35,__irq5); 267 set_irq(IDT,0x36,__irq6); 268 set_irq(IDT,0x37,__irq7); 269 set_irq(IDT,0x38,__irq8); 270 set_irq(IDT,0x39,__irq9); 271 set_irq(IDT,0x3A,__irq10); 272 set_irq(IDT,0x3B,__irq11); 273 set_irq(IDT,0x3C,__irq12); 274 set_irq(IDT,0x3D,__irq13); 275 set_irq(IDT,0x3E,__irq14); 276 set_irq(IDT,0x3F,__irq15); 277 278 #ifdef __SMP__ 279 set_irq(IDT,0x40,__ipi_cf); 280 set_irq(IDT,0x41,__ipi_tlb); 281 set_irq(IDT,0x42,__ipi_pte); 282 set_irq(IDT,0x43,__ipi_resched); 283 set_irq(IDT,0x44,__ipi_stop); 284 #endif 285 286 i386lidt((uint32) IDT, 0x3FF); 287 288 remap_irqs(); 289 unmask_irq(0); 290 unmask_irq(2); 291 } 292 293 void restore_idt(void) 294 { 295 unmap_irqs(); 296 i386lidt(0,0x3FF); 297 } 298 299 300 #ifdef __SMP__ 301 void ipi_dispatch (regs r, uint32 number) 302 { 303 unsigned int config; 304 305 kprintf ("cpu#%d got ipi %x", smp_my_cpu (), number); 306 apic_write (APIC_EOI, 0); 307 switch (number) 308 { 309 case IPI_CACHE_FLUSH: 310 asm ("wbinvd"); 311 break; 312 case IPI_INV_TLB: 313 local_flush_tlb (); 314 break; 315 case IPI_INV_PTE: 316 local_flush_tlb (); /* FIXME */ 317 break; 318 case IPI_INV_RESCHED: 319 break; 320 case IPI_STOP: 321 config = apic_read (APIC_LVTT); 322 apic_write (APIC_LVTT, config | 0x10000); 323 while (!smp_begun) ; 324 apic_write (APIC_LVTT, config); 325 break; 326 } 327 } 328 #endif 329