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>
88 extern struct emul emul_sunos;
89 #endif
90
91 void trap(struct frame *, int, u_int, u_int);
92
93 static void panictrap(int, u_int, u_int, struct frame *);
94 static void trapcpfault(struct lwp *, struct frame *, int);
95 static void userret(struct lwp *, struct frame *fp, u_quad_t, u_int, int);
96
97 const 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 };
113 int trap_types = sizeof trap_type / sizeof trap_type[0];
114
115 /*
116 * Size of various exception stack frames (minus the standard 8 bytes)
117 */
118 short 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
166 int mmudebug = 0;
167 int 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
174 extern struct pcb *curpcb;
175
176 /*
177 * trap and syscall both need the following work done before returning
178 * to user mode.
179 */
180 static inline void
userret(struct lwp * l,struct frame * fp,u_quad_t oticks,u_int faultaddr,int fromtrap)181 userret(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
188 again:
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 */
239 void machine_userret(struct lwp *, struct frame *, u_quad_t);
240
241 void
machine_userret(struct lwp * l,struct frame * f,u_quad_t t)242 machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
243 {
244
245 userret(l, f, t, 0, 0);
246 }
247
248 static void
panictrap(int type,u_int code,u_int v,struct frame * fp)249 panictrap(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
272 kgdb_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 */
300 static void
trapcpfault(struct lwp * l,struct frame * fp,int error)301 trapcpfault(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*/
323 void
trap(struct frame * fp,int type,u_int code,u_int v)324 trap(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;
671 out:
672 userret(l, fp, sticks, v, 1);
673 }
674