1 /* $NetBSD: trap.c,v 1.24 1996/11/06 20:19:55 cgd 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 cpu_switch(0); 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(frame->code<0x40000000){ 195 ptep=(u_int *)p->p_addr->u_pcb.P0BR; 196 pte=&ptep[(frame->code>>PGSHIFT)]; 197 } else if(frame->code>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_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) P0++; 230 else if(frame->code>0x7fffffff) SYS++; 231 else P1++; 232 233 if(P0){ 234 faultaddr=(u_int)pm->pm_pcb->P0BR+ 235 ((testaddr>>PGSHIFT)<<2); 236 } else if(P1){ 237 faultaddr=(u_int)pm->pm_pcb->P1BR+ 238 ((testaddr>>PGSHIFT)<<2); 239 } else panic("pageflt: PTE fault in SPT\n"); 240 241 faultaddr&=~PAGE_MASK; 242 rv = vm_fault(pte_map, faultaddr, 243 VM_PROT_WRITE|VM_PROT_READ, FALSE); 244 if (rv != KERN_SUCCESS) { 245 246 sig=SIGSEGV; 247 goto bad; 248 } else 249 trapsig=0; 250 } 251 addr=(frame->code& ~PAGE_MASK); 252 if((frame->pc>(unsigned)0x80000000)&& 253 (frame->code>(unsigned)0x80000000)){ 254 map=kernel_map; 255 } else { 256 map= &p->p_vmspace->vm_map; 257 } 258 if(frame->trap&T_WRITE) ftype=VM_PROT_WRITE|VM_PROT_READ; 259 else ftype = VM_PROT_READ; 260 261 rv = vm_fault(map, addr, ftype, FALSE); 262 if (rv != KERN_SUCCESS) { 263 if(frame->pc>(u_int)0x80000000){ 264 if(p->p_addr->u_pcb.iftrap){ 265 frame->pc=(int)p->p_addr->u_pcb.iftrap; 266 return; 267 } 268 printf("Segv in kernel mode: rv %d\n",rv); 269 goto faulter; 270 } 271 sig=SIGSEGV; 272 } else trapsig=0; 273 break; 274 275 case T_PTELEN: 276 case T_PTELEN|T_USER: /* Page table length exceeded */ 277 pm=&p->p_vmspace->vm_pmap; 278 #ifdef TRAPDEBUG 279 if(faultdebug)printf("trap ptelen type %x, code %x, pc %x, psl %x\n", 280 frame->trap, frame->code, frame->pc, frame->psl); 281 #endif 282 if(frame->code<0x40000000){ /* P0 */ 283 int i; 284 285 if (p->p_vmspace == 0){ 286 printf("no vmspace in fault\n"); 287 goto faulter; 288 } 289 i = p->p_vmspace->vm_tsize + p->p_vmspace->vm_dsize; 290 if (i > (frame->code >> PAGE_SHIFT)){ 291 pmap_expandp0(pm, i << 1); 292 trapsig = 0; 293 } else { 294 sig = SIGSEGV; 295 } 296 } else if (frame->code > 0x7fffffff){ /* System, segv */ 297 sig = SIGSEGV; 298 } else { /* P1 */ 299 int i; 300 301 i = (u_int)(p->p_vmspace->vm_maxsaddr); 302 if (frame->code < i){ 303 sig = SIGSEGV; 304 } else { 305 pmap_expandp1(pm); 306 trapsig = 0; 307 } 308 } 309 break; 310 311 case T_BPTFLT|T_USER: 312 case T_TRCTRAP|T_USER: 313 sig = SIGTRAP; 314 frame->psl &= ~PSL_T; 315 break; 316 317 case T_PRIVINFLT|T_USER: 318 case T_RESADFLT|T_USER: 319 case T_RESOPFLT|T_USER: 320 sig=SIGILL; 321 break; 322 323 case T_ARITHFLT|T_USER: 324 sig=SIGFPE; 325 break; 326 327 case T_ASTFLT|T_USER: 328 mtpr(AST_NO,PR_ASTLVL); 329 trapsig=0; 330 break; 331 332 #ifdef DDB 333 case T_KDBTRAP: 334 kdb_trap(frame); 335 return; 336 #endif 337 } 338 bad: 339 if (trapsig) 340 trapsignal(curproc, sig, frame->code); 341 uret: 342 userret(curproc, frame->pc, frame->psl); 343 }; 344 345 void 346 showstate(p) 347 struct proc *p; 348 { 349 if(p){ 350 printf("\npid %d, command %s\n",p->p_pid, p->p_comm); 351 printf("text size %x, data size %x, stack size %x\n", 352 p->p_vmspace->vm_tsize, p->p_vmspace->vm_dsize,p->p_vmspace-> 353 vm_ssize); 354 printf("virt text %x, virt data %x, max stack %x\n", 355 (u_int)p->p_vmspace->vm_taddr, (u_int)p->p_vmspace->vm_daddr, 356 (u_int)p->p_vmspace->vm_maxsaddr); 357 printf("kernel uarea %x, end uarea %x\n",(u_int)p->p_addr, 358 (u_int)p->p_addr + USPACE); 359 } else { 360 printf("No process\n"); 361 } 362 printf("kernel stack: %x, interrupt stack %x\n", 363 mfpr(PR_KSP),mfpr(PR_ISP)); 364 printf("P0BR %x, P0LR %x, P1BR %x, P1LR %x\n", 365 mfpr(PR_P0BR),mfpr(PR_P0LR),mfpr(PR_P1BR),mfpr(PR_P1LR)); 366 } 367 368 void 369 setregs(p, pack, stack, retval) 370 struct proc *p; 371 struct exec_package *pack; 372 u_long stack; 373 register_t retval[2]; 374 { 375 struct trapframe *exptr; 376 377 exptr = p->p_addr->u_pcb.framep; 378 exptr->pc = pack->ep_entry + 2; 379 exptr->sp = stack; 380 retval[0] = retval[1] = 0; 381 } 382 383 void 384 syscall(frame) 385 struct trapframe *frame; 386 { 387 struct sysent *callp; 388 int nsys; 389 int err, rval[2], args[8]; 390 struct trapframe *exptr; 391 struct proc *p = curproc; 392 393 #ifdef TRAPDEBUG 394 if(startsysc)printf("trap syscall %s pc %x, psl %x, sp %x, pid %d, frame %x\n", 395 syscallnames[frame->code], frame->pc, frame->psl,frame->sp, 396 curproc->p_pid,frame); 397 #endif 398 399 exptr = p->p_addr->u_pcb.framep = frame; 400 callp = p->p_emul->e_sysent; 401 nsys = p->p_emul->e_nsysent; 402 403 if(frame->code == SYS___syscall){ 404 int g = *(int *)(frame->ap); 405 406 frame->code=*(int *)(frame->ap+4); 407 frame->ap+=8; 408 *(int *)(frame->ap)=g-2; 409 } 410 411 if(frame->code<0||frame->code>=nsys) 412 callp += p->p_emul->e_nosys; 413 else 414 callp += frame->code; 415 416 rval[0]=0; 417 rval[1]=frame->r1; 418 if(callp->sy_narg) { 419 err = copyin((char*)frame->ap+4, args, callp->sy_argsize); 420 if (err) { 421 #ifdef KTRACE 422 if (KTRPOINT(p, KTR_SYSCALL)) 423 ktrsyscall(p->p_tracep, frame->code, 424 callp->sy_argsize, args); 425 #endif 426 goto bad; 427 } 428 } 429 #ifdef KTRACE 430 if (KTRPOINT(p, KTR_SYSCALL)) 431 ktrsyscall(p->p_tracep, frame->code, callp->sy_argsize, args); 432 #endif 433 err=(*callp->sy_call)(curproc,args,rval); 434 exptr = curproc->p_addr->u_pcb.framep; 435 436 #ifdef TRAPDEBUG 437 if(startsysc) 438 printf("retur %s pc %x, psl %x, sp %x, pid %d, v{rde %d r0 %d, r1 %d, frame %x\n", 439 syscallnames[exptr->code], exptr->pc, exptr->psl,exptr->sp, 440 curproc->p_pid,err,rval[0],rval[1],exptr); 441 #endif 442 443 bad: 444 switch (err) { 445 case 0: 446 exptr->r1 = rval[1]; 447 exptr->r0 = rval[0]; 448 exptr->psl &= ~PSL_C; 449 break; 450 451 case EJUSTRETURN: 452 return; 453 454 case ERESTART: 455 exptr->pc = exptr->pc-2; 456 break; 457 458 default: 459 exptr->r0 = err; 460 exptr->psl |= PSL_C; 461 break; 462 } 463 userret(curproc, exptr->pc, exptr->psl); 464 #ifdef KTRACE 465 if (KTRPOINT(p, KTR_SYSRET)) 466 ktrsysret(p->p_tracep, frame->code, err, rval[0]); 467 #endif 468 } 469 470 void 471 stray(scb, vec) 472 int scb, vec; 473 { 474 printf("stray interrupt scb %d, vec 0x%x\n", scb, vec); 475 } 476 477 void 478 printstack(loaddr, highaddr) 479 u_int *loaddr, *highaddr; 480 { 481 u_int *tmp; 482 483 (u_int)tmp = 0xfffffffc & (u_int)loaddr; /* Easy align */ 484 485 for (;tmp < highaddr;tmp += 4) 486 printf("%8x: %8x %8x %8x %8x\n", 487 (int)tmp, *tmp, *(tmp + 1), *(tmp + 2), *(tmp + 3)); 488 } 489 490 void 491 showregs(frame) 492 struct trapframe *frame; 493 { 494 printf("P0BR %8x P1BR %8x P0LR %8x P1LR %8x\n", 495 mfpr(PR_P0BR), mfpr(PR_P1BR), mfpr(PR_P0LR), mfpr(PR_P1LR)); 496 printf("KSP %8x ISP %8x USP %8x\n", 497 mfpr(PR_KSP), mfpr(PR_ISP), mfpr(PR_USP)); 498 printf("R0 %8x R1 %8x R2 %8x R3 %8x\n", 499 frame->r0, frame->r1, frame->r2, frame->r3); 500 printf("R4 %8x R5 %8x R6 %8x R7 %8x\n", 501 frame->r4, frame->r5, frame->r6, frame->r7); 502 printf("R8 %8x R9 %8x R10 %8x R11 %8x\n", 503 frame->r8, frame->r9, frame->r10, frame->r11); 504 printf("FP %8x AP %8x PC %8x PSL %8x\n", 505 frame->fp, frame->ap, frame->pc, frame->psl); 506 } 507