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