1 /* $NetBSD: trap.c,v 1.93 2004/03/14 01:08:49 cl 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 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.93 2004/03/14 01:08:49 cl Exp $"); 37 38 #include "opt_ddb.h" 39 #include "opt_ktrace.h" 40 #include "opt_systrace.h" 41 #include "opt_multiprocessor.h" 42 43 #include <sys/types.h> 44 #include <sys/param.h> 45 #include <sys/proc.h> 46 #include <sys/user.h> 47 #include <sys/syscall.h> 48 #include <sys/systm.h> 49 #include <sys/signalvar.h> 50 #include <sys/exec.h> 51 #include <sys/sa.h> 52 #include <sys/savar.h> 53 #include <sys/pool.h> 54 55 #include <uvm/uvm_extern.h> 56 57 #include <machine/mtpr.h> 58 #include <machine/pte.h> 59 #include <machine/pcb.h> 60 #include <machine/trap.h> 61 #include <machine/pmap.h> 62 #include <machine/cpu.h> 63 64 #ifdef DDB 65 #include <machine/db_machdep.h> 66 #endif 67 #include <kern/syscalls.c> 68 #ifdef KTRACE 69 #include <sys/ktrace.h> 70 #endif 71 #ifdef SYSTRACE 72 #include <sys/systrace.h> 73 #endif 74 75 #ifdef TRAPDEBUG 76 volatile int startsysc = 0, faultdebug = 0; 77 #endif 78 79 int cpu_printfataltraps = 0; 80 81 static __inline void userret (struct lwp *, struct trapframe *, u_quad_t); 82 83 void trap (struct trapframe *); 84 void syscall (struct trapframe *); 85 86 const char * const traptypes[]={ 87 "reserved addressing", 88 "privileged instruction", 89 "reserved operand", 90 "breakpoint instruction", 91 "XFC instruction", 92 "system call ", 93 "arithmetic trap", 94 "asynchronous system trap", 95 "page table length fault", 96 "translation violation fault", 97 "trace trap", 98 "compatibility mode fault", 99 "access violation fault", 100 "", 101 "", 102 "KSP invalid", 103 "", 104 "kernel debugger trap" 105 }; 106 int no_traps = 18; 107 108 #define USERMODE(framep) ((((framep)->psl) & (PSL_U)) == PSL_U) 109 #define FAULTCHK \ 110 if (l->l_addr->u_pcb.iftrap) { \ 111 frame->pc = (unsigned)l->l_addr->u_pcb.iftrap; \ 112 frame->psl &= ~PSL_FPD; \ 113 frame->r0 = EFAULT;/* for copyin/out */ \ 114 frame->r1 = -1; /* for fetch/store */ \ 115 return; \ 116 } 117 118 /* 119 * userret: 120 * 121 * Common code used by various execption handlers to 122 * return to usermode. 123 */ 124 static __inline void 125 userret(struct lwp *l, struct trapframe *frame, u_quad_t oticks) 126 { 127 int sig; 128 struct proc *p = l->l_proc; 129 130 /* Generate UNBLOCKED upcall. */ 131 if (l->l_flag & L_SA_BLOCKING) 132 sa_unblock_userret(l); 133 134 /* Take pending signals. */ 135 while ((sig = CURSIG(l)) != 0) 136 postsig(sig); 137 l->l_priority = l->l_usrpri; 138 if (curcpu()->ci_want_resched) { 139 /* 140 * We are being preempted. 141 */ 142 preempt(0); 143 while ((sig = CURSIG(l)) != 0) 144 postsig(sig); 145 } 146 147 /* Invoke per-process kernel-exit handling, if any */ 148 if (p->p_userret) 149 (p->p_userret)(l, p->p_userret_arg); 150 151 /* 152 * If profiling, charge system time to the trapped pc. 153 */ 154 if (p->p_flag & P_PROFIL) { 155 extern int psratio; 156 157 addupc_task(p, frame->pc, 158 (int)(p->p_sticks - oticks) * psratio); 159 } 160 /* Invoke any pending upcalls. */ 161 if (l->l_flag & L_SA_UPCALL) 162 sa_upcall_userret(l); 163 164 curcpu()->ci_schedstate.spc_curpriority = l->l_priority; 165 } 166 167 void 168 trap(struct trapframe *frame) 169 { 170 u_int sig = 0, type = frame->trap, trapsig = 1, code = 0; 171 u_int rv, addr, umode; 172 struct lwp *l; 173 struct proc *p = NULL; 174 u_quad_t oticks = 0; 175 struct vmspace *vm; 176 struct vm_map *map; 177 vm_prot_t ftype; 178 vsize_t nss; 179 180 if ((l = curlwp) != NULL) 181 p = l->l_proc; 182 uvmexp.traps++; 183 if ((umode = USERMODE(frame))) { 184 type |= T_USER; 185 oticks = p->p_sticks; 186 l->l_addr->u_pcb.framep = frame; 187 } 188 189 type&=~(T_WRITE|T_PTEFETCH); 190 191 192 #ifdef TRAPDEBUG 193 if(frame->trap==7) goto fram; 194 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", 195 frame->trap, frame->code, frame->pc, frame->psl); 196 fram: 197 #endif 198 switch(type){ 199 200 default: 201 #ifdef DDB 202 kdb_trap(frame); 203 #endif 204 printf("Trap: type %x, code %x, pc %x, psl %x\n", 205 (u_int)frame->trap, (u_int)frame->code, 206 (u_int)frame->pc, (u_int)frame->psl); 207 panic("trap"); 208 209 case T_KSPNOTVAL: 210 panic("kernel stack invalid"); 211 212 case T_TRANSFLT|T_USER: 213 case T_TRANSFLT: 214 /* 215 * BUG! BUG! BUG! BUG! BUG! 216 * Due to a hardware bug (at in least KA65x CPUs) a double 217 * page table fetch trap will cause a translation fault 218 * even if access in the SPT PTE entry specifies 'no access'. 219 * In for example section 6.4.2 in VAX Architecture 220 * Reference Manual it states that if a page both are invalid 221 * and have no access set, a 'access violation fault' occurs. 222 * Therefore, we must fall through here... 223 */ 224 #ifdef nohwbug 225 panic("translation fault"); 226 #endif 227 228 case T_PTELEN|T_USER: /* Page table length exceeded */ 229 case T_ACCFLT|T_USER: 230 if (frame->code < 0) { /* Check for kernel space */ 231 sig = SIGSEGV; 232 code = SEGV_ACCERR; 233 break; 234 } 235 236 case T_PTELEN: 237 case T_ACCFLT: 238 #ifdef TRAPDEBUG 239 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 240 frame->trap, frame->code, frame->pc, frame->psl); 241 #endif 242 #ifdef DIAGNOSTIC 243 if (p == 0) 244 panic("trap: access fault: addr %lx code %lx", 245 frame->pc, frame->code); 246 if (frame->psl & PSL_IS) 247 panic("trap: pflt on IS"); 248 #endif 249 250 /* 251 * Page tables are allocated in pmap_enter(). We get 252 * info from below if it is a page table fault, but 253 * UVM may want to map in pages without faults, so 254 * because we must check for PTE pages anyway we don't 255 * bother doing it here. 256 */ 257 addr = trunc_page(frame->code); 258 if ((umode == 0) && (frame->code < 0)) { 259 vm = NULL; 260 map = kernel_map; 261 } else { 262 vm = p->p_vmspace; 263 map = &vm->vm_map; 264 } 265 266 if (frame->trap & T_WRITE) 267 ftype = VM_PROT_WRITE; 268 else 269 ftype = VM_PROT_READ; 270 271 if (umode) { 272 KERNEL_PROC_LOCK(l); 273 if (l->l_flag & L_SA) { 274 l->l_savp->savp_faultaddr = (vaddr_t)frame->code; 275 l->l_flag |= L_SA_PAGEFAULT; 276 } 277 } else 278 KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE); 279 280 nss = 0; 281 if (map != kernel_map && 282 (caddr_t)addr >= vm->vm_maxsaddr && 283 (caddr_t)addr < (caddr_t)USRSTACK) { 284 nss = btoc(USRSTACK - addr); 285 if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) { 286 /* 287 * Set nss to 0, since this case is not 288 * a "stack extension". 289 */ 290 nss = 0; 291 } 292 } 293 294 rv = uvm_fault(map, addr, 0, ftype); 295 if (rv != 0) { 296 if (umode == 0) { 297 KERNEL_UNLOCK(); 298 FAULTCHK; 299 panic("Segv in kernel mode: pc %x addr %x", 300 (u_int)frame->pc, (u_int)frame->code); 301 } 302 code = SEGV_ACCERR; 303 if (rv == ENOMEM) { 304 printf("UVM: pid %d (%s), uid %d killed: " 305 "out of swap\n", 306 p->p_pid, p->p_comm, 307 p->p_cred && p->p_ucred ? 308 p->p_ucred->cr_uid : -1); 309 sig = SIGKILL; 310 } else { 311 sig = SIGSEGV; 312 if (rv != EACCES) 313 code = SEGV_MAPERR; 314 } 315 } else { 316 trapsig = 0; 317 if (nss != 0 && nss > vm->vm_ssize) 318 vm->vm_ssize = nss; 319 } 320 if (umode) { 321 l->l_flag &= ~L_SA_PAGEFAULT; 322 KERNEL_PROC_UNLOCK(l); 323 } else 324 KERNEL_UNLOCK(); 325 break; 326 327 case T_BPTFLT|T_USER: 328 sig = SIGTRAP; 329 code = TRAP_BRKPT; 330 break; 331 case T_TRCTRAP|T_USER: 332 sig = SIGTRAP; 333 code = TRAP_TRACE; 334 frame->psl &= ~PSL_T; 335 break; 336 337 case T_PRIVINFLT|T_USER: 338 sig = SIGILL; 339 code = ILL_PRVOPC; 340 break; 341 case T_RESADFLT|T_USER: 342 sig = SIGILL; 343 code = ILL_ILLADR; 344 break; 345 case T_RESOPFLT|T_USER: 346 sig = SIGILL; 347 code = ILL_ILLOPC; 348 break; 349 350 case T_XFCFLT|T_USER: 351 sig = SIGEMT; 352 break; 353 354 case T_ARITHFLT|T_USER: 355 sig = SIGFPE; 356 break; 357 358 case T_ASTFLT|T_USER: 359 mtpr(AST_NO,PR_ASTLVL); 360 trapsig = 0; 361 break; 362 363 #ifdef DDB 364 case T_BPTFLT: /* Kernel breakpoint */ 365 case T_KDBTRAP: 366 case T_KDBTRAP|T_USER: 367 case T_TRCTRAP: 368 kdb_trap(frame); 369 return; 370 #endif 371 } 372 if (trapsig) { 373 ksiginfo_t ksi; 374 if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps) 375 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", 376 p->p_pid, l->l_lid, p->p_comm, sig, frame->trap, 377 frame->code, frame->pc, frame->psl); 378 KERNEL_PROC_LOCK(l); 379 KSI_INIT_TRAP(&ksi); 380 ksi.ksi_signo = sig; 381 ksi.ksi_trap = frame->trap; 382 ksi.ksi_addr = (void *)frame->code; 383 ksi.ksi_code = code; 384 trapsignal(l, &ksi); 385 KERNEL_PROC_UNLOCK(l); 386 } 387 388 if (umode == 0) 389 return; 390 391 userret(l, frame, oticks); 392 } 393 394 void 395 setregs(struct lwp *l, struct exec_package *pack, u_long stack) 396 { 397 struct trapframe *exptr; 398 399 exptr = l->l_addr->u_pcb.framep; 400 exptr->pc = pack->ep_entry + 2; 401 exptr->sp = stack; 402 exptr->r6 = stack; /* for ELF */ 403 exptr->r7 = 0; /* for ELF */ 404 exptr->r8 = 0; /* for ELF */ 405 exptr->r9 = (u_long) l->l_proc->p_psstr; /* for ELF */ 406 } 407 408 void 409 syscall(struct trapframe *frame) 410 { 411 const struct sysent *callp; 412 u_quad_t oticks; 413 int nsys; 414 int err, rval[2], args[8]; 415 struct trapframe *exptr; 416 struct lwp *l = curlwp; 417 struct proc *p = l->l_proc; 418 419 #ifdef TRAPDEBUG 420 if(startsysc)printf("trap syscall %s pc %lx, psl %lx, sp %lx, pid %d, frame %p\n", 421 syscallnames[frame->code], frame->pc, frame->psl,frame->sp, 422 p->p_pid,frame); 423 #endif 424 uvmexp.syscalls++; 425 426 exptr = l->l_addr->u_pcb.framep = frame; 427 callp = p->p_emul->e_sysent; 428 nsys = p->p_emul->e_nsysent; 429 oticks = p->p_sticks; 430 431 if (frame->code == SYS___syscall) { 432 int g = *(int *)(frame->ap); 433 434 frame->code = *(int *)(frame->ap + 4); 435 frame->ap += 8; 436 *(int *)(frame->ap) = g - 2; 437 } 438 439 if ((unsigned long) frame->code >= nsys) 440 callp += p->p_emul->e_nosys; 441 else 442 callp += frame->code; 443 444 rval[0] = 0; 445 rval[1] = frame->r1; 446 KERNEL_PROC_LOCK(l); 447 if (callp->sy_narg) { 448 err = copyin((char*)frame->ap + 4, args, callp->sy_argsize); 449 if (err) { 450 KERNEL_PROC_UNLOCK(l); 451 goto bad; 452 } 453 } 454 455 if ((err = trace_enter(l, frame->code, frame->code, NULL, args)) != 0) { 456 KERNEL_PROC_UNLOCK(l); 457 goto bad; 458 } 459 460 err = (*callp->sy_call)(curlwp, args, rval); 461 KERNEL_PROC_UNLOCK(l); 462 exptr = l->l_addr->u_pcb.framep; 463 464 #ifdef TRAPDEBUG 465 if(startsysc) 466 printf("retur %s pc %lx, psl %lx, sp %lx, pid %d, err %d r0 %d, r1 %d, frame %p\n", 467 syscallnames[exptr->code], exptr->pc, exptr->psl,exptr->sp, 468 p->p_pid,err,rval[0],rval[1],exptr); /* } */ 469 #endif 470 471 bad: 472 switch (err) { 473 case 0: 474 exptr->r1 = rval[1]; 475 exptr->r0 = rval[0]; 476 exptr->psl &= ~PSL_C; 477 break; 478 479 case EJUSTRETURN: 480 break; 481 482 case ERESTART: 483 exptr->pc -= (exptr->code > 63 ? 4 : 2); 484 break; 485 486 default: 487 exptr->r0 = err; 488 exptr->psl |= PSL_C; 489 break; 490 } 491 492 trace_exit(l, frame->code, args, rval, err); 493 494 userret(l, frame, oticks); 495 } 496 497 void 498 child_return(void *arg) 499 { 500 struct lwp *l = arg; 501 502 KERNEL_PROC_UNLOCK(l); 503 userret(l, l->l_addr->u_pcb.framep, 0); 504 505 #ifdef KTRACE 506 if (KTRPOINT(l->l_proc, KTR_SYSRET)) { 507 KERNEL_PROC_LOCK(l); 508 ktrsysret(l->l_proc, SYS_fork, 0, 0); 509 KERNEL_PROC_UNLOCK(l); 510 } 511 #endif 512 } 513 514 /* 515 * Start a new LWP 516 */ 517 void 518 startlwp(arg) 519 void *arg; 520 { 521 int err; 522 ucontext_t *uc = arg; 523 struct lwp *l = curlwp; 524 525 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 526 #if DIAGNOSTIC 527 if (err) { 528 printf("Error %d from cpu_setmcontext.", err); 529 } 530 #endif 531 pool_put(&lwp_uc_pool, uc); 532 533 /* XXX - profiling spoiled here */ 534 userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks); 535 } 536 537 void 538 upcallret(struct lwp *l) 539 { 540 541 /* XXX - profiling */ 542 userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks); 543 } 544 545