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