trap.c revision 1.35
1/* $NetBSD: trap.c,v 1.35 2001/09/10 21:19:21 chris Exp $ */ 2 3/* 4 * This file was taken from mvme68k/mvme68k/trap.c 5 * should probably be re-synced when needed. 6 * Darrin B. Jewell <jewell@mit.edu> Tue Aug 3 10:53:12 UTC 1999 7 * original cvs id: NetBSD: trap.c,v 1.32 1999/08/03 10:52:06 dbj Exp 8 */ 9 10/* 11 * Copyright (c) 1988 University of Utah. 12 * Copyright (c) 1982, 1986, 1990, 1993 13 * The Regents of the University of California. All rights reserved. 14 * 15 * This code is derived from software contributed to Berkeley by 16 * the Systems Programming Group of the University of Utah Computer 17 * Science Department. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 1. Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 3. All advertising materials mentioning features or use of this software 28 * must display the following acknowledgement: 29 * This product includes software developed by the University of 30 * California, Berkeley and its contributors. 31 * 4. Neither the name of the University nor the names of its contributors 32 * may be used to endorse or promote products derived from this software 33 * without specific prior written permission. 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 * SUCH DAMAGE. 46 * 47 * from: Utah $Hdr: trap.c 1.37 92/12/20$ 48 * 49 * @(#)trap.c 8.5 (Berkeley) 1/4/94 50 */ 51 52#include "opt_ddb.h" 53#include "opt_execfmt.h" 54#include "opt_kgdb.h" 55#include "opt_compat_sunos.h" 56#include "opt_compat_hpux.h" 57 58#include <sys/param.h> 59#include <sys/systm.h> 60#include <sys/proc.h> 61#include <sys/acct.h> 62#include <sys/kernel.h> 63#include <sys/signalvar.h> 64#include <sys/resourcevar.h> 65#include <sys/syscall.h> 66#include <sys/syslog.h> 67#include <sys/user.h> 68 69#ifdef DEBUG 70#include <dev/cons.h> 71#endif 72 73#include <machine/db_machdep.h> 74#include <machine/psl.h> 75#include <machine/trap.h> 76#include <machine/cpu.h> 77#include <machine/reg.h> 78 79#include <m68k/cacheops.h> 80 81#include <uvm/uvm_extern.h> 82 83#ifdef COMPAT_HPUX 84#include <compat/hpux/hpux.h> 85#endif 86 87#ifdef COMPAT_SUNOS 88#include <compat/sunos/sunos_syscall.h> 89extern struct emul emul_sunos; 90#endif 91 92int writeback __P((struct frame *fp, int docachepush)); 93void trap __P((int type, u_int code, u_int v, struct frame frame)); 94 95#ifdef DEBUG 96void dumpssw __P((u_short)); 97void dumpwb __P((int, u_short, u_int, u_int)); 98#endif 99 100static inline void userret __P((struct proc *p, struct frame *fp, 101 u_quad_t oticks, u_int faultaddr, int fromtrap)); 102 103int astpending; 104 105char *trap_type[] = { 106 "Bus error", 107 "Address error", 108 "Illegal instruction", 109 "Zero divide", 110 "CHK instruction", 111 "TRAPV instruction", 112 "Privilege violation", 113 "Trace trap", 114 "MMU fault", 115 "SSIR trap", 116 "Format error", 117 "68881 exception", 118 "Coprocessor violation", 119 "Async system trap" 120}; 121int trap_types = sizeof trap_type / sizeof trap_type[0]; 122 123/* 124 * Size of various exception stack frames (minus the standard 8 bytes) 125 */ 126short exframesize[] = { 127 FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 128 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 129 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 130 FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 131 FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 132 -1, -1, /* type 5-6 - undefined */ 133 FMT7SIZE, /* type 7 - access error (68040) */ 134 58, /* type 8 - bus fault (68010) */ 135 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 136 FMTASIZE, /* type A - short bus fault (68020/030) */ 137 FMTBSIZE, /* type B - long bus fault (68020/030) */ 138 -1, -1, -1, -1 /* type C-F - undefined */ 139}; 140 141#ifdef M68060 142#define KDFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_TM_SV)) 143#define WRFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_RW_W)) 144#else 145#define KDFAULT_060(c) 0 146#define WRFAULT_060(c) 0 147#endif 148 149#ifdef M68040 150#define KDFAULT_040(c) (cputype == CPU_68040 && \ 151 ((c) & SSW4_TMMASK) == SSW4_TMKD) 152#define WRFAULT_040(c) (cputype == CPU_68040 && \ 153 ((c) & SSW4_RW) == 0) 154#else 155#define KDFAULT_040(c) 0 156#define WRFAULT_040(c) 0 157#endif 158 159#if defined(M68030) || defined(M68020) 160#define KDFAULT_OTH(c) (cputype <= CPU_68030 && \ 161 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 162#define WRFAULT_OTH(c) (cputype <= CPU_68030 && \ 163 ((c) & (SSW_DF|SSW_RW)) == SSW_DF) 164#else 165#define KDFAULT_OTH(c) 0 166#define WRFAULT_OTH(c) 0 167#endif 168 169#define KDFAULT(c) (KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c)) 170#define WRFAULT(c) (WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c)) 171 172#ifdef DEBUG 173int mmudebug = 0; 174int mmupid = -1; 175#define MDB_FOLLOW 1 176#define MDB_WBFOLLOW 2 177#define MDB_WBFAILED 4 178#define MDB_ISPID(p) ((p) == mmupid) 179#endif 180 181 182#define NSIR 32 183void (*sir_routines[NSIR])(void *); 184void *sir_args[NSIR]; 185int next_sir; 186 187/* 188 * trap and syscall both need the following work done before returning 189 * to user mode. 190 */ 191static inline void 192userret(p, fp, oticks, faultaddr, fromtrap) 193 struct proc *p; 194 struct frame *fp; 195 u_quad_t oticks; 196 u_int faultaddr; 197 int fromtrap; 198{ 199 int sig; 200#ifdef M68040 201 int beenhere = 0; 202 203again: 204#endif 205 /* take pending signals */ 206 while ((sig = CURSIG(p)) != 0) 207 postsig(sig); 208 p->p_priority = p->p_usrpri; 209 if (want_resched) { 210 /* 211 * We are being preempted. 212 */ 213 preempt(NULL); 214 while ((sig = CURSIG(p)) != 0) 215 postsig(sig); 216 } 217 218 /* 219 * If profiling, charge system time to the trapped pc. 220 */ 221 if (p->p_flag & P_PROFIL) { 222 extern int psratio; 223 224 addupc_task(p, fp->f_pc, 225 (int)(p->p_sticks - oticks) * psratio); 226 } 227#ifdef M68040 228 /* 229 * Deal with user mode writebacks (from trap, or from sigreturn). 230 * If any writeback fails, go back and attempt signal delivery. 231 * unless we have already been here and attempted the writeback 232 * (e.g. bad address with user ignoring SIGSEGV). In that case 233 * we just return to the user without sucessfully completing 234 * the writebacks. Maybe we should just drop the sucker? 235 */ 236 if (cputype == CPU_68040 && fp->f_format == FMT7) { 237 if (beenhere) { 238#ifdef DEBUG 239 if (mmudebug & MDB_WBFAILED) 240 printf(fromtrap ? 241 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 242 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 243 p->p_pid, p->p_comm, fp->f_pc, faultaddr); 244#endif 245 } else if ((sig = writeback(fp, fromtrap))) { 246 beenhere = 1; 247 oticks = p->p_sticks; 248 trapsignal(p, sig, faultaddr); 249 goto again; 250 } 251 } 252#endif 253 curcpu()->ci_schedstate.spc_curpriority = p->p_priority; 254} 255 256/* 257 * Used by the common m68k syscall() and child_return() functions. 258 * XXX: Temporary until all m68k ports share common trap()/userret() code. 259 */ 260void machine_userret(struct proc *, struct frame *, u_quad_t); 261 262void 263machine_userret(p, f, t) 264 struct proc *p; 265 struct frame *f; 266 u_quad_t t; 267{ 268 269 userret(p, f, t, 0, 0); 270} 271 272/* 273 * Trap is called from locore to handle most types of processor traps, 274 * including events such as simulated software interrupts/AST's. 275 * System calls are broken out for efficiency. 276 */ 277/*ARGSUSED*/ 278void 279trap(type, code, v, frame) 280 int type; 281 unsigned code; 282 unsigned v; 283 struct frame frame; 284{ 285 extern char fubail[], subail[]; 286 struct proc *p; 287 int i, s; 288 u_int ucode; 289 u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */; 290 int bit; 291 292 uvmexp.traps++; 293 p = curproc; 294 ucode = 0; 295 296 /* I have verified that this DOES happen! -gwr */ 297 if (p == NULL) 298 p = &proc0; 299#ifdef DIAGNOSTIC 300 if (p->p_addr == NULL) 301 panic("trap: no pcb"); 302#endif 303 304 if (USERMODE(frame.f_sr)) { 305 type |= T_USER; 306 sticks = p->p_sticks; 307 p->p_md.md_regs = frame.f_regs; 308 } 309 switch (type) { 310 311 default: 312 dopanic: 313 printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v); 314 printf("%s program counter = 0x%x\n", 315 (type & T_USER) ? "user" : "kernel", frame.f_pc); 316 /* 317 * Let the kernel debugger see the trap frame that 318 * caused us to panic. This is a convenience so 319 * one can see registers at the point of failure. 320 */ 321 s = splhigh(); 322#ifdef KGDB 323 /* If connected, step or cont returns 1 */ 324 if (kgdb_trap(type, &frame)) 325 goto kgdb_cont; 326#endif 327#ifdef DDB 328 (void)kdb_trap(type, (db_regs_t *)&frame); 329#endif 330#ifdef KGDB 331 kgdb_cont: 332#endif 333 splx(s); 334 if (panicstr) { 335 printf("trap during panic!\n"); 336#ifdef DEBUG 337 /* XXX should be a machine-dependent hook */ 338 printf("(press a key)\n"); (void)cngetc(); 339#endif 340 } 341 regdump((struct trapframe *)&frame, 128); 342 type &= ~T_USER; 343 if ((u_int)type < trap_types) 344 panic(trap_type[type]); 345 panic("trap"); 346 347 case T_BUSERR: /* kernel bus error */ 348 if (p->p_addr->u_pcb.pcb_onfault == 0) 349 goto dopanic; 350 /* FALLTHROUGH */ 351 352 copyfault: 353 /* 354 * If we have arranged to catch this fault in any of the 355 * copy to/from user space routines, set PC to return to 356 * indicated location and set flag informing buserror code 357 * that it may need to clean up stack frame. 358 */ 359 frame.f_stackadj = exframesize[frame.f_format]; 360 frame.f_format = frame.f_vector = 0; 361 frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 362 return; 363 364 case T_BUSERR|T_USER: /* bus error */ 365 case T_ADDRERR|T_USER: /* address error */ 366 ucode = v; 367 i = SIGBUS; 368 break; 369 370 case T_COPERR: /* kernel coprocessor violation */ 371 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 372 case T_FMTERR: /* ...just in case... */ 373 /* 374 * The user has most likely trashed the RTE or FP state info 375 * in the stack frame of a signal handler. 376 */ 377 printf("pid %d: kernel %s exception\n", p->p_pid, 378 type==T_COPERR ? "coprocessor" : "format"); 379 type |= T_USER; 380 SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 381 sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 382 sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 383 sigdelset(&p->p_sigctx.ps_sigmask, SIGILL); 384 i = SIGILL; 385 ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 386 break; 387 388 case T_COPERR|T_USER: /* user coprocessor violation */ 389 /* What is a proper response here? */ 390 ucode = 0; 391 i = SIGFPE; 392 break; 393 394 case T_FPERR|T_USER: /* 68881 exceptions */ 395 /* 396 * We pass along the 68881 status register which locore stashed 397 * in code for us. Note that there is a possibility that the 398 * bit pattern of this register will conflict with one of the 399 * FPE_* codes defined in signal.h. Fortunately for us, the 400 * only such codes we use are all in the range 1-7 and the low 401 * 3 bits of the status register are defined as 0 so there is 402 * no clash. 403 */ 404 ucode = code; 405 i = SIGFPE; 406 break; 407 408#ifdef M68040 409 case T_FPEMULI|T_USER: /* unimplemented FP instuction */ 410 case T_FPEMULD|T_USER: /* unimplemented FP data type */ 411 /* XXX need to FSAVE */ 412 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", 413 p->p_pid, p->p_comm, 414 frame.f_format == 2 ? "instruction" : "data type", 415 frame.f_pc, frame.f_fmt2.f_iaddr); 416 /* XXX need to FRESTORE */ 417 i = SIGFPE; 418 break; 419#endif 420 421 case T_ILLINST|T_USER: /* illegal instruction fault */ 422#ifdef COMPAT_HPUX 423 if (p->p_emul == &emul_hpux) { 424 ucode = HPUX_ILL_ILLINST_TRAP; 425 i = SIGILL; 426 break; 427 } 428 /* fall through */ 429#endif 430 case T_PRIVINST|T_USER: /* privileged instruction fault */ 431#ifdef COMPAT_HPUX 432 if (p->p_emul == &emul_hpux) 433 ucode = HPUX_ILL_PRIV_TRAP; 434 else 435#endif 436 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 437 i = SIGILL; 438 break; 439 440 case T_ZERODIV|T_USER: /* Divide by zero */ 441#ifdef COMPAT_HPUX 442 if (p->p_emul == &emul_hpux) 443 ucode = HPUX_FPE_INTDIV_TRAP; 444 else 445#endif 446 ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ 447 i = SIGFPE; 448 break; 449 450 case T_CHKINST|T_USER: /* CHK instruction trap */ 451#ifdef COMPAT_HPUX 452 if (p->p_emul == &emul_hpux) { 453 /* handled differently under hp-ux */ 454 i = SIGILL; 455 ucode = HPUX_ILL_CHK_TRAP; 456 break; 457 } 458#endif 459 ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ 460 i = SIGFPE; 461 break; 462 463 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ 464#ifdef COMPAT_HPUX 465 if (p->p_emul == &emul_hpux) { 466 /* handled differently under hp-ux */ 467 i = SIGILL; 468 ucode = HPUX_ILL_TRAPV_TRAP; 469 break; 470 } 471#endif 472 ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ 473 i = SIGFPE; 474 break; 475 476 /* 477 * XXX: Trace traps are a nightmare. 478 * 479 * HP-UX uses trap #1 for breakpoints, 480 * NetBSD/m68k uses trap #2, 481 * SUN 3.x uses trap #15, 482 * DDB and KGDB uses trap #15 (for kernel breakpoints; 483 * handled elsewhere). 484 * 485 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE. 486 * SUN 3.x traps get passed through as T_TRAP15 and are not really 487 * supported yet. 488 * 489 * XXX: We should never get kernel-mode T_TRAP15 490 * XXX: because locore.s now gives them special treatment. 491 */ 492 case T_TRAP15: /* kernel breakpoint */ 493#ifdef DEBUG 494 printf("unexpected kernel trace trap, type = %d\n", type); 495 printf("program counter = 0x%x\n", frame.f_pc); 496#endif 497 frame.f_sr &= ~PSL_T; 498 return; 499 500 case T_TRACE|T_USER: /* user trace trap */ 501#ifdef COMPAT_SUNOS 502 /* 503 * SunOS uses Trap #2 for a "CPU cache flush". 504 * Just flush the on-chip caches and return. 505 */ 506 if (p->p_emul == &emul_sunos) { 507 ICIA(); 508 DCIU(); 509 return; 510 } 511#endif 512 /* FALLTHROUGH */ 513 case T_TRACE: /* tracing a trap instruction */ 514 case T_TRAP15|T_USER: /* SUN user trace trap */ 515 frame.f_sr &= ~PSL_T; 516 i = SIGTRAP; 517 break; 518 519 case T_ASTFLT: /* system async trap, cannot happen */ 520 goto dopanic; 521 522 case T_ASTFLT|T_USER: /* user async trap */ 523 astpending = 0; 524 /* 525 * We check for software interrupts first. This is because 526 * they are at a higher level than ASTs, and on a VAX would 527 * interrupt the AST. We assume that if we are processing 528 * an AST that we must be at IPL0 so we don't bother to 529 * check. Note that we ensure that we are at least at SIR 530 * IPL while processing the SIR. 531 */ 532 spl1(); 533 /* fall into... */ 534 535 case T_SSIR: /* software interrupt */ 536 case T_SSIR|T_USER: 537 while ((bit = ffs(ssir))) { 538 --bit; 539 ssir &= ~(1 << bit); 540 uvmexp.softs++; 541 if (sir_routines[bit]) 542 sir_routines[bit](sir_args[bit]); 543 } 544 /* 545 * If this was not an AST trap, we are all done. 546 */ 547 if (type != (T_ASTFLT|T_USER)) { 548 uvmexp.traps--; 549 return; 550 } 551 spl0(); 552 if (p->p_flag & P_OWEUPC) { 553 p->p_flag &= ~P_OWEUPC; 554 ADDUPROF(p); 555 } 556 goto out; 557 558 case T_MMUFLT: /* kernel mode page fault */ 559 /* 560 * If we were doing profiling ticks or other user mode 561 * stuff from interrupt code, Just Say No. 562 */ 563 if (p->p_addr->u_pcb.pcb_onfault == fubail || 564 p->p_addr->u_pcb.pcb_onfault == subail) 565 goto copyfault; 566 /* fall into ... */ 567 568 case T_MMUFLT|T_USER: /* page fault */ 569 { 570 vaddr_t va; 571 struct vmspace *vm = p->p_vmspace; 572 struct vm_map *map; 573 int rv; 574 vm_prot_t ftype; 575 extern struct vm_map *kernel_map; 576 577#ifdef DEBUG 578 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 579 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 580 p->p_pid, code, v, frame.f_pc, frame.f_sr); 581#endif 582 /* 583 * It is only a kernel address space fault iff: 584 * 1. (type & T_USER) == 0 and 585 * 2. pcb_onfault not set or 586 * 3. pcb_onfault set but supervisor space data fault 587 * The last can occur during an exec() copyin where the 588 * argument space is lazy-allocated. 589 */ 590 if ((type & T_USER) == 0 && 591 ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code))) 592 map = kernel_map; 593 else 594 map = vm ? &vm->vm_map : kernel_map; 595 596 if (WRFAULT(code)) 597 ftype = VM_PROT_READ | VM_PROT_WRITE; 598 else 599 ftype = VM_PROT_READ; 600 601 va = trunc_page((vaddr_t)v); 602 603 if (map == kernel_map && va == 0) { 604 printf("trap: bad kernel %s access at 0x%x\n", 605 (ftype & VM_PROT_WRITE) ? "read/write" : 606 "read", v); 607 goto dopanic; 608 } 609 610#ifdef COMPAT_HPUX 611 if (ISHPMMADDR(va)) { 612 int pmap_mapmulti __P((pmap_t, vaddr_t)); 613 vaddr_t bva; 614 615 rv = pmap_mapmulti(map->pmap, va); 616 if (rv != 0) { 617 bva = HPMMBASEADDR(va); 618 rv = uvm_fault(map, bva, 0, ftype); 619 if (rv == 0) 620 (void) pmap_mapmulti(map->pmap, va); 621 } 622 } else 623#endif 624 rv = uvm_fault(map, va, 0, ftype); 625#ifdef DEBUG 626 if (rv && MDB_ISPID(p->p_pid)) 627 printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", 628 map, va, ftype, rv); 629#endif 630 /* 631 * If this was a stack access we keep track of the maximum 632 * accessed stack size. Also, if vm_fault gets a protection 633 * failure it is due to accessing the stack region outside 634 * the current limit and we need to reflect that as an access 635 * error. 636 */ 637 if ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr) 638 && map != kernel_map) { 639 if (rv == 0) { 640 unsigned nss; 641 642 nss = btoc(USRSTACK-(unsigned)va); 643 if (nss > vm->vm_ssize) 644 vm->vm_ssize = nss; 645 } else if (rv == EACCES) 646 rv = EFAULT; 647 } 648 if (rv == 0) { 649 if (type == T_MMUFLT) { 650#ifdef M68040 651 if (cputype == CPU_68040) 652 (void) writeback(&frame, 1); 653#endif 654 return; 655 } 656 goto out; 657 } 658 if (type == T_MMUFLT) { 659 if (p->p_addr->u_pcb.pcb_onfault) 660 goto copyfault; 661 printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", 662 map, va, ftype, rv); 663 printf(" type %x, code [mmu,,ssw]: %x\n", 664 type, code); 665 goto dopanic; 666 } 667 ucode = v; 668 if (rv == ENOMEM) { 669 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 670 p->p_pid, p->p_comm, 671 p->p_cred && p->p_ucred ? 672 p->p_ucred->cr_uid : -1); 673 i = SIGKILL; 674 } else { 675 i = SIGSEGV; 676 } 677 break; 678 } 679 } 680 trapsignal(p, i, ucode); 681 if ((type & T_USER) == 0) 682 return; 683out: 684 userret(p, &frame, sticks, v, 1); 685} 686 687#ifdef M68040 688#ifdef DEBUG 689struct writebackstats { 690 int calls; 691 int cpushes; 692 int move16s; 693 int wb1s, wb2s, wb3s; 694 int wbsize[4]; 695} wbstats; 696 697char *f7sz[] = { "longword", "byte", "word", "line" }; 698char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; 699char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", 700 "M-code", "k-data", "k-code", "RES" }; 701char wberrstr[] = 702 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; 703#endif 704 705int 706writeback(fp, docachepush) 707 struct frame *fp; 708 int docachepush; 709{ 710 struct fmt7 *f = &fp->f_fmt7; 711 struct proc *p = curproc; 712 int err = 0; 713 u_int fa; 714 caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault; 715 paddr_t pa; 716 717#ifdef DEBUG 718 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 719 printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); 720 dumpssw(f->f_ssw); 721 } 722 wbstats.calls++; 723#endif 724 /* 725 * Deal with special cases first. 726 */ 727 if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { 728 /* 729 * Dcache push fault. 730 * Line-align the address and write out the push data to 731 * the indicated physical address. 732 */ 733#ifdef DEBUG 734 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { 735 printf(" pushing %s to PA %x, data %x", 736 f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], 737 f->f_fa, f->f_pd0); 738 if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) 739 printf("/%x/%x/%x", 740 f->f_pd1, f->f_pd2, f->f_pd3); 741 printf("\n"); 742 } 743 if (f->f_wb1s & SSW4_WBSV) 744 panic("writeback: cache push with WB1S valid"); 745 wbstats.cpushes++; 746#endif 747 /* 748 * XXX there are security problems if we attempt to do a 749 * cache push after a signal handler has been called. 750 */ 751 if (docachepush) { 752 pmap_enter(pmap_kernel(), (vaddr_t)vmmap, 753 trunc_page(f->f_fa), VM_PROT_WRITE, 754 VM_PROT_WRITE|PMAP_WIRED); 755 pmap_update(pmap_kernel()); 756 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 757 bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16); 758 (void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa); 759 DCFL(pa); 760 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, 761 (vaddr_t)&vmmap[NBPG]); 762 pmap_update(pmap_kernel()); 763 } else 764 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 765 p->p_pid, p->p_comm, p->p_ucred->cr_uid); 766 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 767 /* 768 * MOVE16 fault. 769 * Line-align the address and write out the push data to 770 * the indicated virtual address. 771 */ 772#ifdef DEBUG 773 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 774 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 775 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 776 f->f_pd2, f->f_pd3); 777 if (f->f_wb1s & SSW4_WBSV) 778 panic("writeback: MOVE16 with WB1S valid"); 779 wbstats.move16s++; 780#endif 781 if (KDFAULT(f->f_wb1s)) 782 bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16); 783 else 784 err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); 785 if (err) { 786 fa = f->f_fa & ~0xF; 787#ifdef DEBUG 788 if (mmudebug & MDB_WBFAILED) 789 printf(wberrstr, p->p_pid, p->p_comm, 790 "MOVE16", fp->f_pc, f->f_fa, 791 f->f_fa & ~0xF, f->f_pd0); 792#endif 793 } 794 } else if (f->f_wb1s & SSW4_WBSV) { 795 /* 796 * Writeback #1. 797 * Position the "memory-aligned" data and write it out. 798 */ 799 u_int wb1d = f->f_wb1d; 800 int off; 801 802#ifdef DEBUG 803 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 804 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 805 wbstats.wb1s++; 806 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 807#endif 808 off = (f->f_wb1a & 3) * 8; 809 switch (f->f_wb1s & SSW4_SZMASK) { 810 case SSW4_SZLW: 811 if (off) 812 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 813 if (KDFAULT(f->f_wb1s)) 814 *(long *)f->f_wb1a = wb1d; 815 else 816 err = suword((caddr_t)f->f_wb1a, wb1d); 817 break; 818 case SSW4_SZB: 819 off = 24 - off; 820 if (off) 821 wb1d >>= off; 822 if (KDFAULT(f->f_wb1s)) 823 *(char *)f->f_wb1a = wb1d; 824 else 825 err = subyte((caddr_t)f->f_wb1a, wb1d); 826 break; 827 case SSW4_SZW: 828 off = (off + 16) % 32; 829 if (off) 830 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 831 if (KDFAULT(f->f_wb1s)) 832 *(short *)f->f_wb1a = wb1d; 833 else 834 err = susword((caddr_t)f->f_wb1a, wb1d); 835 break; 836 } 837 if (err) { 838 fa = f->f_wb1a; 839#ifdef DEBUG 840 if (mmudebug & MDB_WBFAILED) 841 printf(wberrstr, p->p_pid, p->p_comm, 842 "#1", fp->f_pc, f->f_fa, 843 f->f_wb1a, f->f_wb1d); 844#endif 845 } 846 } 847 /* 848 * Deal with the "normal" writebacks. 849 * 850 * XXX writeback2 is known to reflect a LINE size writeback after 851 * a MOVE16 was already dealt with above. Ignore it. 852 */ 853 if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 854 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 855#ifdef DEBUG 856 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 857 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 858 wbstats.wb2s++; 859 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 860#endif 861 switch (f->f_wb2s & SSW4_SZMASK) { 862 case SSW4_SZLW: 863 if (KDFAULT(f->f_wb2s)) 864 *(long *)f->f_wb2a = f->f_wb2d; 865 else 866 err = suword((caddr_t)f->f_wb2a, f->f_wb2d); 867 break; 868 case SSW4_SZB: 869 if (KDFAULT(f->f_wb2s)) 870 *(char *)f->f_wb2a = f->f_wb2d; 871 else 872 err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); 873 break; 874 case SSW4_SZW: 875 if (KDFAULT(f->f_wb2s)) 876 *(short *)f->f_wb2a = f->f_wb2d; 877 else 878 err = susword((caddr_t)f->f_wb2a, f->f_wb2d); 879 break; 880 } 881 if (err) { 882 fa = f->f_wb2a; 883#ifdef DEBUG 884 if (mmudebug & MDB_WBFAILED) { 885 printf(wberrstr, p->p_pid, p->p_comm, 886 "#2", fp->f_pc, f->f_fa, 887 f->f_wb2a, f->f_wb2d); 888 dumpssw(f->f_ssw); 889 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 890 } 891#endif 892 } 893 } 894 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 895#ifdef DEBUG 896 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 897 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 898 wbstats.wb3s++; 899 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 900#endif 901 switch (f->f_wb3s & SSW4_SZMASK) { 902 case SSW4_SZLW: 903 if (KDFAULT(f->f_wb3s)) 904 *(long *)f->f_wb3a = f->f_wb3d; 905 else 906 err = suword((caddr_t)f->f_wb3a, f->f_wb3d); 907 break; 908 case SSW4_SZB: 909 if (KDFAULT(f->f_wb3s)) 910 *(char *)f->f_wb3a = f->f_wb3d; 911 else 912 err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); 913 break; 914 case SSW4_SZW: 915 if (KDFAULT(f->f_wb3s)) 916 *(short *)f->f_wb3a = f->f_wb3d; 917 else 918 err = susword((caddr_t)f->f_wb3a, f->f_wb3d); 919 break; 920#ifdef DEBUG 921 case SSW4_SZLN: 922 panic("writeback: wb3s indicates LINE write"); 923#endif 924 } 925 if (err) { 926 fa = f->f_wb3a; 927#ifdef DEBUG 928 if (mmudebug & MDB_WBFAILED) 929 printf(wberrstr, p->p_pid, p->p_comm, 930 "#3", fp->f_pc, f->f_fa, 931 f->f_wb3a, f->f_wb3d); 932#endif 933 } 934 } 935 p->p_addr->u_pcb.pcb_onfault = oonfault; 936 if (err) 937 err = SIGSEGV; 938 return (err); 939} 940 941#ifdef DEBUG 942void 943dumpssw(ssw) 944 u_short ssw; 945{ 946 printf(" SSW: %x: ", ssw); 947 if (ssw & SSW4_CP) 948 printf("CP,"); 949 if (ssw & SSW4_CU) 950 printf("CU,"); 951 if (ssw & SSW4_CT) 952 printf("CT,"); 953 if (ssw & SSW4_CM) 954 printf("CM,"); 955 if (ssw & SSW4_MA) 956 printf("MA,"); 957 if (ssw & SSW4_ATC) 958 printf("ATC,"); 959 if (ssw & SSW4_LK) 960 printf("LK,"); 961 if (ssw & SSW4_RW) 962 printf("RW,"); 963 printf(" SZ=%s, TT=%s, TM=%s\n", 964 f7sz[(ssw & SSW4_SZMASK) >> 5], 965 f7tt[(ssw & SSW4_TTMASK) >> 3], 966 f7tm[ssw & SSW4_TMMASK]); 967} 968 969void 970dumpwb(num, s, a, d) 971 int num; 972 u_short s; 973 u_int a, d; 974{ 975 struct proc *p = curproc; 976 paddr_t pa; 977 978 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 979 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 980 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 981 printf(" PA "); 982 if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE) 983 printf("<invalid address>"); 984 else 985 printf("%lx, current value %lx", pa, fuword((caddr_t)a)); 986 printf("\n"); 987} 988#endif 989#endif 990 991/* 992 * Allocation routines for software interrupts. 993 */ 994u_long 995allocate_sir(proc, arg) 996 void (*proc)(void *); 997 void *arg; 998{ 999 int bit; 1000 1001 if( next_sir >= NSIR ) 1002 panic("allocate_sir: none left"); 1003 bit = next_sir++; 1004 sir_routines[bit] = proc; 1005 sir_args[bit] = arg; 1006 return (1 << bit); 1007} 1008 1009void 1010init_sir() 1011{ 1012 extern void netintr(void); 1013 1014 sir_routines[0] = (void (*)(void *))netintr; 1015 sir_routines[1] = softclock; 1016 next_sir = 2; 1017} 1018