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.6 (Berkeley) 06/24/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 pagein(v, 0); 465 if (type == T_MMUFLT) 466 return; 467 goto out; 468 } 469 #ifdef DEBUG 470 printf("T_MMUFLT: unrecognized scenerio\n"); 471 goto dopanic; 472 #endif 473 } 474 trapsignal(i, ucode); 475 if ((type & USER) == 0) 476 return; 477 out: 478 p = u.u_procp; 479 if (i = CURSIG(p)) 480 psig(i); 481 p->p_pri = p->p_usrpri; 482 if (runrun) { 483 /* 484 * Since we are u.u_procp, clock will normally just change 485 * our priority without moving us from one queue to another 486 * (since the running process is not on a queue.) 487 * If that happened after we setrq ourselves but before we 488 * swtch()'ed, we might not be on the queue indicated by 489 * our priority. 490 */ 491 (void) splclock(); 492 setrq(p); 493 u.u_ru.ru_nivcsw++; 494 swtch(); 495 if (i = CURSIG(p)) 496 psig(i); 497 } 498 if (u.u_prof.pr_scale) { 499 int ticks; 500 struct timeval *tv = &u.u_ru.ru_stime; 501 502 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 503 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 504 if (ticks) { 505 #ifdef PROFTIMER 506 extern int profscale; 507 addupc(frame.f_pc, &u.u_prof, ticks * profscale); 508 #else 509 addupc(frame.f_pc, &u.u_prof, ticks); 510 #endif 511 } 512 } 513 curpri = p->p_pri; 514 } 515 516 /* 517 * Called from the trap handler when a system call occurs 518 */ 519 /*ARGSUSED*/ 520 syscall(code, frame) 521 volatile int code; 522 struct frame frame; 523 { 524 register caddr_t params; 525 register int i; 526 register struct sysent *callp; 527 register struct proc *p = u.u_procp; 528 int error, opc, numsys; 529 int args[8], rval[2]; 530 struct timeval syst; 531 struct sysent *systab; 532 #ifdef HPUXCOMPAT 533 extern struct sysent hpuxsysent[]; 534 extern int hpuxnsysent, notimp(); 535 #endif 536 537 cnt.v_syscall++; 538 syst = u.u_ru.ru_stime; 539 if (!USERMODE(frame.f_sr)) 540 panic("syscall"); 541 u.u_ar0 = frame.f_regs; 542 opc = frame.f_pc - 2; 543 systab = sysent; 544 numsys = nsysent; 545 #ifdef HPUXCOMPAT 546 if (p->p_flag & SHPUX) { 547 systab = hpuxsysent; 548 numsys = hpuxnsysent; 549 } 550 #endif 551 params = (caddr_t)frame.f_regs[SP] + NBPW; 552 if (code == 0) { /* indir */ 553 code = fuword(params); 554 params += NBPW; 555 } 556 if (code >= numsys) 557 callp = &systab[0]; /* indir (illegal) */ 558 else 559 callp = &systab[code]; 560 if ((i = callp->sy_narg * sizeof (int)) && 561 (error = copyin(params, (caddr_t)args, (u_int)i))) { 562 #ifdef HPUXCOMPAT 563 if (p->p_flag & SHPUX) 564 error = bsdtohpuxerrno(error); 565 #endif 566 frame.f_regs[D0] = (u_char) error; 567 frame.f_sr |= PSL_C; /* carry bit */ 568 #ifdef KTRACE 569 if (KTRPOINT(p, KTR_SYSCALL)) 570 ktrsyscall(p->p_tracep, code, callp->sy_narg, args); 571 #endif 572 goto done; 573 } 574 #ifdef KTRACE 575 if (KTRPOINT(p, KTR_SYSCALL)) 576 ktrsyscall(p->p_tracep, code, callp->sy_narg, args); 577 #endif 578 rval[0] = 0; 579 rval[1] = frame.f_regs[D1]; 580 #ifdef HPUXCOMPAT 581 /* debug kludge */ 582 if (callp->sy_call == notimp) 583 error = notimp(u.u_procp, args, rval, code, callp->sy_narg); 584 else 585 #endif 586 error = (*callp->sy_call)(u.u_procp, args, rval); 587 if (error == ERESTART) 588 frame.f_pc = opc; 589 else if (error != EJUSTRETURN) { 590 if (error) { 591 #ifdef HPUXCOMPAT 592 if (p->p_flag & SHPUX) 593 error = bsdtohpuxerrno(error); 594 #endif 595 frame.f_regs[D0] = (u_char) error; 596 frame.f_sr |= PSL_C; /* carry bit */ 597 } else { 598 frame.f_regs[D0] = rval[0]; 599 frame.f_regs[D1] = rval[1]; 600 frame.f_sr &= ~PSL_C; 601 } 602 } 603 /* else if (error == EJUSTRETURN) */ 604 /* nothing to do */ 605 606 done: 607 /* 608 * Reinitialize proc pointer `p' as it may be different 609 * if this is a child returning from fork syscall. 610 */ 611 p = u.u_procp; 612 /* 613 * XXX the check for sigreturn ensures that we don't 614 * attempt to set up a call to a signal handler (sendsig) before 615 * we have cleaned up the stack from the last call (sigreturn). 616 * Allowing this seems to lock up the machine in certain scenarios. 617 * What should really be done is to clean up the signal handling 618 * so that this is not a problem. 619 */ 620 #include "syscall.h" 621 if (code != SYS_sigreturn && (i = CURSIG(p))) 622 psig(i); 623 p->p_pri = p->p_usrpri; 624 if (runrun) { 625 /* 626 * Since we are u.u_procp, clock will normally just change 627 * our priority without moving us from one queue to another 628 * (since the running process is not on a queue.) 629 * If that happened after we setrq ourselves but before we 630 * swtch()'ed, we might not be on the queue indicated by 631 * our priority. 632 */ 633 (void) splclock(); 634 setrq(p); 635 u.u_ru.ru_nivcsw++; 636 swtch(); 637 if (code != SYS_sigreturn && (i = CURSIG(p))) 638 psig(i); 639 } 640 if (u.u_prof.pr_scale) { 641 int ticks; 642 struct timeval *tv = &u.u_ru.ru_stime; 643 644 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 645 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 646 if (ticks) { 647 #ifdef PROFTIMER 648 extern int profscale; 649 addupc(frame.f_pc, &u.u_prof, ticks * profscale); 650 #else 651 addupc(frame.f_pc, &u.u_prof, ticks); 652 #endif 653 } 654 } 655 curpri = p->p_pri; 656 #ifdef KTRACE 657 if (KTRPOINT(p, KTR_SYSRET)) 658 ktrsysret(p->p_tracep, code, error, rval[0]); 659 #endif 660 } 661