00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 00025 00026 00027 00028 00029 00030 #include <types.h> 00031 #include <signal.h> 00032 #include <lib.h> 00033 #include <mips/specialreg.h> 00034 #include <mips/trapframe.h> 00035 #include <cpu.h> 00036 #include <spl.h> 00037 #include <thread.h> 00038 #include <current.h> 00039 #include <vm.h> 00040 #include <mainbus.h> 00041 #include <syscall.h> 00042 00043 00044 00045 extern void asm_usermode( struct trapframe *tf); 00046 00047 00048 void mips_trap( struct trapframe *tf); 00049 00050 00051 00052 #define NTRAPCODES 13 00053 static const char * const trapcodenames[NTRAPCODES] = { 00054 "Interrupt" , 00055 "TLB modify trap" , 00056 "TLB miss on load" , 00057 "TLB miss on store" , 00058 "Address error on load" , 00059 "Address error on store" , 00060 "Bus error on code" , 00061 "Bus error on data" , 00062 "System call" , 00063 "Break instruction" , 00064 "Illegal instruction" , 00065 "Coprocessor unusable" , 00066 "Arithmetic overflow" , 00067 }; 00068 00069 00070 00071 00072 static 00073 void 00074 kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr) 00075 { 00076 int sig = 0; 00077 00078 KASSERT(code < NTRAPCODES); 00079 switch (code) { 00080 case EX_IRQ: 00081 case EX_IBE: 00082 case EX_DBE: 00083 case EX_SYS: 00084 00085 KASSERT(0); 00086 sig = SIGABRT; 00087 break ; 00088 case EX_MOD: 00089 case EX_TLBL: 00090 case EX_TLBS: 00091 sig = SIGSEGV; 00092 break ; 00093 case EX_ADEL: 00094 case EX_ADES: 00095 sig = SIGBUS; 00096 break ; 00097 case EX_BP: 00098 sig = SIGTRAP; 00099 break ; 00100 case EX_RI: 00101 sig = SIGILL; 00102 break ; 00103 case EX_CPU: 00104 sig = SIGSEGV; 00105 break ; 00106 case EX_OVF: 00107 sig = SIGFPE; 00108 break ; 00109 } 00110 00111 00112 00113 00114 00115 kprintf( "Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)

" , 00116 code, sig, trapcodenames[code], epc, vaddr); 00117 panic( "I don't know how to handle this

" ); 00118 } 00119 00120 00121 00122 00123 00124 00125 void 00126 mips_trap( struct trapframe *tf) 00127 { 00128 uint32_t code; 00129 bool isutlb, iskern; 00130 int spl; 00131 00132 00133 KASSERT( sizeof ( struct trapframe)==(37*4)); 00134 00135 00136 00137 00138 code = (tf->tf_cause & CCA_CODE) >> CCA_CODESHIFT; 00139 isutlb = (tf->tf_cause & CCA_UTLB) != 0; 00140 iskern = (tf->tf_status & CST_KUp) == 0; 00141 00142 KASSERT(code < NTRAPCODES); 00143 00144 00145 if (curthread != NULL && curthread->t_stack != NULL) { 00146 KASSERT((vaddr_t)tf > (vaddr_t)curthread->t_stack); 00147 KASSERT((vaddr_t)tf < (vaddr_t)(curthread->t_stack 00148 + STACK_SIZE)); 00149 } 00150 00151 00152 if (code == EX_IRQ) { 00153 int old_in; 00154 bool doadjust; 00155 00156 old_in = curthread->t_in_interrupt; 00157 curthread->t_in_interrupt = 1; 00158 00159 00160 00161 00162 00163 00164 00165 00166 00167 00168 00169 00170 00171 00172 00173 00174 00175 00176 if (curthread->t_curspl == 0) { 00177 KASSERT(curthread->t_curspl == 0); 00178 KASSERT(curthread->t_iplhigh_count == 0); 00179 curthread->t_curspl = IPL_HIGH; 00180 curthread->t_iplhigh_count++; 00181 doadjust = true ; 00182 } 00183 else { 00184 doadjust = false ; 00185 } 00186 00187 mainbus_interrupt(tf); 00188 00189 if (doadjust) { 00190 KASSERT(curthread->t_curspl == IPL_HIGH); 00191 KASSERT(curthread->t_iplhigh_count == 1); 00192 curthread->t_iplhigh_count--; 00193 curthread->t_curspl = 0; 00194 } 00195 00196 curthread->t_in_interrupt = old_in; 00197 goto done2; 00198 } 00199 00200 00201 00202 00203 00204 00205 00206 00207 00208 00209 00210 00211 spl = splhigh(); 00212 splx(spl); 00213 00214 00215 if (code == EX_SYS) { 00216 00217 KASSERT(curthread->t_curspl == 0); 00218 KASSERT(curthread->t_iplhigh_count == 0); 00219 00220 DEBUG(DB_SYSCALL, "syscall: #%d, args %x %x %x %x

" , 00221 tf->tf_v0, tf->tf_a0, tf->tf_a1, tf->tf_a2, tf->tf_a3); 00222 00223 syscall(tf); 00224 goto done; 00225 } 00226 00227 00228 00229 00230 00231 00232 switch (code) { 00233 case EX_MOD: 00234 if (vm_fault(VM_FAULT_READONLY, tf->tf_vaddr)==0) { 00235 goto done; 00236 } 00237 break ; 00238 case EX_TLBL: 00239 if (vm_fault(VM_FAULT_READ, tf->tf_vaddr)==0) { 00240 goto done; 00241 } 00242 break ; 00243 case EX_TLBS: 00244 if (vm_fault(VM_FAULT_WRITE, tf->tf_vaddr)==0) { 00245 goto done; 00246 } 00247 break ; 00248 case EX_IBE: 00249 case EX_DBE: 00250 00251 00252 00253 00254 00255 00256 00257 00258 00259 panic( "Bus error exception, PC=0x%x

" , tf->tf_epc); 00260 break ; 00261 } 00262 00263 00264 00265 00266 00267 00268 00269 if (!iskern) { 00270 00271 00272 00273 00274 kill_curthread(tf->tf_epc, code, tf->tf_vaddr); 00275 goto done; 00276 } 00277 00278 00279 00280 00281 00282 00283 00284 00285 00286 00287 00288 00289 00290 00291 00292 00293 00294 00295 00296 00297 00298 00299 if (curthread != NULL && 00300 curthread->t_machdep.tm_badfaultfunc != NULL) { 00301 tf->tf_epc = (vaddr_t) curthread->t_machdep.tm_badfaultfunc; 00302 goto done; 00303 } 00304 00305 00306 00307 00308 00309 kprintf( "panic: Fatal exception %u (%s) in kernel mode

" , code, 00310 trapcodenames[code]); 00311 kprintf( "panic: EPC 0x%x, exception vaddr 0x%x

" , 00312 tf->tf_epc, tf->tf_vaddr); 00313 00314 panic( "I can't handle this... I think I'll just die now...

" ); 00315 00316 done: 00317 00318 00319 00320 00321 cpu_irqoff(); 00322 done2: 00323 00324 00325 00326 00327 00328 00329 00330 if (curthread->t_stack == NULL) { 00331 return ; 00332 } 00333 00334 cputhreads[curcpu->c_number] = (vaddr_t)curthread; 00335 cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE; 00336 00337 00338 00339 00340 00341 00342 00343 00344 00345 00346 KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf)); 00347 } 00348 00349 00350 00351 00352 00353 00354 00355 00356 00357 00358 00359 00360 00361 00362 00363 00364 00365 00366 void 00367 mips_usermode( struct trapframe *tf) 00368 { 00369 00370 00371 00372 00373 00374 00375 00376 spl0(); 00377 cpu_irqoff(); 00378 00379 cputhreads[curcpu->c_number] = (vaddr_t)curthread; 00380 cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE; 00381 00382 00383 00384 00385 00386 00387 00388 00389 00390 00391 00392 00393 00394 00395 00396 00397 KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf)); 00398 00399 00400 00401 00402 asm_usermode(tf); 00403 } 00404 00405 00406 00407 00408 00409 00410 00411 00412 00413 00414 00415 00416 00417 void 00418 enter_new_process( int argc, userptr_t argv, vaddr_t stack, vaddr_t entry) 00419 { 00420 struct trapframe tf; 00421 00422 bzero(&tf, sizeof (tf)); 00423 00424 tf.tf_status = CST_IRQMASK | CST_IEp | CST_KUp; 00425 tf.tf_epc = entry; 00426 tf.tf_a0 = argc; 00427 tf.tf_a1 = (vaddr_t)argv; 00428 tf.tf_sp = stack; 00429 00430 mips_usermode(&tf); 00431 }