1 /* $NetBSD: trap.c,v 1.27 1997/07/06 22:38:23 ragge Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Ludd, University of Lule}, Sweden. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed at Ludd, University of Lule}. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* All bugs are subject to removal without further notice */ 34 35 36 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include <sys/proc.h> 40 #include <sys/user.h> 41 #include <sys/syscall.h> 42 #include <sys/systm.h> 43 #include <sys/signalvar.h> 44 #include <sys/exec.h> 45 46 #include <vm/vm.h> 47 #include <vm/vm_kern.h> 48 #include <vm/vm_page.h> 49 50 #include <machine/mtpr.h> 51 #include <machine/pte.h> 52 #include <machine/pcb.h> 53 #include <machine/trap.h> 54 #include <machine/pmap.h> 55 56 #ifdef DDB 57 #include <machine/db_machdep.h> 58 #endif 59 #include <kern/syscalls.c> 60 #ifdef KTRACE 61 #include <sys/ktrace.h> 62 #endif 63 64 extern int want_resched,whichqs; 65 #ifdef TRAPDEBUG 66 volatile int startsysc=0,faultdebug=0; 67 #endif 68 69 static void userret __P((struct proc *, u_int, u_int)); 70 void arithflt __P((struct trapframe *)); 71 void syscall __P((struct trapframe *)); 72 void showregs __P((struct trapframe *)); 73 void showstate __P((struct proc *)); 74 void stray __P((int, int)); 75 void printstack __P((u_int *, u_int *)); 76 77 void 78 userret(p, pc, psl) 79 struct proc *p; 80 u_int pc, psl; 81 { 82 int s,sig; 83 84 while ((sig = CURSIG(p)) !=0) 85 postsig(sig); 86 p->p_priority = p->p_usrpri; 87 if (want_resched) { 88 /* 89 * Since we are curproc, clock will normally just change 90 * our priority without moving us from one queue to another 91 * (since the running process is not on a queue.) 92 * If that happened after we setrunqueue ourselves but before 93 * we swtch()'ed, we might not be on the queue indicated by 94 * our priority. 95 */ 96 s=splstatclock(); 97 setrunqueue(curproc); 98 mi_switch(); 99 splx(s); 100 while ((sig = CURSIG(curproc)) != 0) 101 postsig(sig); 102 } 103 104 curpriority = curproc->p_priority; 105 } 106 107 char *traptypes[]={ 108 "reserved addressing", 109 "privileged instruction", 110 "reserved operand", 111 "breakpoint instruction", 112 "Nothing", 113 "system call ", 114 "arithmetic trap", 115 "asynchronous system trap", 116 "page table length fault", 117 "translation violation fault", 118 "trace trap", 119 "compatibility mode fault", 120 "access violation fault", 121 "", 122 "", 123 "KSP invalid", 124 "", 125 "kernel debugger trap" 126 }; 127 int no_traps = 18; 128 129 void 130 arithflt(frame) 131 struct trapframe *frame; 132 { 133 u_int sig, type=frame->trap,trapsig=1,s; 134 u_int rv, addr; 135 struct proc *p=curproc; 136 struct pmap *pm; 137 vm_map_t map; 138 vm_prot_t ftype; 139 extern vm_map_t pte_map; 140 141 if((frame->psl & PSL_U) == PSL_U) { 142 type|=T_USER; 143 p->p_addr->u_pcb.framep = frame; 144 } 145 146 type&=~(T_WRITE|T_PTEFETCH); 147 148 149 #ifdef TRAPDEBUG 150 if(frame->trap==7) goto fram; 151 if(faultdebug)printf("Trap: type %x, code %x, pc %x, psl %x\n", 152 frame->trap, frame->code, frame->pc, frame->psl); 153 fram: 154 #endif 155 switch(type){ 156 157 default: 158 faulter: 159 #ifdef DDB 160 kdb_trap(frame); 161 #endif 162 printf("Trap: type %x, code %x, pc %x, psl %x\n", 163 frame->trap, frame->code, frame->pc, frame->psl); 164 showregs(frame); 165 panic("trap: adr %x",frame->code); 166 case T_KSPNOTVAL: 167 goto faulter; 168 169 case T_TRANSFLT|T_USER: 170 case T_TRANSFLT: /* Translation invalid - may be simul page ref */ 171 if(frame->trap&T_PTEFETCH){ 172 u_int *ptep, *pte, *pte1; 173 174 if(frame->code<0x40000000) 175 ptep=(u_int *)p->p_addr->u_pcb.P0BR; 176 else 177 ptep=(u_int *)p->p_addr->u_pcb.P1BR; 178 pte1=(u_int *)trunc_page(&ptep[(frame->code 179 &0x3fffffff)>>PGSHIFT]); 180 pte=(u_int*)&Sysmap[((u_int)pte1&0x3fffffff)>>PGSHIFT]; 181 if(*pte&PG_SREF){ /* Yes, simulated */ 182 s=splhigh(); 183 184 *pte|=PG_REF|PG_V;*pte&=~PG_SREF;pte++; 185 *pte|=PG_REF|PG_V;*pte&=~PG_SREF; 186 mtpr(0,PR_TBIA); 187 splx(s); 188 goto uret; 189 } 190 } else { 191 u_int *ptep, *pte; 192 193 frame->code = trunc_page(frame->code); 194 if ((u_int)frame->code < (u_int)0x40000000) { 195 ptep = (u_int *)p->p_addr->u_pcb.P0BR; 196 pte = &ptep[(frame->code >> PGSHIFT)]; 197 } else if ((u_int)frame->code > (u_int)0x7fffffff) { 198 pte = (u_int *)&Sysmap[((u_int)frame->code & 199 0x3fffffff) >> PGSHIFT]; 200 } else { 201 ptep = (u_int *)p->p_addr->u_pcb.P1BR; 202 pte = &ptep[(frame->code&0x3fffffff)>>PGSHIFT]; 203 } 204 if (*pte & PG_SREF) { 205 s = splhigh(); 206 *pte|=PG_REF|PG_V;*pte&=~PG_SREF;pte++; 207 *pte|=PG_REF|PG_V;*pte&=~PG_SREF; 208 /* mtpr(frame->code,PR_TBIS); */ 209 /* mtpr(frame->code+NBPG,PR_TBIS); */ 210 mtpr(0,PR_TBIA); 211 splx(s); 212 goto uret; 213 } 214 } 215 /* Fall into... */ 216 case T_ACCFLT: 217 case T_ACCFLT|T_USER: 218 #ifdef TRAPDEBUG 219 if(faultdebug)printf("trap accflt type %x, code %x, pc %x, psl %x\n", 220 frame->trap, frame->code, frame->pc, frame->psl); 221 #endif 222 if (!p) 223 panic("trap: access fault without process"); 224 pm = p->p_vmspace->vm_map.pmap; 225 if(frame->trap&T_PTEFETCH){ 226 u_int faultaddr,testaddr=(u_int)frame->code&0x3fffffff; 227 int P0 = 0, P1 = 0, SYS = 0; 228 229 if (frame->code == testaddr) 230 P0++; 231 else if ((u_int)frame->code > (u_int)0x7fffffff) 232 SYS++; 233 else 234 P1++; 235 236 if (P0) { 237 faultaddr = (u_int)pm->pm_pcb->P0BR + 238 ((testaddr >> PGSHIFT) << 2); 239 } else if (P1) { 240 faultaddr= (u_int)pm->pm_pcb->P1BR + 241 ((testaddr >> PGSHIFT) << 2); 242 } else 243 panic("pageflt: PTE fault in SPT\n"); 244 245 faultaddr &= ~PAGE_MASK; 246 rv = vm_fault(pte_map, faultaddr, 247 VM_PROT_WRITE|VM_PROT_READ, FALSE); 248 if (rv != KERN_SUCCESS) { 249 250 sig = SIGSEGV; 251 goto bad; 252 } else 253 trapsig = 0; 254 } 255 addr=(frame->code& ~PAGE_MASK); 256 if((frame->pc>(unsigned)0x80000000)&& 257 (frame->code>(unsigned)0x80000000)){ 258 map=kernel_map; 259 } else { 260 map= &p->p_vmspace->vm_map; 261 } 262 if(frame->trap&T_WRITE) ftype=VM_PROT_WRITE|VM_PROT_READ; 263 else ftype = VM_PROT_READ; 264 265 rv = vm_fault(map, addr, ftype, FALSE); 266 if (rv != KERN_SUCCESS) { 267 if(frame->pc>(u_int)0x80000000){ 268 if(p->p_addr->u_pcb.iftrap){ 269 frame->pc=(int)p->p_addr->u_pcb.iftrap; 270 return; 271 } 272 printf("Segv in kernel mode: rv %d\n",rv); 273 goto faulter; 274 } 275 sig=SIGSEGV; 276 } else trapsig=0; 277 break; 278 279 case T_PTELEN: 280 case T_PTELEN|T_USER: /* Page table length exceeded */ 281 pm = p->p_vmspace->vm_map.pmap; 282 #ifdef TRAPDEBUG 283 if(faultdebug)printf("trap ptelen type %x, code %x, pc %x, psl %x\n", 284 frame->trap, frame->code, frame->pc, frame->psl); 285 #endif 286 if ((u_int)frame->code < (u_int)0x40000000) { /* P0 */ 287 int i; 288 289 if (p->p_vmspace == 0){ 290 printf("no vmspace in fault\n"); 291 goto faulter; 292 } 293 i = p->p_vmspace->vm_tsize + p->p_vmspace->vm_dsize; 294 if (i > (frame->code >> PAGE_SHIFT)){ 295 pmap_expandp0(pm, i << 1); 296 trapsig = 0; 297 } else { 298 sig = SIGSEGV; 299 } 300 } else if ((u_int)frame->code > (u_int)0x7fffffff){ /* System, segv */ 301 sig = SIGSEGV; 302 } else { /* P1 */ 303 int i; 304 305 i = (u_int)(p->p_vmspace->vm_maxsaddr); 306 if (frame->code < i){ 307 sig = SIGSEGV; 308 } else { 309 pmap_expandp1(pm); 310 trapsig = 0; 311 } 312 } 313 break; 314 315 case T_BPTFLT|T_USER: 316 case T_TRCTRAP|T_USER: 317 sig = SIGTRAP; 318 frame->psl &= ~PSL_T; 319 break; 320 321 case T_PRIVINFLT|T_USER: 322 case T_RESADFLT|T_USER: 323 case T_RESOPFLT|T_USER: 324 sig=SIGILL; 325 break; 326 327 case T_ARITHFLT|T_USER: 328 sig=SIGFPE; 329 break; 330 331 case T_ASTFLT|T_USER: 332 mtpr(AST_NO,PR_ASTLVL); 333 trapsig=0; 334 break; 335 336 #ifdef DDB 337 case T_KDBTRAP: 338 kdb_trap(frame); 339 return; 340 #endif 341 } 342 bad: 343 if (trapsig) 344 trapsignal(curproc, sig, frame->code); 345 uret: 346 userret(curproc, frame->pc, frame->psl); 347 }; 348 349 void 350 showstate(p) 351 struct proc *p; 352 { 353 if(p){ 354 printf("\npid %d, command %s\n",p->p_pid, p->p_comm); 355 printf("text size %x, data size %x, stack size %x\n", 356 p->p_vmspace->vm_tsize, p->p_vmspace->vm_dsize,p->p_vmspace-> 357 vm_ssize); 358 printf("virt text %x, virt data %x, max stack %x\n", 359 (u_int)p->p_vmspace->vm_taddr, (u_int)p->p_vmspace->vm_daddr, 360 (u_int)p->p_vmspace->vm_maxsaddr); 361 printf("kernel uarea %x, end uarea %x\n",(u_int)p->p_addr, 362 (u_int)p->p_addr + USPACE); 363 } else { 364 printf("No process\n"); 365 } 366 printf("kernel stack: %x, interrupt stack %x\n", 367 mfpr(PR_KSP),mfpr(PR_ISP)); 368 printf("P0BR %x, P0LR %x, P1BR %x, P1LR %x\n", 369 mfpr(PR_P0BR),mfpr(PR_P0LR),mfpr(PR_P1BR),mfpr(PR_P1LR)); 370 } 371 372 void 373 setregs(p, pack, stack, retval) 374 struct proc *p; 375 struct exec_package *pack; 376 u_long stack; 377 register_t retval[2]; 378 { 379 struct trapframe *exptr; 380 381 exptr = p->p_addr->u_pcb.framep; 382 exptr->pc = pack->ep_entry + 2; 383 exptr->sp = stack; 384 retval[0] = retval[1] = 0; 385 } 386 387 void 388 syscall(frame) 389 struct trapframe *frame; 390 { 391 struct sysent *callp; 392 int nsys; 393 int err, rval[2], args[8]; 394 struct trapframe *exptr; 395 struct proc *p = curproc; 396 397 #ifdef TRAPDEBUG 398 if(startsysc)printf("trap syscall %s pc %x, psl %x, sp %x, pid %d, frame %x\n", 399 syscallnames[frame->code], frame->pc, frame->psl,frame->sp, 400 curproc->p_pid,frame); 401 #endif 402 403 exptr = p->p_addr->u_pcb.framep = frame; 404 callp = p->p_emul->e_sysent; 405 nsys = p->p_emul->e_nsysent; 406 407 if(frame->code == SYS___syscall){ 408 int g = *(int *)(frame->ap); 409 410 frame->code=*(int *)(frame->ap+4); 411 frame->ap+=8; 412 *(int *)(frame->ap)=g-2; 413 } 414 415 if(frame->code<0||frame->code>=nsys) 416 callp += p->p_emul->e_nosys; 417 else 418 callp += frame->code; 419 420 rval[0]=0; 421 rval[1]=frame->r1; 422 if(callp->sy_narg) { 423 err = copyin((char*)frame->ap+4, args, callp->sy_argsize); 424 if (err) { 425 #ifdef KTRACE 426 if (KTRPOINT(p, KTR_SYSCALL)) 427 ktrsyscall(p->p_tracep, frame->code, 428 callp->sy_argsize, args); 429 #endif 430 goto bad; 431 } 432 } 433 #ifdef KTRACE 434 if (KTRPOINT(p, KTR_SYSCALL)) 435 ktrsyscall(p->p_tracep, frame->code, callp->sy_argsize, args); 436 #endif 437 err=(*callp->sy_call)(curproc,args,rval); 438 exptr = curproc->p_addr->u_pcb.framep; 439 440 #ifdef TRAPDEBUG 441 if(startsysc) 442 printf("retur %s pc %x, psl %x, sp %x, pid %d, v{rde %d r0 %d, r1 %d, frame %x\n", 443 syscallnames[exptr->code], exptr->pc, exptr->psl,exptr->sp, 444 curproc->p_pid,err,rval[0],rval[1],exptr); 445 #endif 446 447 bad: 448 switch (err) { 449 case 0: 450 exptr->r1 = rval[1]; 451 exptr->r0 = rval[0]; 452 exptr->psl &= ~PSL_C; 453 break; 454 455 case EJUSTRETURN: 456 return; 457 458 case ERESTART: 459 exptr->pc = exptr->pc-2; 460 break; 461 462 default: 463 exptr->r0 = err; 464 exptr->psl |= PSL_C; 465 break; 466 } 467 userret(curproc, exptr->pc, exptr->psl); 468 #ifdef KTRACE 469 if (KTRPOINT(p, KTR_SYSRET)) 470 ktrsysret(p->p_tracep, frame->code, err, rval[0]); 471 #endif 472 } 473 474 void 475 stray(scb, vec) 476 int scb, vec; 477 { 478 printf("stray interrupt scb %d, vec 0x%x\n", scb, vec); 479 } 480 481 void 482 printstack(loaddr, highaddr) 483 u_int *loaddr, *highaddr; 484 { 485 u_int *tmp; 486 487 (u_int)tmp = 0xfffffffc & (u_int)loaddr; /* Easy align */ 488 489 for (;tmp < highaddr;tmp += 4) 490 printf("%8x: %8x %8x %8x %8x\n", 491 (int)tmp, *tmp, *(tmp + 1), *(tmp + 2), *(tmp + 3)); 492 } 493 494 void 495 showregs(frame) 496 struct trapframe *frame; 497 { 498 printf("P0BR %8x P1BR %8x P0LR %8x P1LR %8x\n", 499 mfpr(PR_P0BR), mfpr(PR_P1BR), mfpr(PR_P0LR), mfpr(PR_P1LR)); 500 printf("KSP %8x ISP %8x USP %8x\n", 501 mfpr(PR_KSP), mfpr(PR_ISP), mfpr(PR_USP)); 502 printf("R0 %8x R1 %8x R2 %8x R3 %8x\n", 503 frame->r0, frame->r1, frame->r2, frame->r3); 504 printf("R4 %8x R5 %8x R6 %8x R7 %8x\n", 505 frame->r4, frame->r5, frame->r6, frame->r7); 506 printf("R8 %8x R9 %8x R10 %8x R11 %8x\n", 507 frame->r8, frame->r9, frame->r10, frame->r11); 508 printf("FP %8x AP %8x PC %8x PSL %8x\n", 509 frame->fp, frame->ap, frame->pc, frame->psl); 510 } 511