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