1 /* $NetBSD: trap.c,v 1.88 2002/02/14 07:08:03 chs Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 6 * 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. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah $Hdr: trap.c 1.32 91/04/06$ 41 * 42 * @(#)trap.c 7.15 (Berkeley) 8/2/91 43 */ 44 45 #include "opt_ddb.h" 46 #include "opt_execfmt.h" 47 #include "opt_compat_sunos.h" 48 49 #include <sys/cdefs.h> 50 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.88 2002/02/14 07:08:03 chs Exp $"); 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/syslog.h> 60 #include <sys/syscall.h> 61 62 #include <sys/user.h> 63 64 #include <uvm/uvm_extern.h> 65 66 #include <machine/psl.h> 67 #include <machine/trap.h> 68 #include <machine/cpu.h> 69 #include <machine/reg.h> 70 #include <machine/mtpr.h> 71 #include <machine/pte.h> 72 73 #include <m68k/fpe/fpu_emulate.h> 74 #include <m68k/cacheops.h> 75 76 #ifdef COMPAT_SUNOS 77 #include <compat/sunos/sunos_syscall.h> 78 extern struct emul emul_sunos; 79 #endif 80 81 /* 82 * XXX Hack until I can figure out what to do about this code's removal 83 * from m68k/include/frame.h 84 */ 85 86 /* 68040 fault frame */ 87 #define SSW_CP 0x8000 /* Continuation - Floating-Point Post*/ 88 #define SSW_CU 0x4000 /* Continuation - Unimpl. FP */ 89 #define SSW_CT 0x2000 /* Continuation - Trace */ 90 #define SSW_CM 0x1000 /* Continuation - MOVEM */ 91 #define SSW_MA 0x0800 /* Misaligned access */ 92 #define SSW_ATC 0x0400 /* ATC fault */ 93 #define SSW_LK 0x0200 /* Locked transfer */ 94 #define SSW_RW040 0x0100 /* Read/Write */ 95 #define SSW_SZMASK 0x0060 /* Transfer size */ 96 #define SSW_TTMASK 0x0018 /* Transfer type */ 97 #define SSW_TMMASK 0x0007 /* Transfer modifier */ 98 99 #define WBS_TMMASK 0x0007 100 #define WBS_TTMASK 0x0018 101 #define WBS_SZMASK 0x0060 102 #define WBS_VALID 0x0080 103 104 #define WBS_SIZE_BYTE 0x0020 105 #define WBS_SIZE_WORD 0x0040 106 #define WBS_SIZE_LONG 0x0000 107 #define WBS_SIZE_LINE 0x0060 108 109 #define WBS_TT_NORMAL 0x0000 110 #define WBS_TT_MOVE16 0x0008 111 #define WBS_TT_ALTFC 0x0010 112 #define WBS_TT_ACK 0x0018 113 114 #define WBS_TM_PUSH 0x0000 115 #define WBS_TM_UDATA 0x0001 116 #define WBS_TM_UCODE 0x0002 117 #define WBS_TM_MMUTD 0x0003 118 #define WBS_TM_MMUTC 0x0004 119 #define WBS_TM_SDATA 0x0005 120 #define WBS_TM_SCODE 0x0006 121 #define WBS_TM_RESV 0x0007 122 123 #define MMUSR_PA_MASK 0xfffff000 124 #define MMUSR_B 0x00000800 125 #define MMUSR_G 0x00000400 126 #define MMUSR_U1 0x00000200 127 #define MMUSR_U0 0x00000100 128 #define MMUSR_S 0x00000080 129 #define MMUSR_CM 0x00000060 130 #define MMUSR_M 0x00000010 131 #define MMUSR_0 0x00000008 132 #define MMUSR_W 0x00000004 133 #define MMUSR_T 0x00000002 134 #define MMUSR_R 0x00000001 135 136 #define FSLW_STRING "\020\1SEE\3BPE\4TTR\5WE\6RE\7TWE\010WP\011SP" \ 137 "\012PF\013IL\014PTB\015PTA\016SBE\017PBE" 138 /* 139 * XXX End hack 140 */ 141 142 int astpending; 143 144 char *trap_type[] = { 145 "Bus error", 146 "Address error", 147 "Illegal instruction", 148 "Zero divide", 149 "CHK instruction", 150 "TRAPV instruction", 151 "Privilege violation", 152 "Trace trap", 153 "MMU fault", 154 "SSIR trap", 155 "Format error", 156 "68881 exception", 157 "Coprocessor violation", 158 "Async system trap" 159 }; 160 int trap_types = sizeof trap_type / sizeof trap_type[0]; 161 162 /* 163 * Size of various exception stack frames (minus the standard 8 bytes) 164 */ 165 short exframesize[] = { 166 FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 167 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 168 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 169 FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 170 FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 171 -1, -1, /* type 5-6 - undefined */ 172 FMT7SIZE, /* type 7 - access error (68040) */ 173 58, /* type 8 - bus fault (68010) */ 174 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 175 FMTASIZE, /* type A - short bus fault (68020/030) */ 176 FMTBSIZE, /* type B - long bus fault (68020/030) */ 177 -1, -1, -1, -1 /* type C-F - undefined */ 178 }; 179 180 #ifdef DEBUG 181 int mmudebug = 0; 182 #endif 183 184 extern struct pcb *curpcb; 185 extern char fubail[], subail[]; 186 int _write_back(u_int, u_int, u_int, u_int, struct vm_map *); 187 static void userret(struct proc *, int, u_quad_t); 188 void panictrap(int, u_int, u_int, struct frame *); 189 void trapcpfault(struct proc *, struct frame *); 190 void trapmmufault(int, u_int, u_int, struct frame *, struct proc *, 191 u_quad_t); 192 void trap(int, u_int, u_int, struct frame); 193 #ifdef DDB 194 #include <m68k/db_machdep.h> 195 int kdb_trap(int, db_regs_t *); 196 #endif 197 void _wb_fault(void); 198 199 200 static void 201 userret(p, pc, oticks) 202 struct proc *p; 203 int pc; 204 u_quad_t oticks; 205 { 206 int sig; 207 208 while ((sig = CURSIG(p)) != 0) 209 postsig(sig); 210 211 p->p_priority = p->p_usrpri; 212 213 if (want_resched) { 214 /* 215 * We are being preempted. 216 */ 217 preempt(NULL); 218 while ((sig = CURSIG(p)) != 0) 219 postsig(sig); 220 } 221 /* 222 * If profiling, charge recent system time. 223 */ 224 if (p->p_flag & P_PROFIL) { 225 extern int psratio; 226 227 addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio); 228 } 229 curcpu()->ci_schedstate.spc_curpriority = p->p_priority; 230 } 231 232 /* 233 * Used by the common m68k syscall() and child_return() functions. 234 * XXX: Temporary until all m68k ports share common trap()/userret() code. 235 */ 236 void machine_userret(struct proc *, struct frame *, u_quad_t); 237 238 void 239 machine_userret(p, f, t) 240 struct proc *p; 241 struct frame *f; 242 u_quad_t t; 243 { 244 245 userret(p, f->f_pc, t); 246 } 247 248 void 249 panictrap(type, code, v, fp) 250 int type; 251 u_int code, v; 252 struct frame *fp; 253 { 254 static int panicing = 0; 255 if (panicing++ == 0) { 256 printf("trap type %d, code = %x, v = %x\n", type, code, v); 257 regdump((struct trapframe *)fp, 128); 258 } 259 type &= ~T_USER; 260 #ifdef DEBUG 261 DCIS(); /* XXX? push cache */ 262 #endif 263 if ((u_int)type < trap_types) 264 panic(trap_type[type]); 265 panic("trap"); 266 /*NOTREACHED*/ 267 } 268 269 /* 270 * return to fault handler 271 */ 272 void 273 trapcpfault(p, fp) 274 struct proc *p; 275 struct frame *fp; 276 { 277 /* 278 * We have arranged to catch this fault in one of the 279 * copy to/from user space routines, set PC to return to 280 * indicated location and set flag informing buserror code 281 * that it may need to clean up stack frame. 282 */ 283 fp->f_stackadj = exframesize[fp->f_format]; 284 fp->f_format = fp->f_vector = 0; 285 fp->f_pc = (int) p->p_addr->u_pcb.pcb_onfault; 286 } 287 288 int donomore = 0; 289 290 void 291 trapmmufault(type, code, v, fp, p, sticks) 292 int type; 293 u_int code, v; 294 struct frame *fp; 295 struct proc *p; 296 u_quad_t sticks; 297 { 298 #if defined(DEBUG) && defined(M68060) 299 static u_int oldcode=0, oldv=0; 300 static struct proc *oldp=0; 301 #endif 302 extern struct vm_map *kernel_map; 303 struct vmspace *vm = NULL; 304 vm_prot_t ftype; 305 vaddr_t va; 306 struct vm_map *map; 307 u_int nss; 308 int rv; 309 310 /* 311 * It is only a kernel address space fault iff: 312 * 1. (type & T_USER) == 0 and 313 * 2. pcb_onfault not set or 314 * 3. pcb_onfault set but supervisor space data fault 315 * The last can occur during an exec() copyin where the 316 * argument space is lazy-allocated. 317 */ 318 #ifdef DEBUG 319 /* 320 * Print out some data about the fault 321 */ 322 #ifdef DEBUG_PAGE0 323 if (v < NBPG) /* XXX PAGE0 */ 324 mmudebug |= 0x100; /* XXX PAGE0 */ 325 #endif 326 if (mmudebug && mmutype == MMU_68040) { 327 #ifdef M68060 328 if (machineid & AMIGA_68060) { 329 if (--donomore == 0 || mmudebug & 1) { 330 char bits[64]; 331 printf ("68060 access error: pc %x, code %s," 332 " ea %x\n", fp->f_pc, 333 bitmask_snprintf(code, FSLW_STRING, 334 bits, sizeof(bits)), v); 335 } 336 if (p == oldp && v == oldv && code == oldcode) 337 panic("Identical fault backtoback!"); 338 if (donomore == 0) 339 panic("Tired of faulting."); 340 oldp = p; 341 oldv = v; 342 oldcode = code; 343 } else 344 #endif 345 printf("68040 access error: pc %x, code %x," 346 " ea %x, fa %x\n", fp->f_pc, code, fp->f_fmt7.f_ea, v); 347 if (curpcb) 348 printf(" curpcb %p\n", curpcb); 349 350 351 #ifdef DDB /* XXX PAGE0 */ 352 if (v < NBPG) /* XXX PAGE0 */ 353 Debugger(); /* XXX PAGE0 */ 354 #endif /* XXX PAGE0 */ 355 } 356 #ifdef DEBUG_PAGE0 357 mmudebug &= ~0x100; /* XXX PAGE0 */ 358 #endif 359 #endif 360 361 if (p) 362 vm = p->p_vmspace; 363 364 if (type == T_MMUFLT && 365 (!p || !p->p_addr || p->p_addr->u_pcb.pcb_onfault == 0 || ( 366 #ifdef M68060 367 machineid & AMIGA_68060 ? code & FSLW_TM_SV : 368 #endif 369 mmutype == MMU_68040 ? (code & SSW_TMMASK) == FC_SUPERD : 370 (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)))) 371 map = kernel_map; 372 else 373 map = &vm->vm_map; 374 375 if ( 376 #ifdef M68060 377 machineid & AMIGA_68060 ? code & FSLW_RW_W : 378 #endif 379 mmutype == MMU_68040 ? (code & SSW_RW040) == 0 : 380 (code & (SSW_DF|SSW_RW)) == SSW_DF) 381 /* what about RMW? */ 382 ftype = VM_PROT_WRITE; 383 else 384 ftype = VM_PROT_READ; 385 va = trunc_page((vaddr_t)v); 386 #ifdef DEBUG 387 if (map == kernel_map && va == 0) { 388 printf("trap: bad kernel access at %x pc %x\n", v, fp->f_pc); 389 panictrap(type, code, v, fp); 390 } 391 #endif 392 #ifndef no_386bsd_code 393 /* 394 * XXX: rude hack to make stack limits "work" 395 */ 396 nss = 0; 397 if (map != kernel_map && (caddr_t)va >= vm->vm_maxsaddr) { 398 nss = btoc(USRSTACK - (unsigned)va); 399 if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) { 400 nss = 0; 401 } 402 } 403 #endif 404 405 #ifdef DEBUG 406 if (mmudebug) 407 printf("vm_fault(%p,%lx,%d,0)\n", map, va, ftype); 408 #endif 409 410 rv = uvm_fault(map, va, 0, ftype); 411 412 #ifdef DEBUG 413 if (mmudebug) 414 printf("vmfault %s %lx returned %d\n", 415 map == kernel_map ? "kernel" : "user", va, rv); 416 #endif 417 #ifdef M68060 418 if ((machineid & AMIGA_68060) == 0 && mmutype == MMU_68040) { 419 #else 420 if (mmutype == MMU_68040) { 421 #endif 422 if (rv != 0) { 423 goto nogo; 424 } 425 426 /* 427 * The 68040 doesn't re-run instructions that cause 428 * write page faults (unless due to a move16 isntruction). 429 * So once the page is repaired, we have to write the 430 * value of WB2D out to memory ourselves. Because 431 * the writeback could possibly span two pages in 432 * memory, so we need to check both "ends" of the 433 * address to see if they are in the same page or not. 434 * If not, then we need to make sure the second page 435 * is valid, and bring it into memory if it's not. 436 * 437 * This whole process needs to be repeated for WB3 as well. 438 * <sigh> 439 */ 440 441 /* Check WB1 */ 442 if (fp->f_fmt7.f_wb1s & WBS_VALID) { 443 printf ("trap: wb1 was valid, not handled yet\n"); 444 panictrap(type, code, v, fp); 445 } 446 447 /* 448 * Check WB2 449 * skip if it's for a move16 instruction 450 */ 451 if(fp->f_fmt7.f_wb2s & WBS_VALID && 452 ((fp->f_fmt7.f_wb2s & WBS_TTMASK)==WBS_TT_MOVE16) == 0) { 453 if (_write_back(2, fp->f_fmt7.f_wb2s, 454 fp->f_fmt7.f_wb2d, fp->f_fmt7.f_wb2a, map) != 0) 455 goto nogo; 456 if ((fp->f_fmt7.f_wb2s & WBS_TMMASK) 457 != (code & SSW_TMMASK)) 458 panictrap(type, code, v, fp); 459 } 460 461 /* Check WB3 */ 462 if(fp->f_fmt7.f_wb3s & WBS_VALID) { 463 struct vm_map *wb3_map; 464 465 if ((fp->f_fmt7.f_wb3s & WBS_TMMASK) == WBS_TM_SDATA) 466 wb3_map = kernel_map; 467 else 468 wb3_map = &vm->vm_map; 469 if (_write_back(3, fp->f_fmt7.f_wb3s, 470 fp->f_fmt7.f_wb3d, fp->f_fmt7.f_wb3a, wb3_map) != 0) 471 goto nogo; 472 } 473 } 474 475 #ifdef no_386bsd_code 476 /* 477 * If this was a stack access we keep track of the maximum 478 * accessed stack size. Also, if vm_fault gets a protection 479 * failure it is due to accessing the stack region outside 480 * the current limit and we need to reflect that as an access 481 * error. 482 */ 483 if (map != kernel_map && (caddr_t)va >= vm->vm_maxsaddr) { 484 if (rv == 0) { 485 nss = btoc(USRSTACK-(unsigned)va); 486 if (nss > vm->vm_ssize) 487 vm->vm_ssize = nss; 488 } else if (rv == EACCES) 489 rv = EFAULT; 490 } 491 492 if (rv == 0) { 493 if (type == T_MMUFLT) 494 return; 495 userret(p, fp->f_pc, sticks); 496 return; 497 } 498 #else /* use hacky 386bsd_code */ 499 if (rv == 0) { 500 /* 501 * XXX: continuation of rude stack hack 502 */ 503 if (nss > vm->vm_ssize) 504 vm->vm_ssize = nss; 505 if (type == T_MMUFLT) 506 return; 507 userret(p, fp->f_pc, sticks); 508 return; 509 } 510 nogo: 511 #endif 512 if (type == T_MMUFLT) { 513 if (p->p_addr->u_pcb.pcb_onfault) { 514 trapcpfault(p, fp); 515 return; 516 } 517 printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", 518 map, va, ftype, rv); 519 printf(" type %x, code [mmu,,ssw]: %x\n", 520 type, code); 521 panictrap(type, code, v, fp); 522 } 523 if (rv == ENOMEM) { 524 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 525 p->p_pid, p->p_comm, 526 p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1); 527 trapsignal(p, SIGKILL, v); 528 } else { 529 trapsignal(p, SIGSEGV, v); 530 } 531 if ((type & T_USER) == 0) 532 return; 533 userret(p, fp->f_pc, sticks); 534 } 535 /* 536 * Trap is called from locore to handle most types of processor traps, 537 * including events such as simulated software interrupts/AST's. 538 * System calls are broken out for efficiency. 539 */ 540 /*ARGSUSED*/ 541 void 542 trap(type, code, v, frame) 543 int type; 544 u_int code, v; 545 struct frame frame; 546 { 547 struct proc *p; 548 u_int ucode; 549 u_quad_t sticks = 0; 550 int i; 551 552 p = curproc; 553 ucode = 0; 554 uvmexp.traps++; 555 556 if (USERMODE(frame.f_sr)) { 557 type |= T_USER; 558 sticks = p->p_sticks; 559 p->p_md.md_regs = frame.f_regs; 560 } 561 562 #ifdef DDB 563 if (type == T_TRACE || type == T_BREAKPOINT) { 564 if (kdb_trap(type, (db_regs_t *)&frame)) 565 return; 566 } 567 #endif 568 #ifdef DEBUG 569 if (mmudebug & 2) 570 printf("trap: t %x c %x v %x pad %x adj %x sr %x pc %x fmt %x vc %x\n", 571 type, code, v, frame.f_pad, frame.f_stackadj, frame.f_sr, 572 frame.f_pc, frame.f_format, frame.f_vector); 573 #endif 574 switch (type) { 575 default: 576 panictrap(type, code, v, &frame); 577 /* 578 * Kernel Bus error 579 */ 580 case T_BUSERR: 581 if (!p || !p->p_addr || !p->p_addr->u_pcb.pcb_onfault) 582 panictrap(type, code, v, &frame); 583 trapcpfault(p, &frame); 584 return; 585 /* 586 * User Bus/Addr error. 587 */ 588 case T_BUSERR|T_USER: 589 case T_ADDRERR|T_USER: 590 i = SIGBUS; 591 break; 592 /* 593 * User illegal/privleged inst fault 594 */ 595 case T_ILLINST|T_USER: 596 case T_PRIVINST|T_USER: 597 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ 598 i = SIGILL; 599 break; 600 /* 601 * divde by zero, CHK/TRAPV inst 602 */ 603 case T_ZERODIV|T_USER: 604 case T_CHKINST|T_USER: 605 case T_TRAPVINST|T_USER: 606 ucode = frame.f_format; 607 i = SIGFPE; 608 break; 609 610 case T_FPEMULI|T_USER: 611 case T_FPEMULD|T_USER: 612 #ifdef FPU_EMULATE 613 i = fpu_emulate(&frame, &p->p_addr->u_pcb.pcb_fpregs); 614 /* XXX - Deal with tracing? (frame.f_sr & PSL_T) */ 615 #else 616 printf("pid %d killed: no floating point support\n", p->p_pid); 617 i = SIGILL; 618 #endif 619 break; 620 621 #ifdef FPCOPROC 622 /* 623 * User coprocessor violation 624 */ 625 case T_COPERR|T_USER: 626 ucode = 0; 627 i = SIGFPE; /* XXX What is a proper response here? */ 628 break; 629 /* 630 * 6888x exceptions 631 */ 632 case T_FPERR|T_USER: 633 /* 634 * We pass along the 68881 status register which locore 635 * stashed in code for us. Note that there is a 636 * possibility that the bit pattern of this register 637 * will conflict with one of the FPE_* codes defined 638 * in signal.h. Fortunately for us, the only such 639 * codes we use are all in the range 1-7 and the low 640 * 3 bits of the status register are defined as 0 so 641 * there is no clash. 642 */ 643 ucode = code; 644 i = SIGFPE; 645 break; 646 /* 647 * Kernel coprocessor violation 648 */ 649 case T_COPERR: 650 /*FALLTHROUGH*/ 651 #endif 652 /* 653 * Kernel format error 654 */ 655 case T_FMTERR: 656 /* 657 * The user has most likely trashed the RTE or FP state info 658 * in the stack frame of a signal handler. 659 */ 660 type |= T_USER; 661 #ifdef DEBUG 662 printf("pid %d: kernel %s exception\n", p->p_pid, 663 type==T_COPERR ? "coprocessor" : "format"); 664 #endif 665 SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 666 sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 667 sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 668 sigdelset(&p->p_sigctx.ps_sigmask, SIGILL); 669 i = SIGILL; 670 ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ 671 break; 672 /* 673 * Trace traps. 674 * 675 * M68k NetBSD uses trap #2, 676 * SUN 3.x uses trap #15, 677 * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). 678 * 679 * Amiga traps get mapped by locore.s into T_TRACE. 680 * SUN 3.x traps get passed through as T_TRAP15 and are not really 681 * supported yet. 682 */ 683 case T_TRACE: 684 case T_TRAP15: 685 frame.f_sr &= ~PSL_T; 686 i = SIGTRAP; 687 break; 688 case T_TRACE|T_USER: 689 case T_TRAP15|T_USER: 690 #ifdef COMPAT_SUNOS 691 /* 692 * SunOS uses Trap #2 for a "CPU cache flush". 693 * Just flush the on-chip caches and return. 694 */ 695 if (p->p_emul == &emul_sunos) { 696 ICIA(); 697 DCIU(); 698 return; 699 } 700 #endif 701 frame.f_sr &= ~PSL_T; 702 i = SIGTRAP; 703 break; 704 /* 705 * Kernel AST (should not happen) 706 */ 707 case T_ASTFLT: 708 panictrap(type, code, v, &frame); 709 /* 710 * User AST 711 */ 712 case T_ASTFLT|T_USER: 713 astpending = 0; 714 spl0(); 715 if (p->p_flag & P_OWEUPC) { 716 p->p_flag &= ~P_OWEUPC; 717 ADDUPROF(p); 718 } 719 userret(p, frame.f_pc, sticks); 720 return; 721 /* 722 * Kernel/User page fault 723 */ 724 case T_MMUFLT: 725 if (p && p->p_addr && 726 (p->p_addr->u_pcb.pcb_onfault == (caddr_t)fubail || 727 p->p_addr->u_pcb.pcb_onfault == (caddr_t)subail)) { 728 trapcpfault(p, &frame); 729 return; 730 } 731 /*FALLTHROUGH*/ 732 case T_MMUFLT|T_USER: /* page fault */ 733 trapmmufault(type, code, v, &frame, p, sticks); 734 return; 735 } 736 737 #ifdef DEBUG 738 if (i != SIGTRAP) 739 printf("trapsignal(%d, %d, %d, %x, %x)\n", p->p_pid, i, 740 ucode, v, frame.f_pc); 741 #endif 742 if (i) 743 trapsignal(p, i, ucode); 744 if ((type & T_USER) == 0) 745 return; 746 userret(p, frame.f_pc, sticks); 747 } 748 749 /* 750 * Process a pending write back 751 */ 752 int 753 _write_back (wb, wb_sts, wb_data, wb_addr, wb_map) 754 u_int wb; /* writeback type: 1, 2, or 3 */ 755 u_int wb_sts; /* writeback status information */ 756 u_int wb_data; /* data to writeback */ 757 u_int wb_addr; /* address to writeback to */ 758 struct vm_map *wb_map; 759 { 760 u_int wb_extra_page = 0; 761 u_int wb_rc, mmusr; 762 763 #ifdef DEBUG 764 if (mmudebug) 765 printf("wb%d valid: %x %x %x\n",wb,wb_sts,wb_addr,wb_data); 766 #endif 767 768 /* See if we're going to span two pages (for word or long transfers) */ 769 770 if((wb_sts & WBS_SZMASK) == WBS_SIZE_WORD) 771 if(trunc_page((vaddr_t)wb_addr) != 772 trunc_page((vaddr_t)wb_addr+1)) 773 wb_extra_page = 1; 774 775 if((wb_sts & WBS_SZMASK) == WBS_SIZE_LONG) 776 if(trunc_page((vaddr_t)wb_addr) != 777 trunc_page((vaddr_t)wb_addr+3)) 778 wb_extra_page = 3; 779 780 /* 781 * if it's writeback 3, we need to check the first page 782 */ 783 if (wb == 3) { 784 mmusr = probeva(wb_addr, wb_sts & WBS_TMMASK); 785 #ifdef DEBUG 786 if (mmudebug) 787 printf("wb3: probeva(%x,%x) = %x\n", 788 wb_addr + wb_extra_page, wb_sts & WBS_TMMASK, mmusr); 789 #endif 790 791 if((mmusr & (MMUSR_R | MMUSR_W)) != MMUSR_R) { 792 #ifdef DEBUG 793 if (mmudebug) 794 printf("wb3: need to bring in first page\n"); 795 #endif 796 wb_rc = uvm_fault(wb_map, 797 trunc_page((vm_offset_t)wb_addr), 798 0, VM_PROT_READ | VM_PROT_WRITE); 799 800 if (wb_rc != 0) 801 return (wb_rc); 802 #ifdef DEBUG 803 if (mmudebug) 804 printf("wb3: first page brought in.\n"); 805 #endif 806 } 807 } 808 809 /* 810 * now check to see if a second page is required 811 */ 812 if(wb_extra_page) { 813 814 mmusr = probeva(wb_addr+wb_extra_page, wb_sts & WBS_TMMASK); 815 #ifdef DEBUG 816 if (mmudebug) 817 printf("wb%d: probeva %x %x = %x\n", 818 wb, wb_addr + wb_extra_page, 819 wb_sts & WBS_TMMASK,mmusr); 820 #endif 821 822 if((mmusr & (MMUSR_R | MMUSR_W)) != MMUSR_R) { 823 #ifdef DEBUG 824 if (mmudebug) 825 printf("wb%d: page boundary crossed." 826 " Bringing in extra page.\n",wb); 827 #endif 828 829 wb_rc = uvm_fault(wb_map, 830 trunc_page((vm_offset_t)wb_addr + wb_extra_page), 831 0, VM_PROT_READ | VM_PROT_WRITE); 832 833 if (wb_rc != 0) 834 return (wb_rc); 835 } 836 #ifdef DEBUG 837 if (mmudebug) 838 printf("wb%d: extra page brought in okay.\n", wb); 839 #endif 840 } 841 842 /* Actually do the write now */ 843 844 if ((wb_sts & WBS_TMMASK) == FC_USERD && 845 !curpcb->pcb_onfault) { 846 curpcb->pcb_onfault = (caddr_t) _wb_fault; 847 } 848 849 switch(wb_sts & WBS_SZMASK) { 850 851 case WBS_SIZE_BYTE : 852 asm volatile ("movec %0,%%dfc ; movesb %1,%2@":: "d" (wb_sts & WBS_TMMASK), 853 "d" (wb_data), 854 "a" (wb_addr)); 855 break; 856 857 case WBS_SIZE_WORD : 858 asm volatile ("movec %0,%%dfc ; movesw %1,%2@":: "d" (wb_sts & WBS_TMMASK), 859 "d" (wb_data), 860 "a" (wb_addr)); 861 break; 862 863 case WBS_SIZE_LONG : 864 asm volatile ("movec %0,%%dfc ; movesl %1,%2@":: "d" (wb_sts & WBS_TMMASK), 865 "d" (wb_data), 866 "a" (wb_addr)); 867 break; 868 869 } 870 if (curpcb->pcb_onfault == (caddr_t) _wb_fault) 871 curpcb->pcb_onfault = NULL; 872 if ((wb_sts & WBS_TMMASK) != FC_USERD) 873 asm volatile ("movec %0,%%dfc\n" : : "d" (FC_USERD)); 874 return 0; 875 } 876 877 /* 878 * fault handler for write back 879 */ 880 void 881 _wb_fault() 882 { 883 #ifdef DEBUG 884 printf ("trap: writeback fault\n"); 885 #endif 886 return; 887 } 888