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