1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1982, 1986, 1990, 1993 4 * The Regents of the University of California. 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.37 92/12/20$ 13 * 14 * @(#)trap.c 8.6 (Berkeley) 06/01/94 15 */ 16 17 #include <sys/param.h> 18 #include <sys/systm.h> 19 #include <sys/proc.h> 20 #include <sys/acct.h> 21 #include <sys/kernel.h> 22 #include <sys/signalvar.h> 23 #include <sys/resourcevar.h> 24 #include <sys/syscall.h> 25 #include <sys/syslog.h> 26 #include <sys/user.h> 27 #ifdef KTRACE 28 #include <sys/ktrace.h> 29 #endif 30 31 #include <machine/psl.h> 32 #include <machine/trap.h> 33 #include <machine/cpu.h> 34 #include <machine/reg.h> 35 #include <machine/mtpr.h> 36 37 #include <vm/vm.h> 38 #include <vm/pmap.h> 39 40 #ifdef HPUXCOMPAT 41 #include <hp/hpux/hpux.h> 42 #endif 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 #ifdef HP380 83 #define KDFAULT(c) (mmutype == MMU_68040 ? \ 84 ((c) & SSW4_TMMASK) == SSW4_TMKD : \ 85 ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)) 86 #define WRFAULT(c) (mmutype == MMU_68040 ? \ 87 ((c) & SSW4_RW) == 0 : \ 88 ((c) & (SSW_DF|SSW_RW)) == SSW_DF) 89 #else 90 #define KDFAULT(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 91 #define WRFAULT(c) (((c) & (SSW_DF|SSW_RW)) == SSW_DF) 92 #endif 93 94 #ifdef DEBUG 95 int mmudebug = 0; 96 int mmupid = -1; 97 #define MDB_FOLLOW 1 98 #define MDB_WBFOLLOW 2 99 #define MDB_WBFAILED 4 100 #define MDB_ISPID(p) (p) == mmupid 101 #endif 102 103 /* 104 * trap and syscall both need the following work done before returning 105 * to user mode. 106 */ 107 static inline void 108 userret(p, fp, oticks, faultaddr, fromtrap) 109 register struct proc *p; 110 register struct frame *fp; 111 u_quad_t oticks; 112 u_int faultaddr; 113 int fromtrap; 114 { 115 int sig, s; 116 #ifdef HP380 117 int beenhere = 0; 118 119 again: 120 #endif 121 /* take pending signals */ 122 while ((sig = CURSIG(p)) != 0) 123 postsig(sig); 124 p->p_priority = p->p_usrpri; 125 if (want_resched) { 126 /* 127 * Since we are curproc, clock will normally just change 128 * our priority without moving us from one queue to another 129 * (since the running process is not on a queue.) 130 * If that happened after we put ourselves on the run queue 131 * but before we mi_switch()'ed, we might not be on the queue 132 * indicated by our priority. 133 */ 134 s = splstatclock(); 135 setrunqueue(p); 136 p->p_stats->p_ru.ru_nivcsw++; 137 mi_switch(); 138 splx(s); 139 while ((sig = CURSIG(p)) != 0) 140 postsig(sig); 141 } 142 143 /* 144 * If profiling, charge system time to the trapped pc. 145 */ 146 if (p->p_flag & P_PROFIL) { 147 extern int psratio; 148 149 addupc_task(p, fp->f_pc, 150 (int)(p->p_sticks - oticks) * psratio); 151 } 152 #ifdef HP380 153 /* 154 * Deal with user mode writebacks (from trap, or from sigreturn). 155 * If any writeback fails, go back and attempt signal delivery. 156 * unless we have already been here and attempted the writeback 157 * (e.g. bad address with user ignoring SIGSEGV). In that case 158 * we just return to the user without sucessfully completing 159 * the writebacks. Maybe we should just drop the sucker? 160 */ 161 if (mmutype == MMU_68040 && fp->f_format == FMT7) { 162 if (beenhere) { 163 #ifdef DEBUG 164 if (mmudebug & MDB_WBFAILED) 165 printf(fromtrap ? 166 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 167 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 168 p->p_pid, p->p_comm, fp->f_pc, faultaddr); 169 #endif 170 } else if (sig = writeback(fp, fromtrap)) { 171 beenhere = 1; 172 oticks = p->p_sticks; 173 trapsignal(p, sig, faultaddr); 174 goto again; 175 } 176 } 177 #endif 178 curpriority = p->p_priority; 179 } 180 181 /* 182 * Trap is called from locore to handle most types of processor traps, 183 * including events such as simulated software interrupts/AST's. 184 * System calls are broken out for efficiency. 185 */ 186 /*ARGSUSED*/ 187 trap(type, code, v, frame) 188 int type; 189 unsigned code; 190 register unsigned v; 191 struct frame frame; 192 { 193 extern char fswintr[]; 194 register struct proc *p; 195 register int i; 196 u_int ucode; 197 u_quad_t sticks; 198 199 cnt.v_trap++; 200 p = curproc; 201 ucode = 0; 202 if (USERMODE(frame.f_sr)) { 203 type |= T_USER; 204 sticks = p->p_sticks; 205 p->p_md.md_regs = frame.f_regs; 206 } 207 switch (type) { 208 209 default: 210 dopanic: 211 printf("trap type %d, code = %x, v = %x\n", type, code, v); 212 regdump(&frame, 128); 213 type &= ~T_USER; 214 if ((unsigned)type < TRAP_TYPES) 215 panic(trap_type[type]); 216 panic("trap"); 217 218 case T_BUSERR: /* kernel bus error */ 219 if (!p->p_addr->u_pcb.pcb_onfault) 220 goto dopanic; 221 /* 222 * If we have arranged to catch this fault in any of the 223 * copy to/from user space routines, set PC to return to 224 * indicated location and set flag informing buserror code 225 * that it may need to clean up stack frame. 226 */ 227 copyfault: 228 frame.f_stackadj = exframesize[frame.f_format]; 229 frame.f_format = frame.f_vector = 0; 230 frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 231 return; 232 233 case T_BUSERR|T_USER: /* bus error */ 234 case T_ADDRERR|T_USER: /* address error */ 235 ucode = v; 236 i = SIGBUS; 237 break; 238 239 #ifdef HP380 240 case T_ADDRERR: 241 /* 242 * Yow! Looks like we get a kernel exception if the PC 243 * in the RTE frame is odd on a 68040 (not on a 68030). 244 * It comes through as a user exception for access faults 245 * (T_MMUFLT). 246 */ 247 if (*(short *)frame.f_pc != 0x4e73) 248 goto dopanic; 249 /* fall through */ 250 #endif 251 252 #ifdef FPCOPROC 253 case T_COPERR: /* kernel coprocessor violation */ 254 #endif 255 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 256 case T_FMTERR: /* ...just in case... */ 257 /* 258 * The user has most likely trashed the RTE or FP state info 259 * in the stack frame of a signal handler. 260 */ 261 type |= T_USER; 262 printf("pid %d: kernel %s exception\n", p->p_pid, 263 (type==T_COPERR|T_USER) ? "coprocessor" : 264 (type==T_ADDRERR|T_USER) ? "RTE address" : 265 "RTE format"); 266 p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL; 267 i = sigmask(SIGILL); 268 p->p_sigignore &= ~i; 269 p->p_sigcatch &= ~i; 270 p->p_sigmask &= ~i; 271 i = SIGILL; 272 ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 273 break; 274 275 #ifdef FPCOPROC 276 case T_COPERR|T_USER: /* user coprocessor violation */ 277 /* What is a proper response here? */ 278 ucode = 0; 279 i = SIGFPE; 280 break; 281 282 case T_FPERR|T_USER: /* 68881 exceptions */ 283 /* 284 * We pass along the 68881 status register which locore stashed 285 * in code for us. Note that there is a possibility that the 286 * bit pattern of this register will conflict with one of the 287 * FPE_* codes defined in signal.h. Fortunately for us, the 288 * only such codes we use are all in the range 1-7 and the low 289 * 3 bits of the status register are defined as 0 so there is 290 * no clash. 291 */ 292 ucode = code; 293 i = SIGFPE; 294 break; 295 #endif 296 297 #ifdef HP380 298 case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 299 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 300 /* XXX need to FSAVE */ 301 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 302 p->p_pid, p->p_comm, 303 frame.f_format == 2 ? "instruction" : "data type", 304 frame.f_pc, frame.f_fmt2.f_iaddr); 305 /* XXX need to FRESTORE */ 306 i = SIGFPE; 307 break; 308 #endif 309 310 case T_ILLINST|T_USER: /* illegal instruction fault */ 311 #ifdef HPUXCOMPAT 312 if (p->p_md.md_flags & MDP_HPUX) { 313 ucode = HPUX_ILL_ILLINST_TRAP; 314 i = SIGILL; 315 break; 316 } 317 /* fall through */ 318 #endif 319 case T_PRIVINST|T_USER: /* privileged instruction fault */ 320 #ifdef HPUXCOMPAT 321 if (p->p_md.md_flags & MDP_HPUX) 322 ucode = HPUX_ILL_PRIV_TRAP; 323 else 324 #endif 325 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 326 i = SIGILL; 327 break; 328 329 case T_ZERODIV|T_USER: /* Divide by zero */ 330 #ifdef HPUXCOMPAT 331 if (p->p_md.md_flags & MDP_HPUX) 332 ucode = HPUX_FPE_INTDIV_TRAP; 333 else 334 #endif 335 ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 336 i = SIGFPE; 337 break; 338 339 case T_CHKINST|T_USER: /* CHK instruction trap */ 340 #ifdef HPUXCOMPAT 341 if (p->p_md.md_flags & MDP_HPUX) { 342 /* handled differently under hp-ux */ 343 i = SIGILL; 344 ucode = HPUX_ILL_CHK_TRAP; 345 break; 346 } 347 #endif 348 ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 349 i = SIGFPE; 350 break; 351 352 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 353 #ifdef HPUXCOMPAT 354 if (p->p_md.md_flags & MDP_HPUX) { 355 /* handled differently under hp-ux */ 356 i = SIGILL; 357 ucode = HPUX_ILL_TRAPV_TRAP; 358 break; 359 } 360 #endif 361 ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 362 i = SIGFPE; 363 break; 364 365 /* 366 * XXX: Trace traps are a nightmare. 367 * 368 * HP-UX uses trap #1 for breakpoints, 369 * HPBSD uses trap #2, 370 * SUN 3.x uses trap #15, 371 * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). 372 * 373 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 374 * SUN 3.x traps get passed through as T_TRAP15 and are not really 375 * supported yet. 376 */ 377 case T_TRACE: /* kernel trace trap */ 378 case T_TRAP15: /* SUN trace trap */ 379 frame.f_sr &= ~PSL_T; 380 i = SIGTRAP; 381 break; 382 383 case T_TRACE|T_USER: /* user trace trap */ 384 case T_TRAP15|T_USER: /* SUN user trace trap */ 385 frame.f_sr &= ~PSL_T; 386 i = SIGTRAP; 387 break; 388 389 case T_ASTFLT: /* system async trap, cannot happen */ 390 goto dopanic; 391 392 case T_ASTFLT|T_USER: /* user async trap */ 393 astpending = 0; 394 /* 395 * We check for software interrupts first. This is because 396 * they are at a higher level than ASTs, and on a VAX would 397 * interrupt the AST. We assume that if we are processing 398 * an AST that we must be at IPL0 so we don't bother to 399 * check. Note that we ensure that we are at least at SIR 400 * IPL while processing the SIR. 401 */ 402 spl1(); 403 /* fall into... */ 404 405 case T_SSIR: /* software interrupt */ 406 case T_SSIR|T_USER: 407 if (ssir & SIR_NET) { 408 siroff(SIR_NET); 409 cnt.v_soft++; 410 netintr(); 411 } 412 if (ssir & SIR_CLOCK) { 413 siroff(SIR_CLOCK); 414 cnt.v_soft++; 415 softclock(); 416 } 417 /* 418 * If this was not an AST trap, we are all done. 419 */ 420 if (type != (T_ASTFLT|T_USER)) { 421 cnt.v_trap--; 422 return; 423 } 424 spl0(); 425 if (p->p_flag & P_OWEUPC) { 426 p->p_flag &= ~P_OWEUPC; 427 ADDUPROF(p); 428 } 429 goto out; 430 431 case T_MMUFLT: /* kernel mode page fault */ 432 /* 433 * If we were doing profiling ticks or other user mode 434 * stuff from interrupt code, Just Say No. 435 */ 436 if (p->p_addr->u_pcb.pcb_onfault == fswintr) 437 goto copyfault; 438 /* fall into ... */ 439 440 case T_MMUFLT|T_USER: /* page fault */ 441 { 442 register vm_offset_t va; 443 register struct vmspace *vm = p->p_vmspace; 444 register vm_map_t map; 445 int rv; 446 vm_prot_t ftype; 447 extern vm_map_t kernel_map; 448 449 #ifdef DEBUG 450 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 451 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 452 p->p_pid, code, v, frame.f_pc, frame.f_sr); 453 #endif 454 /* 455 * It is only a kernel address space fault iff: 456 * 1. (type & T_USER) == 0 and 457 * 2. pcb_onfault not set or 458 * 3. pcb_onfault set but supervisor space data fault 459 * The last can occur during an exec() copyin where the 460 * argument space is lazy-allocated. 461 */ 462 if (type == T_MMUFLT && 463 (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code))) 464 map = kernel_map; 465 else 466 map = &vm->vm_map; 467 if (WRFAULT(code)) 468 ftype = VM_PROT_READ | VM_PROT_WRITE; 469 else 470 ftype = VM_PROT_READ; 471 va = trunc_page((vm_offset_t)v); 472 #ifdef DEBUG 473 if (map == kernel_map && va == 0) { 474 printf("trap: bad kernel access at %x\n", v); 475 goto dopanic; 476 } 477 #endif 478 #ifdef HPUXCOMPAT 479 if (ISHPMMADDR(va)) { 480 vm_offset_t bva; 481 482 rv = pmap_mapmulti(map->pmap, va); 483 if (rv != KERN_SUCCESS) { 484 bva = HPMMBASEADDR(va); 485 rv = vm_fault(map, bva, ftype, FALSE); 486 if (rv == KERN_SUCCESS) 487 (void) pmap_mapmulti(map->pmap, va); 488 } 489 } else 490 #endif 491 rv = vm_fault(map, va, ftype, FALSE); 492 #ifdef DEBUG 493 if (rv && MDB_ISPID(p->p_pid)) 494 printf("vm_fault(%x, %x, %x, 0) -> %x\n", 495 map, va, ftype, rv); 496 #endif 497 /* 498 * If this was a stack access we keep track of the maximum 499 * accessed stack size. Also, if vm_fault gets a protection 500 * failure it is due to accessing the stack region outside 501 * the current limit and we need to reflect that as an access 502 * error. 503 */ 504 if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) { 505 if (rv == KERN_SUCCESS) { 506 unsigned nss; 507 508 nss = clrnd(btoc(USRSTACK-(unsigned)va)); 509 if (nss > vm->vm_ssize) 510 vm->vm_ssize = nss; 511 } else if (rv == KERN_PROTECTION_FAILURE) 512 rv = KERN_INVALID_ADDRESS; 513 } 514 if (rv == KERN_SUCCESS) { 515 if (type == T_MMUFLT) { 516 #ifdef HP380 517 if (mmutype == MMU_68040) 518 (void) writeback(&frame, 1); 519 #endif 520 return; 521 } 522 goto out; 523 } 524 if (type == T_MMUFLT) { 525 if (p->p_addr->u_pcb.pcb_onfault) 526 goto copyfault; 527 printf("vm_fault(%x, %x, %x, 0) -> %x\n", 528 map, va, ftype, rv); 529 printf(" type %x, code [mmu,,ssw]: %x\n", 530 type, code); 531 goto dopanic; 532 } 533 ucode = v; 534 i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; 535 break; 536 } 537 } 538 trapsignal(p, i, ucode); 539 if ((type & T_USER) == 0) 540 return; 541 out: 542 userret(p, &frame, sticks, v, 1); 543 } 544 545 #ifdef HP380 546 #ifdef DEBUG 547 struct writebackstats { 548 int calls; 549 int cpushes; 550 int move16s; 551 int wb1s, wb2s, wb3s; 552 int wbsize[4]; 553 } wbstats; 554 555 char *f7sz[] = { "longword", "byte", "word", "line" }; 556 char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 557 char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 558 "M-code", "k-data", "k-code", "RES" }; 559 char wberrstr[] = 560 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 561 #endif 562 563 writeback(fp, docachepush) 564 struct frame *fp; 565 int docachepush; 566 { 567 register struct fmt7 *f = &fp->f_fmt7; 568 register struct proc *p = curproc; 569 int err = 0; 570 u_int fa; 571 caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault; 572 573 #ifdef DEBUG 574 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 575 printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 576 dumpssw(f->f_ssw); 577 } 578 wbstats.calls++; 579 #endif 580 /* 581 * Deal with special cases first. 582 */ 583 if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 584 /* 585 * Dcache push fault. 586 * Line-align the address and write out the push data to 587 * the indicated physical address. 588 */ 589 #ifdef DEBUG 590 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 591 printf(" pushing %s to PA %x, data %x", 592 f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 593 f->f_fa, f->f_pd0); 594 if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 595 printf("/%x/%x/%x", 596 f->f_pd1, f->f_pd2, f->f_pd3); 597 printf("\n"); 598 } 599 if (f->f_wb1s & SSW4_WBSV) 600 panic("writeback: cache push with WB1S valid"); 601 wbstats.cpushes++; 602 #endif 603 /* 604 * XXX there are security problems if we attempt to do a 605 * cache push after a signal handler has been called. 606 */ 607 if (docachepush) { 608 pmap_enter(kernel_pmap, (vm_offset_t)vmmap, 609 trunc_page(f->f_fa), VM_PROT_WRITE, TRUE); 610 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 611 bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16); 612 DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa)); 613 pmap_remove(kernel_pmap, (vm_offset_t)vmmap, 614 (vm_offset_t)&vmmap[NBPG]); 615 } else 616 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 617 p->p_pid, p->p_comm, p->p_ucred->cr_uid); 618 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 619 /* 620 * MOVE16 fault. 621 * Line-align the address and write out the push data to 622 * the indicated virtual address. 623 */ 624 #ifdef DEBUG 625 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 626 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 627 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 628 f->f_pd2, f->f_pd3); 629 if (f->f_wb1s & SSW4_WBSV) 630 panic("writeback: MOVE16 with WB1S valid"); 631 wbstats.move16s++; 632 #endif 633 if (KDFAULT(f->f_wb1s)) 634 bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16); 635 else 636 err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); 637 if (err) { 638 fa = f->f_fa & ~0xF; 639 #ifdef DEBUG 640 if (mmudebug & MDB_WBFAILED) 641 printf(wberrstr, p->p_pid, p->p_comm, 642 "MOVE16", fp->f_pc, f->f_fa, 643 f->f_fa & ~0xF, f->f_pd0); 644 #endif 645 } 646 } else if (f->f_wb1s & SSW4_WBSV) { 647 /* 648 * Writeback #1. 649 * Position the "memory-aligned" data and write it out. 650 */ 651 register u_int wb1d = f->f_wb1d; 652 register int off; 653 654 #ifdef DEBUG 655 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 656 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 657 wbstats.wb1s++; 658 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 659 #endif 660 off = (f->f_wb1a & 3) * 8; 661 switch (f->f_wb1s & SSW4_SZMASK) { 662 case SSW4_SZLW: 663 if (off) 664 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 665 if (KDFAULT(f->f_wb1s)) 666 *(long *)f->f_wb1a = wb1d; 667 else 668 err = suword((caddr_t)f->f_wb1a, wb1d); 669 break; 670 case SSW4_SZB: 671 off = 24 - off; 672 if (off) 673 wb1d >>= off; 674 if (KDFAULT(f->f_wb1s)) 675 *(char *)f->f_wb1a = wb1d; 676 else 677 err = subyte((caddr_t)f->f_wb1a, wb1d); 678 break; 679 case SSW4_SZW: 680 off = (off + 16) % 32; 681 if (off) 682 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 683 if (KDFAULT(f->f_wb1s)) 684 *(short *)f->f_wb1a = wb1d; 685 else 686 err = susword((caddr_t)f->f_wb1a, wb1d); 687 break; 688 } 689 if (err) { 690 fa = f->f_wb1a; 691 #ifdef DEBUG 692 if (mmudebug & MDB_WBFAILED) 693 printf(wberrstr, p->p_pid, p->p_comm, 694 "#1", fp->f_pc, f->f_fa, 695 f->f_wb1a, f->f_wb1d); 696 #endif 697 } 698 } 699 /* 700 * Deal with the "normal" writebacks. 701 * 702 * XXX writeback2 is known to reflect a LINE size writeback after 703 * a MOVE16 was already dealt with above. Ignore it. 704 */ 705 if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 706 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 707 #ifdef DEBUG 708 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 709 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 710 wbstats.wb2s++; 711 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 712 #endif 713 switch (f->f_wb2s & SSW4_SZMASK) { 714 case SSW4_SZLW: 715 if (KDFAULT(f->f_wb2s)) 716 *(long *)f->f_wb2a = f->f_wb2d; 717 else 718 err = suword((caddr_t)f->f_wb2a, f->f_wb2d); 719 break; 720 case SSW4_SZB: 721 if (KDFAULT(f->f_wb2s)) 722 *(char *)f->f_wb2a = f->f_wb2d; 723 else 724 err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); 725 break; 726 case SSW4_SZW: 727 if (KDFAULT(f->f_wb2s)) 728 *(short *)f->f_wb2a = f->f_wb2d; 729 else 730 err = susword((caddr_t)f->f_wb2a, f->f_wb2d); 731 break; 732 } 733 if (err) { 734 fa = f->f_wb2a; 735 #ifdef DEBUG 736 if (mmudebug & MDB_WBFAILED) { 737 printf(wberrstr, p->p_pid, p->p_comm, 738 "#2", fp->f_pc, f->f_fa, 739 f->f_wb2a, f->f_wb2d); 740 dumpssw(f->f_ssw); 741 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 742 } 743 #endif 744 } 745 } 746 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 747 #ifdef DEBUG 748 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 749 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 750 wbstats.wb3s++; 751 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 752 #endif 753 switch (f->f_wb3s & SSW4_SZMASK) { 754 case SSW4_SZLW: 755 if (KDFAULT(f->f_wb3s)) 756 *(long *)f->f_wb3a = f->f_wb3d; 757 else 758 err = suword((caddr_t)f->f_wb3a, f->f_wb3d); 759 break; 760 case SSW4_SZB: 761 if (KDFAULT(f->f_wb3s)) 762 *(char *)f->f_wb3a = f->f_wb3d; 763 else 764 err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); 765 break; 766 case SSW4_SZW: 767 if (KDFAULT(f->f_wb3s)) 768 *(short *)f->f_wb3a = f->f_wb3d; 769 else 770 err = susword((caddr_t)f->f_wb3a, f->f_wb3d); 771 break; 772 #ifdef DEBUG 773 case SSW4_SZLN: 774 panic("writeback: wb3s indicates LINE write"); 775 #endif 776 } 777 if (err) { 778 fa = f->f_wb3a; 779 #ifdef DEBUG 780 if (mmudebug & MDB_WBFAILED) 781 printf(wberrstr, p->p_pid, p->p_comm, 782 "#3", fp->f_pc, f->f_fa, 783 f->f_wb3a, f->f_wb3d); 784 #endif 785 } 786 } 787 p->p_addr->u_pcb.pcb_onfault = oonfault; 788 /* 789 * Determine the cause of the failure if any translating to 790 * a signal. If the corresponding VA is valid and RO it is 791 * a protection fault (SIGBUS) otherwise consider it an 792 * illegal reference (SIGSEGV). 793 */ 794 if (err) { 795 if (vm_map_check_protection(&p->p_vmspace->vm_map, 796 trunc_page(fa), round_page(fa), 797 VM_PROT_READ) && 798 !vm_map_check_protection(&p->p_vmspace->vm_map, 799 trunc_page(fa), round_page(fa), 800 VM_PROT_WRITE)) 801 err = SIGBUS; 802 else 803 err = SIGSEGV; 804 } 805 return(err); 806 } 807 808 #ifdef DEBUG 809 dumpssw(ssw) 810 register u_short ssw; 811 { 812 printf(" SSW: %x: ", ssw); 813 if (ssw & SSW4_CP) 814 printf("CP,"); 815 if (ssw & SSW4_CU) 816 printf("CU,"); 817 if (ssw & SSW4_CT) 818 printf("CT,"); 819 if (ssw & SSW4_CM) 820 printf("CM,"); 821 if (ssw & SSW4_MA) 822 printf("MA,"); 823 if (ssw & SSW4_ATC) 824 printf("ATC,"); 825 if (ssw & SSW4_LK) 826 printf("LK,"); 827 if (ssw & SSW4_RW) 828 printf("RW,"); 829 printf(" SZ=%s, TT=%s, TM=%s\n", 830 f7sz[(ssw & SSW4_SZMASK) >> 5], 831 f7tt[(ssw & SSW4_TTMASK) >> 3], 832 f7tm[ssw & SSW4_TMMASK]); 833 } 834 835 dumpwb(num, s, a, d) 836 int num; 837 u_short s; 838 u_int a, d; 839 { 840 register struct proc *p = curproc; 841 vm_offset_t pa; 842 843 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 844 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 845 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 846 printf(" PA "); 847 pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a); 848 if (pa == 0) 849 printf("<invalid address>"); 850 else 851 printf("%x, current value %x", pa, fuword((caddr_t)a)); 852 printf("\n"); 853 } 854 #endif 855 #endif 856 857 /* 858 * Proces a system call. 859 */ 860 syscall(code, frame) 861 u_int code; 862 struct frame frame; 863 { 864 register caddr_t params; 865 register struct sysent *callp; 866 register struct proc *p; 867 int error, opc, numsys; 868 u_int argsize; 869 struct args { 870 int i[8]; 871 } args; 872 int rval[2]; 873 u_quad_t sticks; 874 #ifdef HPUXCOMPAT 875 extern struct sysent hpuxsysent[]; 876 extern int hpuxnsysent, notimp(); 877 #endif 878 879 cnt.v_syscall++; 880 if (!USERMODE(frame.f_sr)) 881 panic("syscall"); 882 p = curproc; 883 sticks = p->p_sticks; 884 p->p_md.md_regs = frame.f_regs; 885 opc = frame.f_pc - 2; 886 #ifdef HPUXCOMPAT 887 if (p->p_md.md_flags & MDP_HPUX) 888 callp = hpuxsysent, numsys = hpuxnsysent; 889 else 890 #endif 891 callp = sysent, numsys = nsysent; 892 params = (caddr_t)frame.f_regs[SP] + sizeof(int); 893 switch (code) { 894 895 case SYS_syscall: 896 /* 897 * Code is first argument, followed by actual args. 898 */ 899 code = fuword(params); 900 params += sizeof(int); 901 /* 902 * XXX sigreturn requires special stack manipulation 903 * that is only done if entered via the sigreturn 904 * trap. Cannot allow it here so make sure we fail. 905 */ 906 if (code == SYS_sigreturn) 907 code = numsys; 908 break; 909 910 case SYS___syscall: 911 /* 912 * Like syscall, but code is a quad, so as to maintain 913 * quad alignment for the rest of the arguments. 914 */ 915 #ifdef HPUXCOMPAT 916 if (p->p_md.md_flags & MDP_HPUX) 917 break; 918 #endif 919 code = fuword(params + _QUAD_LOWWORD * sizeof(int)); 920 params += sizeof(quad_t); 921 break; 922 923 default: 924 /* nothing to do by default */ 925 break; 926 } 927 if (code < numsys) 928 callp += code; 929 else 930 callp += SYS_syscall; /* => nosys */ 931 argsize = callp->sy_narg * sizeof(int); 932 if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) { 933 #ifdef KTRACE 934 if (KTRPOINT(p, KTR_SYSCALL)) 935 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 936 #endif 937 goto bad; 938 } 939 #ifdef KTRACE 940 if (KTRPOINT(p, KTR_SYSCALL)) 941 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 942 #endif 943 rval[0] = 0; 944 rval[1] = frame.f_regs[D1]; 945 #ifdef HPUXCOMPAT 946 /* debug kludge */ 947 if (callp->sy_call == notimp) 948 error = notimp(p, args.i, rval, code, callp->sy_narg); 949 else 950 #endif 951 error = (*callp->sy_call)(p, &args, rval); 952 switch (error) { 953 954 case 0: 955 /* 956 * Reinitialize proc pointer `p' as it may be different 957 * if this is a child returning from fork syscall. 958 */ 959 p = curproc; 960 frame.f_regs[D0] = rval[0]; 961 frame.f_regs[D1] = rval[1]; 962 frame.f_sr &= ~PSL_C; 963 break; 964 965 case ERESTART: 966 frame.f_pc = opc; 967 break; 968 969 case EJUSTRETURN: 970 break; /* nothing to do */ 971 972 default: 973 bad: 974 #ifdef HPUXCOMPAT 975 if (p->p_md.md_flags & MDP_HPUX) 976 error = bsdtohpuxerrno(error); 977 #endif 978 frame.f_regs[D0] = error; 979 frame.f_sr |= PSL_C; 980 break; 981 } 982 983 userret(p, &frame, sticks, (u_int)0, 0); 984 #ifdef KTRACE 985 if (KTRPOINT(p, KTR_SYSRET)) 986 ktrsysret(p->p_tracep, code, error, rval[0]); 987 #endif 988 } 989