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