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