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