xref: /netbsd/sys/arch/sun3/sun3/trap.c (revision bf9ec67e)
1 /*	$NetBSD: trap.c,v 1.105 2002/05/14 02:58:34 matt Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 Gordon W. Ross
5  * Copyright (c) 1993 Adam Glass
6  * Copyright (c) 1988 University of Utah.
7  * Copyright (c) 1982, 1986, 1990, 1993
8  *	The Regents of the University of California.  All rights reserved.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * the Systems Programming Group of the University of Utah Computer
12  * Science Department.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. All advertising materials mentioning features or use of this software
23  *    must display the following acknowledgement:
24  *	This product includes software developed by the University of
25  *	California, Berkeley and its contributors.
26  * 4. Neither the name of the University nor the names of its contributors
27  *    may be used to endorse or promote products derived from this software
28  *    without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40  * SUCH DAMAGE.
41  *
42  *	from: Utah Hdr: trap.c 1.37 92/12/20
43  *	from: @(#)trap.c	8.5 (Berkeley) 1/4/94
44  */
45 
46 #include "opt_ddb.h"
47 #include "opt_execfmt.h"
48 #include "opt_kgdb.h"
49 #include "opt_compat_aout_m68k.h"
50 #include "opt_compat_sunos.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/user.h>
62 #ifdef	KGDB
63 #include <sys/kgdb.h>
64 #endif
65 
66 #include <uvm/uvm_extern.h>
67 
68 #include <machine/cpu.h>
69 #include <machine/endian.h>
70 #include <machine/psl.h>
71 #include <machine/trap.h>
72 #include <machine/reg.h>
73 
74 #include <sun3/sun3/fc.h>
75 #include <sun3/sun3/machdep.h>
76 
77 #ifdef DDB
78 #include <machine/db_machdep.h>
79 #include <ddb/db_extern.h>
80 #endif
81 
82 #ifdef COMPAT_SUNOS
83 #include <compat/sunos/sunos_syscall.h>
84 extern struct emul emul_sunos;
85 #endif
86 
87 #ifdef COMPAT_AOUT_M68K
88 extern struct emul emul_netbsd_aoutm68k;
89 #endif
90 
91 /*
92  * The sun3 wants faults to go through the pmap code, but
93  * the sun3x just goes directly to the common VM code.
94  */
95 #ifdef	_SUN3X_
96 # define _pmap_fault(map, va, ftype) \
97 	uvm_fault(map, va, 0, ftype)
98 #endif	/* SUN3X */
99 
100 /* Special labels in m68k/copy.s */
101 extern char fubail[], subail[];
102 
103 /* These are called from locore.s */
104 void trap __P((int type, u_int code, u_int v, struct trapframe));
105 void trap_kdebug __P((int type, struct trapframe tf));
106 int _nodb_trap __P((int type, struct trapframe *));
107 void straytrap __P((struct trapframe));
108 
109 static void userret __P((struct proc *, struct trapframe *, u_quad_t));
110 
111 int astpending;
112 int want_resched;
113 
114 char	*trap_type[] = {
115 	"Bus error",
116 	"Address error",
117 	"Illegal instruction",
118 	"Zero divide",
119 	"CHK instruction",
120 	"TRAPV instruction",
121 	"Privilege violation",
122 	"Trace trap",
123 	"MMU fault",
124 	"SSIR trap",
125 	"Format error",
126 	"68881 exception",
127 	"Coprocessor violation",
128 	"Async system trap",
129 	"Unused? (14)",
130 	"Breakpoint",
131 	"FPU instruction",
132 	"FPU data format",
133 };
134 u_int trap_types = sizeof(trap_type) / sizeof(trap_type[0]);
135 
136 /*
137  * Size of various exception stack frames (minus the standard 8 bytes)
138  */
139 short	exframesize[] = {
140 	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
141 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
142 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
143 	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
144 	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
145 	-1, -1, 	/* type 5-6 - undefined */
146 	FMT7SIZE,	/* type 7 - access error (68040) */
147 	58,		/* type 8 - bus fault (68010) */
148 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
149 	FMTASIZE,	/* type A - short bus fault (68020/030) */
150 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
151 	-1, -1, -1, -1	/* type C-F - undefined */
152 };
153 
154 #define KDFAULT(c)	(((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
155 #define WRFAULT(c)	(((c) & (SSW_DF|SSW_RW)) == SSW_DF)
156 
157 /* #define	DEBUG XXX */
158 
159 #ifdef DEBUG
160 int mmudebug = 0;
161 int mmupid = -1;
162 #define MDB_ISPID(p)	((p) == mmupid)
163 #define MDB_FOLLOW	1
164 #define MDB_WBFOLLOW	2
165 #define MDB_WBFAILED	4
166 #define MDB_CPFAULT 	8
167 #endif
168 
169 /*
170  * trap and syscall both need the following work done before
171  * returning to user mode.
172  */
173 static void
174 userret(p, tf, oticks)
175 	struct proc *p;
176 	struct trapframe *tf;
177 	u_quad_t oticks;
178 {
179 	int sig;
180 
181 	/* take pending signals */
182 	while ((sig = CURSIG(p)) != 0)
183 		postsig(sig);
184 
185 	p->p_priority = p->p_usrpri;
186 
187 	if (want_resched) {
188 		/*
189 		 * We are being preempted.
190 		 */
191 		preempt(NULL);
192 		while ((sig = CURSIG(p)) != 0)
193 			postsig(sig);
194 	}
195 
196 	/*
197 	 * If profiling, charge system time to the trapped pc.
198 	 */
199 	if (p->p_flag & P_PROFIL) {
200 		extern int psratio;
201 		addupc_task(p, tf->tf_pc,
202 		            (int)(p->p_sticks - oticks) * psratio);
203 	}
204 
205 	curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
206 }
207 
208 /*
209  * Used by the common m68k syscall() and child_return() functions.
210  * XXX: Temporary until all m68k ports share common trap()/userret() code.
211  */
212 void machine_userret(struct proc *, struct frame *, u_quad_t);
213 
214 void
215 machine_userret(p, f, t)
216 	struct proc *p;
217 	struct frame *f;
218 	u_quad_t t;
219 {
220 
221 	userret(p, &f->F_t, t);
222 }
223 
224 /*
225  * Trap is called from locore to handle most types of processor traps,
226  * including events such as simulated software interrupts/AST's.
227  * System calls are broken out for efficiency.
228  */
229 /*ARGSUSED*/
230 void
231 trap(type, code, v, tf)
232 	int type;
233 	u_int code, v;
234 	struct trapframe tf;
235 {
236 	struct proc *p;
237 	int sig, tmp;
238 	u_int ucode;
239 	u_quad_t sticks;
240 	caddr_t onfault;
241 
242 	uvmexp.traps++;
243 	p = curproc;
244 	ucode = 0;
245 	sig = 0;
246 
247 	/* I have verified that this DOES happen! -gwr */
248 	if (p == NULL)
249 		p = &proc0;
250 #ifdef	DIAGNOSTIC
251 	if (p->p_addr == NULL)
252 		panic("trap: no pcb");
253 #endif
254 
255 	if (USERMODE(tf.tf_sr)) {
256 		type |= T_USER;
257 		sticks = p->p_sticks;
258 		p->p_md.md_regs = tf.tf_regs;
259 	} else {
260 		sticks = 0;
261 		/* XXX: Detect trap recursion? */
262 	}
263 
264 	switch (type) {
265 	default:
266 	dopanic:
267 		printf("trap type=0x%x, code=0x%x, v=0x%x\n", type, code, v);
268 		/*
269 		 * Let the kernel debugger see the trap frame that
270 		 * caused us to panic.  This is a convenience so
271 		 * one can see registers at the point of failure.
272 		 */
273 		tmp = splhigh();
274 #ifdef KGDB
275 		/* If connected, step or cont returns 1 */
276 		if (kgdb_trap(type, &tf))
277 			goto kgdb_cont;
278 #endif
279 #ifdef	DDB
280 		(void) kdb_trap(type, (db_regs_t *) &tf);
281 #endif
282 #ifdef KGDB
283 	kgdb_cont:
284 #endif
285 		splx(tmp);
286 		if (panicstr) {
287 			/*
288 			 * Note: panic is smart enough to do:
289 			 *   boot(RB_AUTOBOOT | RB_NOSYNC, NULL)
290 			 * if we call it again.
291 			 */
292 			panic("trap during panic!");
293 		}
294 		regdump(&tf, 128);
295 		type &= ~T_USER;
296 		if ((u_int)type < trap_types)
297 			panic(trap_type[type]);
298 		panic("trap type 0x%x", type);
299 
300 	case T_BUSERR:		/* kernel bus error */
301 		if (p->p_addr->u_pcb.pcb_onfault == NULL)
302 			goto dopanic;
303 		/*FALLTHROUGH*/
304 
305 	copyfault:
306 		/*
307 		 * If we have arranged to catch this fault in any of the
308 		 * copy to/from user space routines, set PC to return to
309 		 * indicated location and set flag informing buserror code
310 		 * that it may need to clean up stack frame.
311 		 */
312 		tf.tf_stackadj = exframesize[tf.tf_format];
313 		tf.tf_format = tf.tf_vector = 0;
314 		tf.tf_pc = (int) p->p_addr->u_pcb.pcb_onfault;
315 		goto done;
316 
317 	case T_BUSERR|T_USER:	/* bus error */
318 	case T_ADDRERR|T_USER:	/* address error */
319 		ucode = v;
320 		sig = SIGBUS;
321 		break;
322 
323 	case T_COPERR:		/* kernel coprocessor violation */
324 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
325 	case T_FMTERR:		/* ...just in case... */
326 		/*
327 		 * The user has most likely trashed the RTE or FP state info
328 		 * in the stack frame of a signal handler.
329 		 */
330 		printf("pid %d: kernel %s exception\n", p->p_pid,
331 		       type==T_COPERR ? "coprocessor" : "format");
332 		type |= T_USER;
333 		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
334 		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
335 		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
336 		sigdelset(&p->p_sigctx.ps_sigmask, SIGILL);
337 		sig = SIGILL;
338 		ucode = tf.tf_format;
339 		break;
340 
341 	case T_COPERR|T_USER:	/* user coprocessor violation */
342 		/* What is a proper response here? */
343 		ucode = 0;
344 		sig = SIGFPE;
345 		break;
346 
347 	case T_FPERR|T_USER:	/* 68881 exceptions */
348 		/*
349 		 * We pass along the 68881 status register which locore stashed
350 		 * in code for us.  Note that there is a possibility that the
351 		 * bit pattern of this register will conflict with one of the
352 		 * FPE_* codes defined in signal.h.  Fortunately for us, the
353 		 * only such codes we use are all in the range 1-7 and the low
354 		 * 3 bits of the status register are defined as 0 so there is
355 		 * no clash.
356 		 */
357 		ucode = code;
358 		sig = SIGFPE;
359 		break;
360 
361 	case T_FPEMULI:		/* FPU faults in supervisor mode */
362 	case T_FPEMULD:
363 		if (nofault)	/* Doing FPU probe? */
364 			longjmp(nofault);
365 		goto dopanic;
366 
367 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
368 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
369 #ifdef	FPU_EMULATE
370 		sig = fpu_emulate(&tf, &p->p_addr->u_pcb.pcb_fpregs);
371 		/* XXX - Deal with tracing? (tf.tf_sr & PSL_T) */
372 #else
373 		uprintf("pid %d killed: no floating point support\n", p->p_pid);
374 		sig = SIGILL;
375 #endif
376 		break;
377 
378 	case T_ILLINST|T_USER:	/* illegal instruction fault */
379 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
380 		ucode = tf.tf_format;
381 		sig = SIGILL;
382 		break;
383 
384 	case T_ZERODIV|T_USER:	/* Divide by zero */
385 	case T_CHKINST|T_USER:	/* CHK instruction trap */
386 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
387 		ucode = tf.tf_format;
388 		sig = SIGFPE;
389 		break;
390 
391 	/*
392 	 * XXX: Trace traps are a nightmare.
393 	 *
394 	 *	HP-UX uses trap #1 for breakpoints,
395 	 *	NetBSD/m68k uses trap #2,
396 	 *	SUN 3.x uses trap #15,
397 	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
398 	 *	handled elsewhere).
399 	 *
400 	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
401 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
402 	 * supported yet.
403 	 *
404 	 * XXX: We should never get kernel-mode T_TRAP15
405 	 * XXX: because locore.s now gives them special treatment.
406 	 */
407 	case T_TRAP15:		/* kernel breakpoint */
408 		tf.tf_sr &= ~PSL_T;
409 		goto done;
410 
411 	case T_TRACE|T_USER:	/* user trace trap */
412 #ifdef COMPAT_SUNOS
413 		/*
414 		 * SunOS uses Trap #2 for a "CPU cache flush"
415 		 * Just flush the on-chip caches and return.
416 		 * XXX - Too bad NetBSD uses trap 2...
417 		 */
418 		if (p->p_emul == &emul_sunos) {
419 			ICIA();
420 			DCIU();
421 			/* get out fast */
422 			goto done;
423 		}
424 #endif
425 		/* FALLTHROUGH */
426 	case T_TRACE:		/* tracing a trap instruction */
427 	case T_TRAP15|T_USER:	/* SUN user trace trap */
428 		tf.tf_sr &= ~PSL_T;
429 		sig = SIGTRAP;
430 		break;
431 
432 	case T_ASTFLT:		/* system async trap, cannot happen */
433 		goto dopanic;
434 
435 	case T_ASTFLT|T_USER:	/* user async trap */
436 		astpending = 0;
437 		/* T_SSIR is not used on a Sun3. */
438 		if (p->p_flag & P_OWEUPC) {
439 			p->p_flag &= ~P_OWEUPC;
440 			ADDUPROF(p);
441 		}
442 		goto douret;
443 
444 	case T_MMUFLT:		/* kernel mode page fault */
445 		/* Hacks to avoid calling VM code from debugger. */
446 #ifdef	DDB
447 		if (db_recover != 0)
448 			goto dopanic;
449 #endif
450 #ifdef	KGDB
451 		if (kgdb_recover != 0)
452 			goto dopanic;
453 #endif
454 		/*
455 		 * If we were doing profiling ticks or other user mode
456 		 * stuff from interrupt code, Just Say No.
457 		 */
458 		if (p->p_addr->u_pcb.pcb_onfault == (caddr_t)fubail ||
459 		    p->p_addr->u_pcb.pcb_onfault == (caddr_t)subail)
460 		{
461 #ifdef	DEBUG
462 			if (mmudebug & MDB_CPFAULT) {
463 				printf("trap: copyfault fu/su bail\n");
464 				Debugger();
465 			}
466 #endif
467 			goto copyfault;
468 		}
469 		/*FALLTHROUGH*/
470 
471 	case T_MMUFLT|T_USER: { 	/* page fault */
472 		vaddr_t va;
473 		struct vmspace *vm = p->p_vmspace;
474 		struct vm_map *map;
475 		int rv;
476 		vm_prot_t ftype;
477 		extern struct vm_map *kernel_map;
478 
479 #ifdef DEBUG
480 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
481 		printf("trap: T_MMUFLT pid=%d, code=0x%x, v=0x%x, pc=0x%x, sr=0x%x\n",
482 		       p->p_pid, code, v, tf.tf_pc, tf.tf_sr);
483 #endif
484 
485 		/*
486 		 * It is only a kernel address space fault iff:
487 		 * 	1. (type & T_USER) == 0  and: (2 or 3)
488 		 * 	2. pcb_onfault not set or
489 		 *	3. pcb_onfault set but supervisor space data fault
490 		 * The last can occur during an exec() copyin where the
491 		 * argument space is lazy-allocated.
492 		 */
493 		map = &vm->vm_map;
494 		if ((type & T_USER) == 0) {
495 			/* supervisor mode fault */
496 			if ((p->p_addr->u_pcb.pcb_onfault == NULL) || KDFAULT(code))
497 				map = kernel_map;
498 		}
499 
500 		if (WRFAULT(code))
501 			ftype = VM_PROT_WRITE;
502 		else
503 			ftype = VM_PROT_READ;
504 		va = m68k_trunc_page((vaddr_t)v);
505 
506 		/*
507 		 * Need to resolve the fault.
508 		 *
509 		 * We give the pmap code a chance to resolve faults by
510 		 * reloading translations that it was forced to unload.
511 		 * This function does that, and calls vm_fault if it
512 		 * could not resolve the fault by reloading the MMU.
513 		 * This function may also, for example, disallow any
514 		 * faults in the kernel text segment, etc.
515 		 */
516 
517 		onfault = p->p_addr->u_pcb.pcb_onfault;
518 		p->p_addr->u_pcb.pcb_onfault = NULL;
519 		rv = _pmap_fault(map, va, ftype);
520 		p->p_addr->u_pcb.pcb_onfault = onfault;
521 
522 #ifdef	DEBUG
523 		if (rv && MDB_ISPID(p->p_pid)) {
524 			printf("vm_fault(%p, 0x%lx, 0x%x, 0) -> 0x%x\n",
525 			       map, va, ftype, rv);
526 			if (mmudebug & MDB_WBFAILED)
527 				Debugger();
528 		}
529 #endif	/* DEBUG */
530 
531 		/*
532 		 * If this was a stack access we keep track of the maximum
533 		 * accessed stack size.  Also, if vm_fault gets a protection
534 		 * failure it is due to accessing the stack region outside
535 		 * the current limit and we need to reflect that as an access
536 		 * error.
537 		 */
538 		if ((map != kernel_map) && ((caddr_t)va >= vm->vm_maxsaddr)) {
539 			if (rv == 0) {
540 				unsigned nss;
541 
542 				nss = btoc((u_int)(USRSTACK-va));
543 				if (nss > vm->vm_ssize)
544 					vm->vm_ssize = nss;
545 			} else if (rv == EACCES)
546 				rv = EFAULT;
547 		}
548 		if (rv == 0)
549 			goto finish;
550 
551 		if ((type & T_USER) == 0) {
552 			/* supervisor mode fault */
553 			if (p->p_addr->u_pcb.pcb_onfault) {
554 #ifdef	DEBUG
555 				if (mmudebug & MDB_CPFAULT) {
556 					printf("trap: copyfault pcb_onfault\n");
557 					Debugger();
558 				}
559 #endif
560 				goto copyfault;
561 			}
562 			printf("vm_fault(%p, 0x%lx, 0x%x, 0) -> 0x%x\n",
563 			       map, va, ftype, rv);
564 			goto dopanic;
565 		}
566 		ucode = v;
567 		if (rv == ENOMEM) {
568 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
569 			       p->p_pid, p->p_comm,
570 			       p->p_cred && p->p_ucred ?
571 			       p->p_ucred->cr_uid : -1);
572 			sig = SIGKILL;
573 		} else {
574 			sig = SIGSEGV;
575 		}
576 		break;
577 		} /* T_MMUFLT */
578 	} /* switch */
579 
580 finish:
581 	/* If trap was from supervisor mode, just return. */
582 	if ((type & T_USER) == 0)
583 		goto done;
584 	/* Post a signal if necessary. */
585 	if (sig != 0)
586 		trapsignal(p, sig, ucode);
587 douret:
588 	userret(p, &tf, sticks);
589 
590 done:;
591 	/* XXX: Detect trap recursion? */
592 }
593 
594 /*
595  * This is used if we hit a kernel breakpoint or trace trap
596  * when there is no debugger installed (or not attached).
597  * Drop into the PROM temporarily...
598  */
599 int
600 _nodb_trap(type, tf)
601 	int type;
602 	struct trapframe *tf;
603 {
604 
605 	printf("\r\nKernel ");
606 	if ((0 <= type) && (type < trap_types))
607 		printf("%s", trap_type[type]);
608 	else
609 		printf("trap 0x%x", type);
610 	printf(", frame=%p\r\n", tf);
611 	printf("No debugger; doing PROM abort.\r\n");
612 	printf("To continue, type: c <RETURN>\r\n");
613 	sunmon_abort();
614 	/* OK then, just resume... */
615 	tf->tf_sr &= ~PSL_T;
616 	return(1);
617 }
618 
619 /*
620  * This is called by locore for supervisor-mode trace and
621  * breakpoint traps.  This is separate from trap() above
622  * so that breakpoints in trap() will work.
623  *
624  * If we have both DDB and KGDB, let KGDB see it first,
625  * because KGDB will just return 0 if not connected.
626  */
627 void
628 trap_kdebug(type, tf)
629 	int type;
630 	struct trapframe tf;
631 {
632 
633 #ifdef	KGDB
634 	/* Let KGDB handle it (if connected) */
635 	if (kgdb_trap(type, &tf))
636 		return;
637 #endif
638 #ifdef	DDB
639 	/* Let DDB handle it. */
640 	if (kdb_trap(type, &tf))
641 		return;
642 #endif
643 
644 	/* Drop into the PROM temporarily... */
645 	(void)_nodb_trap(type, &tf);
646 }
647 
648 /*
649  * Called by locore.s for an unexpected interrupt.
650  * XXX - Almost identical to trap_kdebug...
651  */
652 void
653 straytrap(tf)
654 	struct trapframe tf;
655 {
656 	int type = -1;
657 
658 	printf("unexpected trap; vector=0x%x at pc=0x%x\n",
659 		tf.tf_vector, tf.tf_pc);
660 
661 #ifdef	KGDB
662 	/* Let KGDB handle it (if connected) */
663 	if (kgdb_trap(type, &tf))
664 		return;
665 #endif
666 #ifdef	DDB
667 	/* Let DDB handle it. */
668 	if (kdb_trap(type, &tf))
669 		return;
670 #endif
671 
672 	/* Drop into the PROM temporarily... */
673 	(void)_nodb_trap(type, &tf);
674 }
675