trap.c revision 1.28
1/* $NetBSD: trap.c,v 1.28 2000/12/19 21:09:57 scw 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 p->p_sigacts->ps_sigact[SIGILL].sa_handler = SIG_DFL; 380 sigdelset(&p->p_sigignore, SIGILL); 381 sigdelset(&p->p_sigcatch, SIGILL); 382 sigdelset(&p->p_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 != KERN_SUCCESS) { 616 bva = HPMMBASEADDR(va); 617 rv = uvm_fault(map, bva, 0, ftype); 618 if (rv == KERN_SUCCESS) 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 == KERN_SUCCESS) { 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 == KERN_PROTECTION_FAILURE) 645 rv = KERN_INVALID_ADDRESS; 646 } 647 if (rv == KERN_SUCCESS) { 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 == KERN_RESOURCE_SHORTAGE) { 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 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; 755 bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16); 756 (void) pmap_extract(pmap_kernel(), (vaddr_t)fa, &pa); 757 DCFL(pa); 758 pmap_remove(pmap_kernel(), (vaddr_t)vmmap, 759 (vaddr_t)&vmmap[NBPG]); 760 } else 761 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", 762 p->p_pid, p->p_comm, p->p_ucred->cr_uid); 763 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { 764 /* 765 * MOVE16 fault. 766 * Line-align the address and write out the push data to 767 * the indicated virtual address. 768 */ 769#ifdef DEBUG 770 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 771 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", 772 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, 773 f->f_pd2, f->f_pd3); 774 if (f->f_wb1s & SSW4_WBSV) 775 panic("writeback: MOVE16 with WB1S valid"); 776 wbstats.move16s++; 777#endif 778 if (KDFAULT(f->f_wb1s)) 779 bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16); 780 else 781 err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); 782 if (err) { 783 fa = f->f_fa & ~0xF; 784#ifdef DEBUG 785 if (mmudebug & MDB_WBFAILED) 786 printf(wberrstr, p->p_pid, p->p_comm, 787 "MOVE16", fp->f_pc, f->f_fa, 788 f->f_fa & ~0xF, f->f_pd0); 789#endif 790 } 791 } else if (f->f_wb1s & SSW4_WBSV) { 792 /* 793 * Writeback #1. 794 * Position the "memory-aligned" data and write it out. 795 */ 796 u_int wb1d = f->f_wb1d; 797 int off; 798 799#ifdef DEBUG 800 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 801 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); 802 wbstats.wb1s++; 803 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 804#endif 805 off = (f->f_wb1a & 3) * 8; 806 switch (f->f_wb1s & SSW4_SZMASK) { 807 case SSW4_SZLW: 808 if (off) 809 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 810 if (KDFAULT(f->f_wb1s)) 811 *(long *)f->f_wb1a = wb1d; 812 else 813 err = suword((caddr_t)f->f_wb1a, wb1d); 814 break; 815 case SSW4_SZB: 816 off = 24 - off; 817 if (off) 818 wb1d >>= off; 819 if (KDFAULT(f->f_wb1s)) 820 *(char *)f->f_wb1a = wb1d; 821 else 822 err = subyte((caddr_t)f->f_wb1a, wb1d); 823 break; 824 case SSW4_SZW: 825 off = (off + 16) % 32; 826 if (off) 827 wb1d = (wb1d >> (32 - off)) | (wb1d << off); 828 if (KDFAULT(f->f_wb1s)) 829 *(short *)f->f_wb1a = wb1d; 830 else 831 err = susword((caddr_t)f->f_wb1a, wb1d); 832 break; 833 } 834 if (err) { 835 fa = f->f_wb1a; 836#ifdef DEBUG 837 if (mmudebug & MDB_WBFAILED) 838 printf(wberrstr, p->p_pid, p->p_comm, 839 "#1", fp->f_pc, f->f_fa, 840 f->f_wb1a, f->f_wb1d); 841#endif 842 } 843 } 844 /* 845 * Deal with the "normal" writebacks. 846 * 847 * XXX writeback2 is known to reflect a LINE size writeback after 848 * a MOVE16 was already dealt with above. Ignore it. 849 */ 850 if (err == 0 && (f->f_wb2s & SSW4_WBSV) && 851 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { 852#ifdef DEBUG 853 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 854 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 855 wbstats.wb2s++; 856 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; 857#endif 858 switch (f->f_wb2s & SSW4_SZMASK) { 859 case SSW4_SZLW: 860 if (KDFAULT(f->f_wb2s)) 861 *(long *)f->f_wb2a = f->f_wb2d; 862 else 863 err = suword((caddr_t)f->f_wb2a, f->f_wb2d); 864 break; 865 case SSW4_SZB: 866 if (KDFAULT(f->f_wb2s)) 867 *(char *)f->f_wb2a = f->f_wb2d; 868 else 869 err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); 870 break; 871 case SSW4_SZW: 872 if (KDFAULT(f->f_wb2s)) 873 *(short *)f->f_wb2a = f->f_wb2d; 874 else 875 err = susword((caddr_t)f->f_wb2a, f->f_wb2d); 876 break; 877 } 878 if (err) { 879 fa = f->f_wb2a; 880#ifdef DEBUG 881 if (mmudebug & MDB_WBFAILED) { 882 printf(wberrstr, p->p_pid, p->p_comm, 883 "#2", fp->f_pc, f->f_fa, 884 f->f_wb2a, f->f_wb2d); 885 dumpssw(f->f_ssw); 886 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); 887 } 888#endif 889 } 890 } 891 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { 892#ifdef DEBUG 893 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 894 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); 895 wbstats.wb3s++; 896 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; 897#endif 898 switch (f->f_wb3s & SSW4_SZMASK) { 899 case SSW4_SZLW: 900 if (KDFAULT(f->f_wb3s)) 901 *(long *)f->f_wb3a = f->f_wb3d; 902 else 903 err = suword((caddr_t)f->f_wb3a, f->f_wb3d); 904 break; 905 case SSW4_SZB: 906 if (KDFAULT(f->f_wb3s)) 907 *(char *)f->f_wb3a = f->f_wb3d; 908 else 909 err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); 910 break; 911 case SSW4_SZW: 912 if (KDFAULT(f->f_wb3s)) 913 *(short *)f->f_wb3a = f->f_wb3d; 914 else 915 err = susword((caddr_t)f->f_wb3a, f->f_wb3d); 916 break; 917#ifdef DEBUG 918 case SSW4_SZLN: 919 panic("writeback: wb3s indicates LINE write"); 920#endif 921 } 922 if (err) { 923 fa = f->f_wb3a; 924#ifdef DEBUG 925 if (mmudebug & MDB_WBFAILED) 926 printf(wberrstr, p->p_pid, p->p_comm, 927 "#3", fp->f_pc, f->f_fa, 928 f->f_wb3a, f->f_wb3d); 929#endif 930 } 931 } 932 p->p_addr->u_pcb.pcb_onfault = oonfault; 933 if (err) 934 err = SIGSEGV; 935 return (err); 936} 937 938#ifdef DEBUG 939void 940dumpssw(ssw) 941 u_short ssw; 942{ 943 printf(" SSW: %x: ", ssw); 944 if (ssw & SSW4_CP) 945 printf("CP,"); 946 if (ssw & SSW4_CU) 947 printf("CU,"); 948 if (ssw & SSW4_CT) 949 printf("CT,"); 950 if (ssw & SSW4_CM) 951 printf("CM,"); 952 if (ssw & SSW4_MA) 953 printf("MA,"); 954 if (ssw & SSW4_ATC) 955 printf("ATC,"); 956 if (ssw & SSW4_LK) 957 printf("LK,"); 958 if (ssw & SSW4_RW) 959 printf("RW,"); 960 printf(" SZ=%s, TT=%s, TM=%s\n", 961 f7sz[(ssw & SSW4_SZMASK) >> 5], 962 f7tt[(ssw & SSW4_TTMASK) >> 3], 963 f7tm[ssw & SSW4_TMMASK]); 964} 965 966void 967dumpwb(num, s, a, d) 968 int num; 969 u_short s; 970 u_int a, d; 971{ 972 struct proc *p = curproc; 973 paddr_t pa; 974 975 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", 976 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], 977 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); 978 printf(" PA "); 979 if (pmap_extract(p->p_vmspace->vm_map.pmap, (vaddr_t)a, &pa) == FALSE) 980 printf("<invalid address>"); 981 else 982 printf("%lx, current value %lx", pa, fuword((caddr_t)a)); 983 printf("\n"); 984} 985#endif 986#endif 987 988/* 989 * Allocation routines for software interrupts. 990 */ 991u_long 992allocate_sir(proc, arg) 993 void (*proc)(void *); 994 void *arg; 995{ 996 int bit; 997 998 if( next_sir >= NSIR ) 999 panic("allocate_sir: none left"); 1000 bit = next_sir++; 1001 sir_routines[bit] = proc; 1002 sir_args[bit] = arg; 1003 return (1 << bit); 1004} 1005 1006void 1007init_sir() 1008{ 1009 extern void netintr(void); 1010 1011 sir_routines[0] = (void (*)(void *))netintr; 1012 sir_routines[1] = (void (*)(void *))softclock; 1013 next_sir = 2; 1014} 1015