1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: trap.c 1.28 89/09/25$ 13 * 14 * @(#)trap.c 7.5 (Berkeley) 06/22/90 15 */ 16 17 #include "cpu.h" 18 #include "psl.h" 19 #include "reg.h" 20 #include "pte.h" 21 #include "mtpr.h" 22 23 #include "param.h" 24 #include "systm.h" 25 #include "user.h" 26 #include "proc.h" 27 #include "seg.h" 28 #include "trap.h" 29 #include "acct.h" 30 #include "kernel.h" 31 #include "vm.h" 32 #include "cmap.h" 33 #include "syslog.h" 34 #ifdef KTRACE 35 #include "ktrace.h" 36 #endif 37 38 #ifdef HPUXCOMPAT 39 #include "../hpux/hpux.h" 40 #endif 41 42 #define USER 040 /* user-mode flag added to type */ 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 #ifdef DEBUG 66 int mmudebug = 0; 67 #endif 68 69 /* 70 * Called from the trap handler when a processor trap occurs. 71 */ 72 /*ARGSUSED*/ 73 trap(type, code, v, frame) 74 int type; 75 unsigned code; 76 register unsigned v; 77 struct frame frame; 78 { 79 register int i; 80 unsigned ucode = 0; 81 register struct proc *p = u.u_procp; 82 struct timeval syst; 83 unsigned ncode; 84 85 cnt.v_trap++; 86 syst = u.u_ru.ru_stime; 87 if (USERMODE(frame.f_sr)) { 88 type |= USER; 89 u.u_ar0 = frame.f_regs; 90 } 91 switch (type) { 92 93 default: 94 dopanic: 95 #ifdef KGDB 96 if (!panicstr && kgdb_trap(type, code, v, &frame)) 97 return; 98 #endif 99 printf("trap type %d, code = %x, v = %x\n", type, code, v); 100 regdump(frame.f_regs, 128); 101 type &= ~USER; 102 if ((unsigned)type < TRAP_TYPES) 103 panic(trap_type[type]); 104 panic("trap"); 105 106 case T_BUSERR: /* kernel bus error */ 107 if (!u.u_pcb.pcb_onfault) 108 goto dopanic; 109 /* 110 * If we have arranged to catch this fault in any of the 111 * copy to/from user space routines, set PC to return to 112 * indicated location and set flag informing buserror code 113 * that it may need to clean up stack frame. 114 */ 115 copyfault: 116 frame.f_pc = (int) u.u_pcb.pcb_onfault; 117 frame.f_stackadj = -1; 118 return; 119 120 case T_BUSERR+USER: /* bus error */ 121 case T_ADDRERR+USER: /* address error */ 122 i = SIGBUS; 123 break; 124 125 #ifdef FPCOPROC 126 case T_COPERR: /* kernel coprocessor violation */ 127 #endif 128 case T_FMTERR: /* kernel format error */ 129 /* 130 * The user has most likely trashed the RTE or FP state info 131 * in the stack frame of a signal handler. 132 */ 133 type |= USER; 134 printf("pid %d: kernel %s exception\n", u.u_procp->p_pid, 135 type==T_COPERR ? "coprocessor" : "format"); 136 u.u_signal[SIGILL] = SIG_DFL; 137 i = sigmask(SIGILL); 138 p->p_sigignore &= ~i; 139 p->p_sigcatch &= ~i; 140 p->p_sigmask &= ~i; 141 i = SIGILL; 142 ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 143 break; 144 145 #ifdef FPCOPROC 146 case T_COPERR+USER: /* user coprocessor violation */ 147 /* What is a proper response here? */ 148 ucode = 0; 149 i = SIGFPE; 150 break; 151 152 case T_FPERR+USER: /* 68881 exceptions */ 153 /* 154 * We pass along the 68881 status register which locore stashed 155 * in code for us. Note that there is a possibility that the 156 * bit pattern of this register will conflict with one of the 157 * FPE_* codes defined in signal.h. Fortunately for us, the 158 * only such codes we use are all in the range 1-7 and the low 159 * 3 bits of the status register are defined as 0 so there is 160 * no clash. 161 */ 162 ucode = code; 163 i = SIGFPE; 164 break; 165 #endif 166 167 case T_ILLINST+USER: /* illegal instruction fault */ 168 #ifdef HPUXCOMPAT 169 if (u.u_procp->p_flag & SHPUX) { 170 ucode = HPUX_ILL_ILLINST_TRAP; 171 i = SIGILL; 172 break; 173 } 174 /* fall through */ 175 #endif 176 case T_PRIVINST+USER: /* privileged instruction fault */ 177 #ifdef HPUXCOMPAT 178 if (u.u_procp->p_flag & SHPUX) 179 ucode = HPUX_ILL_PRIV_TRAP; 180 else 181 #endif 182 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 183 i = SIGILL; 184 break; 185 186 case T_ZERODIV+USER: /* Divide by zero */ 187 #ifdef HPUXCOMPAT 188 if (u.u_procp->p_flag & SHPUX) 189 ucode = HPUX_FPE_INTDIV_TRAP; 190 else 191 #endif 192 ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 193 i = SIGFPE; 194 break; 195 196 case T_CHKINST+USER: /* CHK instruction trap */ 197 #ifdef HPUXCOMPAT 198 if (u.u_procp->p_flag & SHPUX) { 199 /* handled differently under hp-ux */ 200 i = SIGILL; 201 ucode = HPUX_ILL_CHK_TRAP; 202 break; 203 } 204 #endif 205 ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 206 i = SIGFPE; 207 break; 208 209 case T_TRAPVINST+USER: /* TRAPV instruction trap */ 210 #ifdef HPUXCOMPAT 211 if (u.u_procp->p_flag & SHPUX) { 212 /* handled differently under hp-ux */ 213 i = SIGILL; 214 ucode = HPUX_ILL_TRAPV_TRAP; 215 break; 216 } 217 #endif 218 ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 219 i = SIGFPE; 220 break; 221 222 /* 223 * XXX: Trace traps are a nightmare. 224 * 225 * HP-UX uses trap #1 for breakpoints, 226 * HPBSD uses trap #2, 227 * SUN 3.x uses trap #15, 228 * KGDB uses trap #15 (for kernel breakpoints). 229 * 230 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 231 * SUN 3.x traps get passed through as T_TRAP15 and are not really 232 * supported yet. KGDB traps are also passed through as T_TRAP15 233 * and are not used yet. 234 */ 235 case T_TRACE: /* kernel trace trap */ 236 case T_TRAP15: /* SUN (or KGDB) kernel trace trap */ 237 #ifdef KGDB 238 if (kgdb_trap(type, code, v, &frame)) 239 return; 240 #endif 241 frame.f_sr &= ~PSL_T; 242 i = SIGTRAP; 243 break; 244 245 case T_TRACE+USER: /* user trace trap */ 246 case T_TRAP15+USER: /* SUN user trace trap */ 247 frame.f_sr &= ~PSL_T; 248 i = SIGTRAP; 249 break; 250 251 case T_ASTFLT: /* system async trap, cannot happen */ 252 goto dopanic; 253 254 case T_ASTFLT+USER: /* user async trap */ 255 astoff(); 256 /* 257 * We check for software interrupts first. This is because 258 * they are at a higher level than ASTs, and on a VAX would 259 * interrupt the AST. We assume that if we are processing 260 * an AST that we must be at IPL0 so we don't bother to 261 * check. Note that we ensure that we are at least at SIR 262 * IPL while processing the SIR. 263 */ 264 spl1(); 265 /* fall into... */ 266 267 case T_SSIR: /* software interrupt */ 268 case T_SSIR+USER: 269 if (ssir & SIR_NET) { 270 siroff(SIR_NET); 271 cnt.v_soft++; 272 netintr(); 273 } 274 if (ssir & SIR_CLOCK) { 275 siroff(SIR_CLOCK); 276 cnt.v_soft++; 277 softclock((caddr_t)frame.f_pc, (int)frame.f_sr); 278 } 279 /* 280 * If this was not an AST trap, we are all done. 281 */ 282 if (type != T_ASTFLT+USER) { 283 cnt.v_trap--; 284 return; 285 } 286 spl0(); 287 #ifndef PROFTIMER 288 if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) { 289 addupc(frame.f_pc, &u.u_prof, 1); 290 u.u_procp->p_flag &= ~SOWEUPC; 291 } 292 #endif 293 goto out; 294 295 case T_MMUFLT: /* kernel mode page fault */ 296 /* 297 * Could be caused by a page fault in one of the copy to/from 298 * user space routines. If so, we will have a catch address. 299 */ 300 if (!u.u_pcb.pcb_onfault) 301 goto dopanic; 302 /* fall into ... */ 303 304 case T_MMUFLT+USER: /* page fault */ 305 /* 306 printf("trap: T_MMUFLT pid %d, code %x, v %x, pc %x, ps %x\n", 307 p->p_pid, code, v, frame.f_pc, frame.f_sr); 308 */ 309 if (v >= USRSTACK) { 310 if (type == T_MMUFLT) 311 goto copyfault; 312 i = SIGSEGV; 313 break; 314 } 315 ncode = code >> 16; 316 #if defined(HP330) || defined(HP360) || defined(HP370) 317 /* 318 * Crudely map PMMU faults into HP MMU faults. 319 */ 320 if (mmutype != MMU_HP) { 321 int ocode = ncode; 322 ncode = 0; 323 if (ocode & PMMU_WP) 324 ncode |= MMU_WPF; 325 else if (ocode & PMMU_INV) { 326 if ((ocode & PMMU_LVLMASK) == 2) 327 ncode |= MMU_PF; 328 else 329 ncode |= MMU_PTF; 330 } 331 /* 332 * RMW cycle, must load ATC by hand 333 */ 334 else if ((code & (SSW_DF|SSW_RM)) == (SSW_DF|SSW_RM)) { 335 #ifdef DEBUG 336 log(LOG_WARNING, 337 "RMW fault at %x: MMUSR %x SSW %x\n", 338 v, ocode, code & 0xFFFF); 339 #endif 340 ploadw((caddr_t)v); 341 return; 342 } 343 /* 344 * Fault with no fault bits, should indicate bad 345 * hardware but we see this on 340s using starbase 346 * sometimes (faults accessing catseye registers) 347 */ 348 else { 349 log(LOG_WARNING, 350 "Bad PMMU fault at %x: MMUSR %x SSW %x\n", 351 v, ocode, code & 0xFFFF); 352 return; 353 } 354 #ifdef DEBUG 355 if (mmudebug && mmudebug == p->p_pid) 356 printf("MMU %d: v%x, os%x, ns%x\n", 357 p->p_pid, v, ocode, ncode); 358 #endif 359 } 360 #endif 361 #ifdef DEBUG 362 if ((ncode & (MMU_PTF|MMU_PF|MMU_WPF|MMU_FPE)) == 0) { 363 printf("T_MMUFLT with no fault bits\n"); 364 goto dopanic; 365 } 366 #endif 367 if (ncode & MMU_PTF) { 368 #ifdef DEBUG 369 /* 370 * NOTE: we use a u_int instead of an ste since the 371 * current compiler generates bogus code for some 372 * bitfield operations (i.e. attempts to access last 373 * word of a page as a longword causing fault). 374 */ 375 extern struct ste *vtoste(); 376 u_int *ste = (u_int *)vtoste(p, v); 377 378 if (*ste & SG_V) { 379 if (ncode & MMU_WPF) { 380 printf("PTF|WPF...\n"); 381 if (type == T_MMUFLT) 382 goto copyfault; 383 i = SIGBUS; 384 break; 385 } 386 printf("MMU_PTF with sg_v, ste@%x = %x\n", 387 ste, *ste); 388 goto dopanic; 389 } 390 #endif 391 #ifdef HPUXCOMPAT 392 if (ISHPMMADDR(v)) { 393 extern struct ste *vtoste(); 394 u_int *bste, *nste; 395 396 bste = (u_int *)vtoste(p, HPMMBASEADDR(v)); 397 nste = (u_int *)vtoste(p, v); 398 if ((*bste & SG_V) && *nste == SG_NV) { 399 *nste = *bste; 400 TBIAU(); 401 return; 402 } 403 } 404 #endif 405 growit: 406 if (type == T_MMUFLT) 407 goto copyfault; 408 if (grow((unsigned)frame.f_regs[SP]) || grow(v)) 409 goto out; 410 i = SIGSEGV; 411 break; 412 } 413 #ifdef HPUXCOMPAT 414 if (ISHPMMADDR(v)) { 415 TBIS(v); 416 v = HPMMBASEADDR(v); 417 } 418 #endif 419 /* 420 * NOTE: WPF without PG_V is possible 421 * (e.g. attempt to write shared text which is paged out) 422 */ 423 if (ncode & MMU_WPF) { 424 #ifdef DEBUG 425 extern struct ste *vtoste(); 426 u_int *ste = (u_int *)vtoste(p, v); 427 428 if (!(*ste & SG_V)) { 429 printf("MMU_WPF without sg_v, ste@%x = %x\n", 430 ste, *ste); 431 goto dopanic; 432 } 433 #endif 434 if (type == T_MMUFLT) 435 goto copyfault; 436 i = SIGBUS; 437 break; 438 } 439 if (ncode & MMU_PF) { 440 register u_int vp; 441 #ifdef DEBUG 442 extern struct ste *vtoste(); 443 u_int *ste = (u_int *)vtoste(p, v); 444 struct pte *pte; 445 446 if (!(*ste & SG_V)) { 447 printf("MMU_PF without sg_v, ste@%x = %x\n", 448 ste, *ste); 449 goto dopanic; 450 } 451 #endif 452 vp = btop(v); 453 if (vp >= dptov(p, p->p_dsize) && 454 vp < sptov(p, p->p_ssize-1)) 455 goto growit; 456 #ifdef DEBUG 457 pte = vtopte(p, vp); 458 if (*(u_int *)pte & PG_V) { 459 printf("MMU_PF with pg_v, pte = %x\n", 460 *(u_int *)pte); 461 goto dopanic; 462 } 463 #endif 464 i = u.u_error; 465 pagein(v, 0); 466 u.u_error = i; 467 if (type == T_MMUFLT) 468 return; 469 goto out; 470 } 471 #ifdef DEBUG 472 printf("T_MMUFLT: unrecognized scenerio\n"); 473 goto dopanic; 474 #endif 475 } 476 trapsignal(i, ucode); 477 if ((type & USER) == 0) 478 return; 479 out: 480 p = u.u_procp; 481 if (i = CURSIG(p)) 482 psig(i); 483 p->p_pri = p->p_usrpri; 484 if (runrun) { 485 /* 486 * Since we are u.u_procp, clock will normally just change 487 * our priority without moving us from one queue to another 488 * (since the running process is not on a queue.) 489 * If that happened after we setrq ourselves but before we 490 * swtch()'ed, we might not be on the queue indicated by 491 * our priority. 492 */ 493 (void) splclock(); 494 setrq(p); 495 u.u_ru.ru_nivcsw++; 496 swtch(); 497 if (i = CURSIG(p)) 498 psig(i); 499 } 500 if (u.u_prof.pr_scale) { 501 int ticks; 502 struct timeval *tv = &u.u_ru.ru_stime; 503 504 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 505 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 506 if (ticks) { 507 #ifdef PROFTIMER 508 extern int profscale; 509 addupc(frame.f_pc, &u.u_prof, ticks * profscale); 510 #else 511 addupc(frame.f_pc, &u.u_prof, ticks); 512 #endif 513 } 514 } 515 curpri = p->p_pri; 516 } 517 518 /* 519 * Called from the trap handler when a system call occurs 520 */ 521 /*ARGSUSED*/ 522 syscall(code, frame) 523 volatile int code; 524 struct frame frame; 525 { 526 register caddr_t params; 527 register int i; 528 register struct sysent *callp; 529 register struct proc *p = u.u_procp; 530 int error, opc, numsys; 531 struct timeval syst; 532 struct sysent *systab; 533 #ifdef HPUXCOMPAT 534 extern struct sysent hpuxsysent[]; 535 extern int hpuxnsysent, notimp(); 536 #endif 537 538 cnt.v_syscall++; 539 syst = u.u_ru.ru_stime; 540 if (!USERMODE(frame.f_sr)) 541 panic("syscall"); 542 u.u_ar0 = frame.f_regs; 543 u.u_error = 0; 544 opc = frame.f_pc - 2; 545 systab = sysent; 546 numsys = nsysent; 547 #ifdef HPUXCOMPAT 548 if (p->p_flag & SHPUX) { 549 systab = hpuxsysent; 550 numsys = hpuxnsysent; 551 } 552 #endif 553 params = (caddr_t)frame.f_regs[SP] + NBPW; 554 if (code == 0) { /* indir */ 555 code = fuword(params); 556 params += NBPW; 557 } 558 if (code >= numsys) 559 callp = &systab[0]; /* indir (illegal) */ 560 else 561 callp = &systab[code]; 562 if ((i = callp->sy_narg * sizeof (int)) && 563 (error = copyin(params, (caddr_t)u.u_arg, (u_int)i))) { 564 #ifdef HPUXCOMPAT 565 if (p->p_flag & SHPUX) 566 error = bsdtohpuxerrno(error); 567 #endif 568 frame.f_regs[D0] = (u_char) error; 569 frame.f_sr |= PSL_C; /* carry bit */ 570 #ifdef KTRACE 571 if (KTRPOINT(p, KTR_SYSCALL)) 572 ktrsyscall(p->p_tracep, code, callp->sy_narg); 573 #endif 574 goto done; 575 } 576 #ifdef KTRACE 577 if (KTRPOINT(p, KTR_SYSCALL)) 578 ktrsyscall(p->p_tracep, code, callp->sy_narg); 579 #endif 580 u.u_r.r_val1 = 0; 581 u.u_r.r_val2 = frame.f_regs[D0]; 582 #ifdef HPUXCOMPAT 583 /* debug kludge */ 584 if (callp->sy_call == notimp) 585 error = notimp(u.u_procp, u.u_ap, &u.u_r.r_val1, 586 code, callp->sy_narg); 587 else 588 #endif 589 error = (*callp->sy_call)(u.u_procp, u.u_ap, &u.u_r.r_val1); 590 error = u.u_error; /* XXX */ 591 if (error == ERESTART) 592 frame.f_pc = opc; 593 else if (error != EJUSTRETURN) { 594 if (error) { 595 #ifdef HPUXCOMPAT 596 if (p->p_flag & SHPUX) 597 error = bsdtohpuxerrno(error); 598 #endif 599 frame.f_regs[D0] = (u_char) error; 600 frame.f_sr |= PSL_C; /* carry bit */ 601 } else { 602 frame.f_regs[D0] = u.u_r.r_val1; 603 frame.f_regs[D1] = u.u_r.r_val2; 604 frame.f_sr &= ~PSL_C; 605 } 606 } 607 /* else if (error == EJUSTRETURN) */ 608 /* nothing to do */ 609 610 done: 611 /* 612 * Reinitialize proc pointer `p' as it may be different 613 * if this is a child returning from fork syscall. 614 */ 615 p = u.u_procp; 616 /* 617 * XXX the check for sigreturn ensures that we don't 618 * attempt to set up a call to a signal handler (sendsig) before 619 * we have cleaned up the stack from the last call (sigreturn). 620 * Allowing this seems to lock up the machine in certain scenarios. 621 * What should really be done is to clean up the signal handling 622 * so that this is not a problem. 623 */ 624 #include "syscall.h" 625 if (code != SYS_sigreturn && (i = CURSIG(p))) 626 psig(i); 627 p->p_pri = p->p_usrpri; 628 if (runrun) { 629 /* 630 * Since we are u.u_procp, clock will normally just change 631 * our priority without moving us from one queue to another 632 * (since the running process is not on a queue.) 633 * If that happened after we setrq ourselves but before we 634 * swtch()'ed, we might not be on the queue indicated by 635 * our priority. 636 */ 637 (void) splclock(); 638 setrq(p); 639 u.u_ru.ru_nivcsw++; 640 swtch(); 641 if (code != SYS_sigreturn && (i = CURSIG(p))) 642 psig(i); 643 } 644 if (u.u_prof.pr_scale) { 645 int ticks; 646 struct timeval *tv = &u.u_ru.ru_stime; 647 648 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 649 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 650 if (ticks) { 651 #ifdef PROFTIMER 652 extern int profscale; 653 addupc(frame.f_pc, &u.u_prof, ticks * profscale); 654 #else 655 addupc(frame.f_pc, &u.u_prof, ticks); 656 #endif 657 } 658 } 659 curpri = p->p_pri; 660 #ifdef KTRACE 661 if (KTRPOINT(p, KTR_SYSRET)) 662 ktrsysret(p->p_tracep, code); 663 #endif 664 } 665