1 /* 2 * linux/kernel/traps.c 3 * 4 * (C) 1991 Linus Torvalds 5 */ 6 7 /* 8 * 'Traps.c' handles hardware traps and faults after we have saved some 9 * state in 'asm.s'. Currently mostly a debugging-aid, will be extended 10 * to mainly kill the offending process (probably by giving it a signal, 11 * but possibly by killing it outright if necessary). 12 */ 13 #include <string.h> 14 15 #include <linux/head.h> 16 #include <linux/sched.h> 17 #include <linux/kernel.h> 18 #include <asm/system.h> 19 #include <asm/segment.h> 20 #include <asm/io.h> 21 22 #define get_seg_byte(seg,addr) ({ 23 register char __res; 24 __asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" 25 :"=a" (__res):"" (seg),"m" (*(addr))); 26 __res;}) 27 28 #define get_seg_long(seg,addr) ({ 29 register unsigned long __res; 30 __asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" 31 :"=a" (__res):"" (seg),"m" (*(addr))); 32 __res;}) 33 34 #define _fs() ({ 35 register unsigned short __res; 36 __asm__("mov %%fs,%%ax":"=a" (__res):); 37 __res;}) 38 39 int do_exit(long code); 40 41 void page_exception(void); 42 43 void divide_error(void); 44 void debug(void); 45 void nmi(void); 46 void int3(void); 47 void overflow(void); 48 void bounds(void); 49 void invalid_op(void); 50 void device_not_available(void); 51 void double_fault(void); 52 void coprocessor_segment_overrun(void); 53 void invalid_TSS(void); 54 void segment_not_present(void); 55 void stack_segment(void); 56 void general_protection(void); 57 void page_fault(void); 58 void coprocessor_error(void); 59 void reserved(void); 60 void parallel_interrupt(void); 61 void irq13(void); 62 63 static void die(char * str,long esp_ptr,long nr) 64 { 65 long * esp = (long *) esp_ptr; 66 int i; 67 68 printk("%s: %04x ",str,nr&0xffff); 69 printk("EIP: %04x:%p EFLAGS: %p ESP: %04x:%p ", 70 esp[1],esp[0],esp[2],esp[4],esp[3]); 71 printk("fs: %04x ",_fs()); 72 printk("base: %p, limit: %p ",get_base(current->ldt[1]),get_limit(0x17)); 73 if (esp[4] == 0x17) { 74 printk("Stack: "); 75 for (i=0;i<4;i++) 76 printk("%p ",get_seg_long(0x17,i+(long *)esp[3])); 77 printk(" "); 78 } 79 str(i); 80 printk("Pid: %d, process nr: %d ",current->pid,0xffff & i); 81 for(i=0;i<10;i++) 82 printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); 83 printk(" "); 84 do_exit(11); /* play segment exception */ 85 } 86 87 void do_double_fault(long esp, long error_code) 88 { 89 die("double fault",esp,error_code); 90 } 91 92 void do_general_protection(long esp, long error_code) 93 { 94 die("general protection",esp,error_code); 95 } 96 97 void do_divide_error(long esp, long error_code) 98 { 99 die("divide error",esp,error_code); 100 } 101 102 void do_int3(long * esp, long error_code, 103 long fs,long es,long ds, 104 long ebp,long esi,long edi, 105 long edx,long ecx,long ebx,long eax) 106 { 107 int tr; 108 109 __asm__("str %%ax":"=a" (tr):"" (0)); 110 printk("eax ebx ecx edx %8x %8x %8x %8x ", 111 eax,ebx,ecx,edx); 112 printk("esi edi ebp esp %8x %8x %8x %8x ", 113 esi,edi,ebp,(long) esp); 114 printk(" ds es fs tr %4x %4x %4x %4x ", 115 ds,es,fs,tr); 116 printk("EIP: %8x CS: %4x EFLAGS: %8x ",esp[0],esp[1],esp[2]); 117 } 118 119 void do_nmi(long esp, long error_code) 120 { 121 die("nmi",esp,error_code); 122 } 123 124 void do_debug(long esp, long error_code) 125 { 126 die("debug",esp,error_code); 127 } 128 129 void do_overflow(long esp, long error_code) 130 { 131 die("overflow",esp,error_code); 132 } 133 134 void do_bounds(long esp, long error_code) 135 { 136 die("bounds",esp,error_code); 137 } 138 139 void do_invalid_op(long esp, long error_code) 140 { 141 die("invalid operand",esp,error_code); 142 } 143 144 void do_device_not_available(long esp, long error_code) 145 { 146 die("device not available",esp,error_code); 147 } 148 149 void do_coprocessor_segment_overrun(long esp, long error_code) 150 { 151 die("coprocessor segment overrun",esp,error_code); 152 } 153 154 void do_invalid_TSS(long esp,long error_code) 155 { 156 die("invalid TSS",esp,error_code); 157 } 158 159 void do_segment_not_present(long esp,long error_code) 160 { 161 die("segment not present",esp,error_code); 162 } 163 164 void do_stack_segment(long esp,long error_code) 165 { 166 die("stack segment",esp,error_code); 167 } 168 169 void do_coprocessor_error(long esp, long error_code) 170 { 171 if (last_task_used_math != current) 172 return; 173 die("coprocessor error",esp,error_code); 174 } 175 176 void do_reserved(long esp, long error_code) 177 { 178 die("reserved (15,17-47) error",esp,error_code); 179 } 180 181 void trap_init(void) 182 { 183 int i; 184 185 set_trap_gate(0,÷_error); 186 set_trap_gate(1,&debug); 187 set_trap_gate(2,&nmi); 188 set_system_gate(3,&int3); /* int3-5 can be called from all */ 189 set_system_gate(4,&overflow); 190 set_system_gate(5,&bounds); 191 set_trap_gate(6,&invalid_op); 192 set_trap_gate(7,&device_not_available); 193 set_trap_gate(8,&double_fault); 194 set_trap_gate(9,&coprocessor_segment_overrun); 195 set_trap_gate(10,&invalid_TSS); 196 set_trap_gate(11,&segment_not_present); 197 set_trap_gate(12,&stack_segment); 198 set_trap_gate(13,&general_protection); 199 set_trap_gate(14,&page_fault); 200 set_trap_gate(15,&reserved); 201 set_trap_gate(16,&coprocessor_error); 202 for (i=17;i<48;i++) 203 set_trap_gate(i,&reserved); 204 set_trap_gate(45,&irq13); 205 outb_p(inb_p(0x21)&0xfb,0x21); 206 outb(inb_p(0xA1)&0xdf,0xA1); 207 set_trap_gate(39,¶llel_interrupt); 208 } 209