1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1992 OMRON Corporation. 4 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department. 10 * 11 * %sccs.include.redist.c% 12 * 13 * from: Utah $Hdr: trap.c 1.35 91/12/26$ 14 * OMRON: $Id: trap.c,v 1.2 92/06/14 06:23:41 moti Exp $ 15 * 16 * from: hp300/hp300/trap.c 7.23 (Berkeley) 7/9/92 17 * 18 * @(#)trap.c 7.3 (Berkeley) 10/11/92 19 */ 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/proc.h> 24 #include <sys/acct.h> 25 #include <sys/kernel.h> 26 #include <sys/signalvar.h> 27 #include <sys/resourcevar.h> 28 #include <sys/syscall.h> 29 #include <sys/syslog.h> 30 #include <sys/user.h> 31 #ifdef KTRACE 32 #include <sys/ktrace.h> 33 #endif 34 35 #include <machine/psl.h> 36 #include <machine/trap.h> 37 #include <machine/cpu.h> 38 #include <machine/reg.h> 39 #include <machine/mtpr.h> 40 41 #include <vm/vm.h> 42 #include <vm/pmap.h> 43 44 struct sysent sysent[]; 45 int nsysent; 46 47 char *trap_type[] = { 48 "Bus error", 49 "Address error", 50 "Illegal instruction", 51 "Zero divide", 52 "CHK instruction", 53 "TRAPV instruction", 54 "Privilege violation", 55 "Trace trap", 56 "MMU fault", 57 "SSIR trap", 58 "Format error", 59 "68881 exception", 60 "Coprocessor violation", 61 "Async system trap" 62 }; 63 #define TRAP_TYPES (sizeof trap_type / sizeof trap_type[0]) 64 65 /* 66 * Size of various exception stack frames (minus the standard 8 bytes) 67 */ 68 short exframesize[] = { 69 FMT0SIZE, /* type 0 - normal (68020/030/040) */ 70 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 71 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040) */ 72 FMT3SIZE, /* type 3 - FP post-instruction (68040) */ 73 -1, -1, -1, /* type 4-6 - undefined */ 74 FMT7SIZE, /* type 7 - access error (68040) */ 75 58, /* type 8 - bus fault (68010) */ 76 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 77 FMTASIZE, /* type A - short bus fault (68020/030) */ 78 FMTBSIZE, /* type B - long bus fault (68020/030) */ 79 -1, -1, -1, -1 /* type C-F - undefined */ 80 }; 81 82 #define KDFAULT(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 83 #define WRFAULT(c) (((c) & (SSW_DF|SSW_RW)) == SSW_DF) 84 85 #ifdef DEBUG 86 int mmudebug = 0; 87 int mmupid = -1; 88 #define MDB_FOLLOW 1 89 #define MDB_WBFOLLOW 2 90 #define MDB_WBFAILED 4 91 #define MDB_ISPID(p) (p) == mmupid 92 #endif 93 94 /* 95 * trap and syscall both need the following work done before returning 96 * to user mode. 97 */ 98 static inline void 99 userret(p, fp, oticks, faultaddr, fromtrap) 100 register struct proc *p; 101 register struct frame *fp; 102 u_quad_t oticks; 103 u_int faultaddr; 104 int fromtrap; 105 { 106 int sig, s; 107 108 /* take pending signals */ 109 while ((sig = CURSIG(p)) != 0) 110 psig(sig); 111 p->p_pri = p->p_usrpri; 112 if (want_resched) { 113 /* 114 * Since we are curproc, clock will normally just change 115 * our priority without moving us from one queue to another 116 * (since the running process is not on a queue.) 117 * If that happened after we setrq ourselves but before we 118 * swtch()'ed, we might not be on the queue indicated by 119 * our priority. 120 */ 121 s = splstatclock(); 122 setrq(p); 123 p->p_stats->p_ru.ru_nivcsw++; 124 swtch(); 125 splx(s); 126 while ((sig = CURSIG(p)) != 0) 127 psig(sig); 128 } 129 130 /* 131 * If profiling, charge system time to the trapped pc. 132 */ 133 if (p->p_flag & SPROFIL) 134 addupc_intr(p, fp->f_pc, (int)(p->p_sticks - oticks)); 135 #ifdef HP380 136 /* 137 * Deal with user mode writebacks (from trap, or from sigreturn). 138 * If any writeback fails, go back and attempt signal delivery. 139 * unless we have already been here and attempted the writeback 140 * (e.g. bad address with user ignoring SIGSEGV). In that case 141 * we just return to the user without sucessfully completing 142 * the writebacks. Maybe we should just drop the sucker? 143 */ 144 if (mmutype == MMU_68040 && fp->f_format == FMT7) { 145 if (beenhere) { 146 #ifdef DEBUG 147 if (mmudebug & MDB_WBFAILED) 148 printf(fromtrap ? 149 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 150 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 151 p->p_pid, p->p_comm, fp->f_pc, faultaddr); 152 #endif 153 } else if (sig = writeback(fp, fromtrap)) { 154 beenhere = 1; 155 oticks = p->p_sticks; 156 trapsignal(p, sig, faultaddr); 157 goto again; 158 } 159 } 160 #endif 161 curpri = p->p_pri; 162 } 163 164 /* 165 * Trap is called from locore to handle most types of processor traps, 166 * including events such as simulated software interrupts/AST's. 167 * System calls are broken out for efficiency. 168 */ 169 /*ARGSUSED*/ 170 trap(type, code, v, frame) 171 int type; 172 unsigned code; 173 register unsigned v; 174 struct frame frame; 175 { 176 register int i; 177 unsigned ucode; 178 register struct proc *p; 179 u_quad_t sticks; 180 unsigned ncode; 181 extern char fswintr[]; 182 183 cnt.v_trap++; 184 p = curproc; 185 ucode = 0; 186 if (USERMODE(frame.f_sr)) { 187 type |= T_USER; 188 sticks = p->p_sticks; 189 p->p_md.md_regs = frame.f_regs; 190 } 191 switch (type) { 192 193 default: 194 dopanic: 195 printf("trap type %d, code = %x, v = %x\n", type, code, v); 196 regdump(frame.f_regs, 128); 197 type &= ~T_USER; 198 if ((unsigned)type < TRAP_TYPES) 199 panic(trap_type[type]); 200 panic("trap"); 201 202 case T_BUSERR: /* kernel bus error */ 203 if (!p->p_addr->u_pcb.pcb_onfault) 204 goto dopanic; 205 /* 206 * If we have arranged to catch this fault in any of the 207 * copy to/from user space routines, set PC to return to 208 * indicated location and set flag informing buserror code 209 * that it may need to clean up stack frame. 210 */ 211 copyfault: 212 frame.f_stackadj = exframesize[frame.f_format]; 213 frame.f_format = frame.f_vector = 0; 214 frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 215 return; 216 217 case T_BUSERR|T_USER: /* bus error */ 218 case T_ADDRERR|T_USER: /* address error */ 219 ucode = v; 220 i = SIGBUS; 221 break; 222 223 #ifdef FPCOPROC 224 case T_COPERR: /* kernel coprocessor violation */ 225 #endif 226 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 227 case T_FMTERR: /* ...just in case... */ 228 /* 229 * The user has most likely trashed the RTE or FP state info 230 * in the stack frame of a signal handler. 231 */ 232 type |= T_USER; 233 printf("pid %d: kernel %s exception\n", p->p_pid, 234 type==T_COPERR ? "coprocessor" : "format"); 235 p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL; 236 i = sigmask(SIGILL); 237 p->p_sigignore &= ~i; 238 p->p_sigcatch &= ~i; 239 p->p_sigmask &= ~i; 240 i = SIGILL; 241 ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 242 break; 243 244 #ifdef FPCOPROC 245 case T_COPERR|T_USER: /* user coprocessor violation */ 246 /* What is a proper response here? */ 247 ucode = 0; 248 i = SIGFPE; 249 break; 250 251 case T_FPERR|T_USER: /* 68881 exceptions */ 252 /* 253 * We pass along the 68881 status register which locore stashed 254 * in code for us. Note that there is a possibility that the 255 * bit pattern of this register will conflict with one of the 256 * FPE_* codes defined in signal.h. Fortunately for us, the 257 * only such codes we use are all in the range 1-7 and the low 258 * 3 bits of the status register are defined as 0 so there is 259 * no clash. 260 */ 261 ucode = code; 262 i = SIGFPE; 263 break; 264 #endif 265 266 case T_ILLINST|T_USER: /* illegal instruction fault */ 267 case T_PRIVINST|T_USER: /* privileged instruction fault */ 268 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 269 i = SIGILL; 270 break; 271 272 case T_ZERODIV|T_USER: /* Divide by zero */ 273 ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 274 i = SIGFPE; 275 break; 276 277 case T_CHKINST|T_USER: /* CHK instruction trap */ 278 ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 279 i = SIGFPE; 280 break; 281 282 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 283 ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 284 i = SIGFPE; 285 break; 286 287 /* 288 * XXX: Trace traps are a nightmare. 289 * 290 * HP-UX uses trap #1 for breakpoints, 291 * HPBSD uses trap #2, 292 * SUN 3.x uses trap #15, 293 * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). 294 * 295 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 296 * SUN 3.x traps get passed through as T_TRAP15 and are not really 297 * supported yet. 298 */ 299 case T_TRACE: /* kernel trace trap */ 300 case T_TRAP15: /* SUN trace trap */ 301 frame.f_sr &= ~PSL_T; 302 i = SIGTRAP; 303 break; 304 305 case T_TRACE|T_USER: /* user trace trap */ 306 case T_TRAP15|T_USER: /* SUN user trace trap */ 307 frame.f_sr &= ~PSL_T; 308 i = SIGTRAP; 309 break; 310 311 case T_ASTFLT: /* system async trap, cannot happen */ 312 goto dopanic; 313 314 case T_ASTFLT|T_USER: /* user async trap */ 315 astpending = 0; 316 /* 317 * We check for software interrupts first. This is because 318 * they are at a higher level than ASTs, and on a VAX would 319 * interrupt the AST. We assume that if we are processing 320 * an AST that we must be at IPL0 so we don't bother to 321 * check. Note that we ensure that we are at least at SIR 322 * IPL while processing the SIR. 323 */ 324 spl1(); 325 /* fall into... */ 326 327 case T_SSIR: /* software interrupt */ 328 case T_SSIR|T_USER: 329 if (ssir & SIR_NET) { 330 siroff(SIR_NET); 331 cnt.v_soft++; 332 netintr(); 333 } 334 if (ssir & SIR_CLOCK) { 335 siroff(SIR_CLOCK); 336 cnt.v_soft++; 337 softclock(); 338 } 339 /* 340 * If this was not an AST trap, we are all done. 341 */ 342 if (type != (T_ASTFLT|T_USER)) { 343 cnt.v_trap--; 344 return; 345 } 346 spl0(); 347 if (p->p_flag & SOWEUPC) { 348 p->p_flag &= ~SOWEUPC; 349 ADDUPROF(p); 350 } 351 goto out; 352 353 case T_MMUFLT: /* kernel mode page fault */ 354 /* 355 * If we were doing profiling ticks or other user mode 356 * stuff from interrupt code, Just Say No. 357 */ 358 if (p->p_addr->u_pcb.pcb_onfault == fswintr) 359 goto copyfault; 360 /* fall into ... */ 361 362 case T_MMUFLT|T_USER: /* page fault */ 363 { 364 register vm_offset_t va; 365 register struct vmspace *vm = p->p_vmspace; 366 register vm_map_t map; 367 int rv; 368 vm_prot_t ftype; 369 extern vm_map_t kernel_map; 370 371 #ifdef DEBUG 372 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 373 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 374 p->p_pid, code, v, frame.f_pc, frame.f_sr); 375 #endif 376 /* 377 * It is only a kernel address space fault iff: 378 * 1. (type & T_USER) == 0 and 379 * 2. pcb_onfault not set or 380 * 3. pcb_onfault set but supervisor space data fault 381 * The last can occur during an exec() copyin where the 382 * argument space is lazy-allocated. 383 */ 384 if (type == T_MMUFLT && 385 (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code))) 386 map = kernel_map; 387 else 388 map = &vm->vm_map; 389 if (WRFAULT(code)) 390 ftype = VM_PROT_READ | VM_PROT_WRITE; 391 else 392 ftype = VM_PROT_READ; 393 va = trunc_page((vm_offset_t)v); 394 #ifdef DEBUG 395 if (map == kernel_map && va == 0) { 396 printf("trap: bad kernel access at %x\n", v); 397 goto dopanic; 398 } 399 #endif 400 rv = vm_fault(map, va, ftype, FALSE); 401 #ifdef DEBUG 402 if (rv && MDB_ISPID(p->p_pid)) 403 printf("vm_fault(%x, %x, %x, 0) -> %x\n", 404 map, va, ftype, rv); 405 #endif 406 /* 407 * If this was a stack access we keep track of the maximum 408 * accessed stack size. Also, if vm_fault gets a protection 409 * failure it is due to accessing the stack region outside 410 * the current limit and we need to reflect that as an access 411 * error. 412 */ 413 if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) { 414 if (rv == KERN_SUCCESS) { 415 unsigned nss; 416 417 nss = clrnd(btoc(USRSTACK-(unsigned)va)); 418 if (nss > vm->vm_ssize) 419 vm->vm_ssize = nss; 420 } else if (rv == KERN_PROTECTION_FAILURE) 421 rv = KERN_INVALID_ADDRESS; 422 } 423 if (rv == KERN_SUCCESS) { 424 if (type == T_MMUFLT) { 425 return; 426 } 427 goto out; 428 } 429 if (type == T_MMUFLT) { 430 if (p->p_addr->u_pcb.pcb_onfault) 431 goto copyfault; 432 printf("vm_fault(%x, %x, %x, 0) -> %x\n", 433 map, va, ftype, rv); 434 printf(" type %x, code [mmu,,ssw]: %x\n", 435 type, code); 436 goto dopanic; 437 } 438 ucode = v; 439 i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; 440 break; 441 } 442 } 443 trapsignal(p, i, ucode); 444 if ((type & T_USER) == 0) 445 return; 446 out: 447 userret(p, &frame, sticks, v, 1); 448 } 449 450 /* 451 * Proces a system call. 452 */ 453 syscall(code, frame) 454 u_int code; 455 struct frame frame; 456 { 457 register caddr_t params; 458 register struct sysent *callp; 459 register struct proc *p; 460 int error, opc, numsys, s; 461 u_int argsize; 462 struct args { 463 int i[8]; 464 } args; 465 int rval[2]; 466 u_quad_t sticks; 467 468 cnt.v_syscall++; 469 if (!USERMODE(frame.f_sr)) 470 panic("syscall"); 471 p = curproc; 472 sticks = p->p_sticks; 473 p->p_md.md_regs = frame.f_regs; 474 opc = frame.f_pc - 2; 475 callp = sysent, numsys = nsysent; 476 params = (caddr_t)frame.f_regs[SP] + sizeof(int); 477 switch (code) { 478 479 case SYS_indir: 480 /* 481 * Code is first argument, followed by actual args. 482 */ 483 code = fuword(params); 484 params += sizeof(int); 485 break; 486 487 case SYS___indir: 488 /* 489 * Like indir, but code is a quad, so as to maintain 490 * quad alignment for the rest of the arguments. 491 */ 492 code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 493 params += sizeof(quad_t); 494 break; 495 496 default: 497 /* nothing to do by default */ 498 break; 499 } 500 if (code < numsys) 501 callp += code; 502 else 503 callp += SYS_indir; /* => nosys */ 504 argsize = callp->sy_narg * sizeof(int); 505 if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) { 506 #ifdef KTRACE 507 if (KTRPOINT(p, KTR_SYSCALL)) 508 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 509 #endif 510 goto bad; 511 } 512 #ifdef KTRACE 513 if (KTRPOINT(p, KTR_SYSCALL)) 514 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 515 #endif 516 rval[0] = 0; 517 rval[1] = frame.f_regs[D1]; 518 error = (*callp->sy_call)(p, &args, rval); 519 switch (error) { 520 521 case 0: 522 /* 523 * Reinitialize proc pointer `p' as it may be different 524 * if this is a child returning from fork syscall. 525 */ 526 p = curproc; 527 frame.f_regs[D0] = rval[0]; 528 frame.f_regs[D1] = rval[1]; 529 frame.f_sr &= ~PSL_C; 530 break; 531 532 case ERESTART: 533 frame.f_pc = opc; 534 break; 535 536 case EJUSTRETURN: 537 break; /* nothing to do */ 538 539 default: 540 bad: 541 frame.f_regs[D0] = error; 542 frame.f_sr |= PSL_C; 543 break; 544 } 545 546 userret(p, &frame, sticks, (u_int)0, 0); 547 #ifdef KTRACE 548 if (KTRPOINT(p, KTR_SYSRET)) 549 ktrsysret(p->p_tracep, code, error, rval[0]); 550 #endif 551 } 552