1/* $NetBSD: trap.c,v 1.119 2023/10/05 19:41:03 ad 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. 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.32 91/04/06$ 37 * 38 * @(#)trap.c 7.15 (Berkeley) 8/2/91 39 */ 40 41#include <sys/cdefs.h> 42__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.119 2023/10/05 19:41:03 ad Exp $"); 43 44#include "opt_ddb.h" 45#include "opt_execfmt.h" 46#include "opt_kgdb.h" 47#include "opt_compat_sunos.h" 48#include "opt_fpu_emulate.h" 49#include "opt_m68k_arch.h" 50 51#include <sys/param.h> 52#include <sys/systm.h> 53#include <sys/proc.h> 54#include <sys/acct.h> 55#include <sys/kernel.h> 56#include <sys/signalvar.h> 57#include <sys/resourcevar.h> 58#include <sys/syslog.h> 59#include <sys/syscall.h> 60#include <sys/userret.h> 61#include <sys/kauth.h> 62 63#include <uvm/uvm_extern.h> 64 65#include <m68k/cpu.h> 66#include <m68k/cacheops.h> 67 68#include <machine/psl.h> 69#include <machine/trap.h> 70#include <machine/cpu.h> 71#include <machine/pcb.h> 72#include <machine/reg.h> 73#include <machine/pte.h> 74#ifdef DDB 75#include <machine/db_machdep.h> 76#endif 77 78#ifdef DEBUG 79#include <dev/cons.h> /* cngetc() */ 80#endif 81 82#ifdef FPU_EMULATE 83#include <m68k/fpe/fpu_emulate.h> 84#endif 85 86#ifdef COMPAT_SUNOS 87#include <compat/sunos/sunos_syscall.h> 88extern struct emul emul_sunos; 89#endif 90 91void trap(struct frame *, int, u_int, u_int); 92 93static void panictrap(int, u_int, u_int, struct frame *); 94static void trapcpfault(struct lwp *, struct frame *, int); 95static void userret(struct lwp *, struct frame *fp, u_quad_t, u_int, int); 96 97const char *trap_type[] = { 98 "Bus error", 99 "Address error", 100 "Illegal instruction", 101 "Zero divide", 102 "CHK instruction", 103 "TRAPV instruction", 104 "Privilege violation", 105 "Trace trap", 106 "MMU fault", 107 "SSIR trap", 108 "Format error", 109 "68881 exception", 110 "Coprocessor violation", 111 "Async system trap" 112}; 113int trap_types = sizeof trap_type / sizeof trap_type[0]; 114 115/* 116 * Size of various exception stack frames (minus the standard 8 bytes) 117 */ 118short exframesize[] = { 119 FMT0SIZE, /* type 0 - normal (68020/030/040/060) */ 120 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */ 121 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040/060) */ 122 FMT3SIZE, /* type 3 - FP post-instruction (68040/060) */ 123 FMT4SIZE, /* type 4 - access error/fp disabled (68060) */ 124 -1, -1, /* type 5-6 - undefined */ 125 FMT7SIZE, /* type 7 - access error (68040) */ 126 58, /* type 8 - bus fault (68010) */ 127 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */ 128 FMTASIZE, /* type A - short bus fault (68020/030) */ 129 FMTBSIZE, /* type B - long bus fault (68020/030) */ 130 -1, -1, -1, -1 /* type C-F - undefined */ 131}; 132 133#ifdef M68060 134#define KDFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_TM_SV)) 135#define WRFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_RW_W)) 136#else 137#define KDFAULT_060(c) 0 138#define WRFAULT_060(c) 0 139#endif 140 141#ifdef M68040 142#define KDFAULT_040(c) (cputype == CPU_68040 && \ 143 ((c) & SSW4_TMMASK) == SSW4_TMKD) 144#define WRFAULT_040(c) (cputype == CPU_68040 && \ 145 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW) 146#else 147#define KDFAULT_040(c) 0 148#define WRFAULT_040(c) 0 149#endif 150 151#if defined(M68030) || defined(M68020) 152#define KDFAULT_OTH(c) (cputype <= CPU_68030 && \ 153 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) 154#define WRFAULT_OTH(c) (cputype <= CPU_68030 && \ 155 (((c) & SSW_DF) != 0 && \ 156 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0)))) 157#else 158#define KDFAULT_OTH(c) 0 159#define WRFAULT_OTH(c) 0 160#endif 161 162#define KDFAULT(c) (KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c)) 163#define WRFAULT(c) (WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c)) 164 165#ifdef DEBUG 166int mmudebug = 0; 167int mmupid = -1; 168#define MDB_FOLLOW 1 169#define MDB_WBFOLLOW 2 170#define MDB_WBFAILED 4 171#define MDB_ISPID(pid) ((pid) == mmupid) 172#endif 173 174extern struct pcb *curpcb; 175 176/* 177 * trap and syscall both need the following work done before returning 178 * to user mode. 179 */ 180static inline void 181userret(struct lwp *l, struct frame *fp, u_quad_t oticks, u_int faultaddr, int fromtrap) 182{ 183 struct proc *p = l->l_proc; 184#ifdef M68040 185 int sig; 186 int beenhere = 0; 187 188again: 189#endif 190 /* Invoke MI userret code */ 191 mi_userret(l); 192 193 /* 194 * If profiling, charge system time to the trapped pc. 195 */ 196 if (p->p_stflag & PST_PROFIL) { 197 extern int psratio; 198 199 addupc_task(l, fp->f_pc, 200 (int)(p->p_sticks - oticks) * psratio); 201 } 202#ifdef M68040 203 /* 204 * Deal with user mode writebacks (from trap, or from sigreturn). 205 * If any writeback fails, go back and attempt signal delivery. 206 * unless we have already been here and attempted the writeback 207 * (e.g. bad address with user ignoring SIGSEGV). In that case 208 * we just return to the user without successfully completing 209 * the writebacks. Maybe we should just drop the sucker? 210 */ 211 if (cputype == CPU_68040 && fp->f_format == FMT7) { 212 if (beenhere) { 213#ifdef DEBUG 214 if (mmudebug & MDB_WBFAILED) 215 printf(fromtrap ? 216 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : 217 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", 218 p->p_pid, p->p_comm, fp->f_pc, faultaddr); 219#endif 220 } else if ((sig = m68040_writeback(fp, fromtrap))) { 221 ksiginfo_t ksi; 222 beenhere = 1; 223 oticks = p->p_sticks; 224 (void)memset(&ksi, 0, sizeof(ksi)); 225 ksi.ksi_signo = sig; 226 ksi.ksi_addr = (void *)faultaddr; 227 ksi.ksi_code = BUS_OBJERR; 228 trapsignal(l, &ksi); 229 goto again; 230 } 231 } 232#endif 233} 234 235/* 236 * Used by the common m68k syscall() and child_return() functions. 237 * XXX: Temporary until all m68k ports share common trap()/userret() code. 238 */ 239void machine_userret(struct lwp *, struct frame *, u_quad_t); 240 241void 242machine_userret(struct lwp *l, struct frame *f, u_quad_t t) 243{ 244 245 userret(l, f, t, 0, 0); 246} 247 248static void 249panictrap(int type, u_int code, u_int v, struct frame *fp) 250{ 251 int s; 252 253 printf("trap type %d, code = %x, v = %x\n", type, code, v); 254 printf("%s program counter = 0x%x\n", 255 (type & T_USER) ? "user" : "kernel", fp->f_pc); 256 257 /* 258 * Let the kernel debugger see the trap frame that 259 * caused us to panic. This is a convenience so 260 * one can see registers at the point of failure. 261 */ 262 s = splhigh(); 263#ifdef KGDB 264 /* If connected, step or cont returns 1 */ 265 if (kgdb_trap(type, &fp)) 266 goto kgdb_cont; 267#endif 268#ifdef DDB 269 (void)kdb_trap(type, (db_regs_t *)fp); 270#endif 271#ifdef KGDB 272kgdb_cont: 273#endif 274 splx(s); 275 276 if (panicstr) { 277 printf("Double panic\n"); 278#ifdef DEBUG 279 /* XXX Should be a machine dependent hook */ 280 printf("(press a key)\n"); 281 cnpollc(1); 282 (void)cngetc(); 283 cnpollc(0); 284#endif 285 } 286 287 regdump((struct trapframe *)fp, 128); 288 DCIS(); /* XXX? push cache */ 289 290 type &= ~T_USER; 291 if ((u_int)type < trap_types) 292 panic(trap_type[type]); 293 panic("trap"); 294 /*NOTREACHED*/ 295} 296 297/* 298 * return to fault handler 299 */ 300static void 301trapcpfault(struct lwp *l, struct frame *fp, int error) 302{ 303 struct pcb *pcb = lwp_getpcb(l); 304 305 /* 306 * We have arranged to catch this fault in one of the 307 * copy to/from user space routines, set PC to return to 308 * indicated location and set flag informing buserror code 309 * that it may need to clean up stack frame. 310 */ 311 fp->f_stackadj = exframesize[fp->f_format]; 312 fp->f_format = fp->f_vector = 0; 313 fp->f_pc = (int)pcb->pcb_onfault; 314 fp->f_regs[D0] = error; 315} 316 317/* 318 * Trap is called from locore to handle most types of processor traps, 319 * including events such as simulated software interrupts/AST's. 320 * System calls are broken out for efficiency. 321 */ 322/*ARGSUSED*/ 323void 324trap(struct frame *fp, int type, u_int code, u_int v) 325{ 326 struct lwp *l; 327 struct proc *p; 328 struct pcb *pcb; 329 ksiginfo_t ksi; 330 u_quad_t sticks; 331 332 l = curlwp; 333 sticks = 0; 334 335 curcpu()->ci_data.cpu_ntrap++; 336 337 KSI_INIT_TRAP(&ksi); 338 ksi.ksi_trap = type & ~T_USER; 339 340 p = l->l_proc; 341 pcb = lwp_getpcb(l); 342 KASSERT(pcb != NULL); 343 344 if (USERMODE(fp->f_sr)) { 345 type |= T_USER; 346 sticks = p->p_sticks; 347 l->l_md.md_regs = fp->f_regs; 348 } 349 switch (type) { 350 default: 351 panictrap(type, code, v, fp); 352 /* 353 * Kernel Bus error 354 */ 355 case T_BUSERR: 356 if (pcb->pcb_onfault == 0) 357 panictrap(type, code, v, fp); 358 trapcpfault(l, fp, EFAULT); 359 return; 360 /* 361 * User Bus/Addr error. 362 */ 363 case T_BUSERR|T_USER: 364 case T_ADDRERR|T_USER: 365 ksi.ksi_addr = (void *)v; 366 ksi.ksi_signo = SIGBUS; 367 ksi.ksi_code = (type == (T_BUSERR|T_USER)) ? 368 BUS_OBJERR : BUS_ADRERR; 369 break; 370 371 /* 372 * Kernel coprocessor violation 373 */ 374 case T_COPERR: 375 /*FALLTHROUGH*/ 376 /* 377 * Kernel/User format error 378 */ 379 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ 380 case T_FMTERR: 381 /* 382 * The user has most likely trashed the RTE or FP state info 383 * in the stack frame of a signal handler. 384 */ 385 type |= T_USER; 386#ifdef DEBUG 387 printf("pid %d: kernel %s exception\n", p->p_pid, 388 type==T_COPERR ? "coprocessor" : "format"); 389#endif 390 mutex_enter(p->p_lock); 391 SIGACTION(p, SIGILL).sa_handler = SIG_DFL; 392 sigdelset(&p->p_sigctx.ps_sigignore, SIGILL); 393 sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL); 394 sigdelset(&l->l_sigmask, SIGILL); 395 mutex_exit(p->p_lock); 396 397 ksi.ksi_signo = SIGILL; 398 ksi.ksi_addr = (void *)(int)fp->f_format; 399 /* XXX was ILL_RESAD_FAULT */ 400 ksi.ksi_code = (type == T_COPERR) ? 401 ILL_COPROC : ILL_ILLOPC; 402 break; 403 404 /* 405 * User coprocessor violation 406 */ 407 case T_COPERR|T_USER: 408 /* XXX What is a proper response here? */ 409 ksi.ksi_signo = SIGFPE; 410 ksi.ksi_code = FPE_FLTINV; 411 break; 412 413 /* 414 * 6888x exceptions 415 */ 416 case T_FPERR|T_USER: 417 /* 418 * We pass along the 68881 status register which locore 419 * stashed in code for us. 420 */ 421 ksi.ksi_signo = SIGFPE; 422 ksi.ksi_code = fpsr2siginfocode(code); 423 break; 424 425 /* 426 * Unimplemented FPU instructions/datatypes. 427 */ 428 case T_FPEMULI|T_USER: 429 case T_FPEMULD|T_USER: 430#ifdef FPU_EMULATE 431 if (fpu_emulate(fp, &pcb->pcb_fpregs, &ksi) == 0) 432 ; /* XXX - Deal with tracing? (fp->f_sr & PSL_T) */ 433#else 434 uprintf("pid %d killed: no floating point support.\n", 435 p->p_pid); 436 ksi.ksi_signo = SIGILL; 437 ksi.ksi_code = ILL_ILLOPC; 438#endif 439 break; 440 441 /* 442 * FPU faults in supervisor mode. 443 */ 444 case T_FPEMULI: 445 case T_FPEMULD: { 446 extern int *nofault; 447 448 if (nofault) /* If we're probing. */ 449 longjmp((label_t *) nofault); 450 panictrap(type, code, v, fp); 451 } 452 453 /* 454 * User illegal/privileged inst fault 455 */ 456 case T_ILLINST|T_USER: 457 case T_PRIVINST|T_USER: 458 ksi.ksi_addr = (void *)(int)fp->f_format; 459 /* XXX was ILL_PRIVIN_FAULT */ 460 ksi.ksi_signo = SIGILL; 461 ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ? 462 ILL_PRVOPC : ILL_ILLOPC; 463 break; 464 465 /* 466 * divde by zero, CHK/TRAPV inst 467 */ 468 case T_ZERODIV|T_USER: 469 ksi.ksi_code = FPE_FLTDIV; 470 case T_CHKINST|T_USER: 471 case T_TRAPVINST|T_USER: 472 ksi.ksi_addr = (void *)(int)fp->f_format; 473 ksi.ksi_signo = SIGFPE; 474 break; 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 use trap #15 (for kernel breakpoints; 482 * handled elsewhere). 483 * 484 * NetBSD and HP-UX traps 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: 492 fp->f_sr &= ~PSL_T; 493 return; 494 495 case T_TRACE|T_USER: 496#ifdef COMPAT_SUNOS 497 /* 498 * SunOS uses Trap #2 for a "CPU cache flush". 499 * Just flush the on-chip caches and return. 500 */ 501 if (p->p_emul == &emul_sunos) { 502 ICIA(); 503 DCIU(); 504 return; 505 } 506#endif 507 /* FALLTHROUGH */ 508 case T_TRACE: /* tracing a trap instruction */ 509 case T_TRAP15|T_USER: 510 fp->f_sr &= ~PSL_T; 511 ksi.ksi_signo = SIGTRAP; 512 break; 513 /* 514 * Kernel AST (should not happen) 515 */ 516 case T_ASTFLT: 517 panictrap(type, code, v, fp); 518 /* 519 * User AST 520 */ 521 case T_ASTFLT|T_USER: 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 /*FALLTHROUGH*/ 533 /* 534 * Software interrupt 535 */ 536 case T_SSIR: 537 case T_SSIR|T_USER: 538 /* 539 * If this was not an AST trap, we are all done. 540 */ 541 if (type != (T_ASTFLT|T_USER)) { 542 curcpu()->ci_data.cpu_ntrap--; 543 return; 544 } 545 spl0(); 546 if (l->l_pflag & LP_OWEUPC) { 547 l->l_pflag &= ~LP_OWEUPC; 548 ADDUPROF(l); 549 } 550 goto out; 551 /* 552 * Kernel/User page fault 553 */ 554 case T_MMUFLT: 555 case T_MMUFLT|T_USER: /* page fault */ 556 { 557 vaddr_t va; 558 struct vmspace *vm = p->p_vmspace; 559 struct vm_map *map; 560 void *onfault; 561 int rv; 562 vm_prot_t ftype; 563 extern struct vm_map *kernel_map; 564 565 onfault = pcb->pcb_onfault; 566 567#ifdef DEBUG 568 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) 569 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", 570 p ? p->p_pid : -1, code, v, fp->f_pc, fp->f_sr); 571#endif 572 /* 573 * It is only a kernel address space fault iff: 574 * 1. (type & T_USER) == 0 and 575 * 2. pcb_onfault not set or 576 * 3. pcb_onfault set but supervisor space data fault 577 * The last can occur during an exec() copyin where the 578 * argument space is lazy-allocated. 579 */ 580 if (type == T_MMUFLT && (onfault == 0 || KDFAULT(code))) 581 map = kernel_map; 582 else { 583 map = vm ? &vm->vm_map : kernel_map; 584 } 585 586 if (WRFAULT(code)) 587 ftype = VM_PROT_WRITE; 588 else 589 ftype = VM_PROT_READ; 590 va = trunc_page(v); 591#ifdef DEBUG 592 if (map == kernel_map && va == 0) { 593 printf("trap: bad kernel access at %x\n", v); 594 panictrap(type, code, v, fp); 595 } 596#endif 597 pcb->pcb_onfault = NULL; 598 rv = uvm_fault(map, va, ftype); 599 pcb->pcb_onfault = onfault; 600#ifdef DEBUG 601 if (rv && MDB_ISPID(p->p_pid)) 602 printf("vm_fault(%p, %lx, %x) -> %x\n", 603 map, va, ftype, rv); 604#endif 605 /* 606 * If this was a stack access we keep track of the maximum 607 * accessed stack size. Also, if vm_fault gets a protection 608 * failure it is due to accessing the stack region outside 609 * the current limit and we need to reflect that as an access 610 * error. 611 */ 612 if (rv == 0) { 613 if (map != kernel_map && (void *)va >= vm->vm_maxsaddr) 614 uvm_grow(p, va); 615 616 if (type == T_MMUFLT) { 617#ifdef M68040 618 if (cputype == CPU_68040) 619 (void) m68040_writeback(fp, 1); 620#endif 621 return; 622 } 623 goto out; 624 } 625 if (rv == EACCES) { 626 ksi.ksi_code = SEGV_ACCERR; 627 rv = EFAULT; 628 } else 629 ksi.ksi_code = SEGV_MAPERR; 630 if (type == T_MMUFLT) { 631 if (onfault) { 632 trapcpfault(l, fp, rv); 633 return; 634 } 635 printf("\nvm_fault(%p, %lx, %x) -> %x\n", 636 map, va, ftype, rv); 637 printf(" type %x, code [mmu,,ssw]: %x\n", 638 type, code); 639 panictrap(type, code, v, fp); 640 } 641 ksi.ksi_addr = (void *)v; 642 switch (rv) { 643 case ENOMEM: 644 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 645 p->p_pid, p->p_comm, 646 l->l_cred ? 647 kauth_cred_geteuid(l->l_cred) : -1); 648 ksi.ksi_signo = SIGKILL; 649 break; 650 case EINVAL: 651 ksi.ksi_signo = SIGBUS; 652 ksi.ksi_code = BUS_ADRERR; 653 break; 654 case EACCES: 655 ksi.ksi_signo = SIGSEGV; 656 ksi.ksi_code = SEGV_ACCERR; 657 break; 658 default: 659 ksi.ksi_signo = SIGSEGV; 660 ksi.ksi_code = SEGV_MAPERR; 661 break; 662 } 663 break; 664 } 665 } 666 667 if (ksi.ksi_signo) 668 trapsignal(l, &ksi); 669 if ((type & T_USER) == 0) 670 return; 671out: 672 userret(l, fp, sticks, v, 1); 673} 674