openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

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(&current->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