xref: /netbsd/sys/arch/i386/i386/trap.c (revision c4a72b64)
1 /*	$NetBSD: trap.c,v 1.176 2002/11/22 15:23:44 fvdl Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Charles M. Hannum.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*-
40  * Copyright (c) 1990 The Regents of the University of California.
41  * All rights reserved.
42  *
43  * This code is derived from software contributed to Berkeley by
44  * the University of Utah, and William Jolitz.
45  *
46  * Redistribution and use in source and binary forms, with or without
47  * modification, are permitted provided that the following conditions
48  * are met:
49  * 1. Redistributions of source code must retain the above copyright
50  *    notice, this list of conditions and the following disclaimer.
51  * 2. Redistributions in binary form must reproduce the above copyright
52  *    notice, this list of conditions and the following disclaimer in the
53  *    documentation and/or other materials provided with the distribution.
54  * 3. All advertising materials mentioning features or use of this software
55  *    must display the following acknowledgement:
56  *	This product includes software developed by the University of
57  *	California, Berkeley and its contributors.
58  * 4. Neither the name of the University nor the names of its contributors
59  *    may be used to endorse or promote products derived from this software
60  *    without specific prior written permission.
61  *
62  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72  * SUCH DAMAGE.
73  *
74  *	@(#)trap.c	7.4 (Berkeley) 5/13/91
75  */
76 
77 /*
78  * 386 Trap and System call handling
79  */
80 
81 #include <sys/cdefs.h>
82 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.176 2002/11/22 15:23:44 fvdl Exp $");
83 
84 #include "opt_ddb.h"
85 #include "opt_kgdb.h"
86 #include "opt_math_emulate.h"
87 #include "opt_vm86.h"
88 #include "opt_kvm86.h"
89 #include "opt_cputype.h"
90 #include "opt_kstack_dr0.h"
91 
92 #include <sys/param.h>
93 #include <sys/systm.h>
94 #include <sys/proc.h>
95 #include <sys/user.h>
96 #include <sys/acct.h>
97 #include <sys/kernel.h>
98 #include <sys/ras.h>
99 #include <sys/signal.h>
100 #include <sys/syscall.h>
101 
102 #include <uvm/uvm_extern.h>
103 
104 #include <machine/cpu.h>
105 #include <machine/cpufunc.h>
106 #include <machine/psl.h>
107 #include <machine/reg.h>
108 #include <machine/trap.h>
109 #include <machine/userret.h>
110 #ifdef DDB
111 #include <machine/db_machdep.h>
112 #endif
113 
114 #include "mca.h"
115 #if NMCA > 0
116 #include <machine/mca_machdep.h>
117 #endif
118 
119 #include "isa.h"
120 
121 #ifdef KGDB
122 #include <sys/kgdb.h>
123 #endif
124 
125 #include "npx.h"
126 
127 void trap __P((struct trapframe));
128 void trap_tss __P((struct i386tss *, int, int));
129 #if defined(I386_CPU)
130 int trapwrite __P((unsigned));
131 #endif
132 
133 #ifdef KVM86
134 #ifdef MULTIPROCESSOR
135 #error KVM86 needs a rewrite to support MP systems.
136 #endif
137 #include <machine/kvm86.h>
138 #define KVM86MODE (kvm86_incall)
139 #else
140 #define KVM86MODE (0)
141 #endif
142 
143 const char * const trap_type[] = {
144 	"privileged instruction fault",		/*  0 T_PRIVINFLT */
145 	"breakpoint trap",			/*  1 T_BPTFLT */
146 	"arithmetic trap",			/*  2 T_ARITHTRAP */
147 	"asynchronous system trap",		/*  3 T_ASTFLT */
148 	"protection fault",			/*  4 T_PROTFLT */
149 	"trace trap",				/*  5 T_TRCTRAP */
150 	"page fault",				/*  6 T_PAGEFLT */
151 	"alignment fault",			/*  7 T_ALIGNFLT */
152 	"integer divide fault",			/*  8 T_DIVIDE */
153 	"non-maskable interrupt",		/*  9 T_NMI */
154 	"overflow trap",			/* 10 T_OFLOW */
155 	"bounds check fault",			/* 11 T_BOUND */
156 	"FPU not available fault",		/* 12 T_DNA */
157 	"double fault",				/* 13 T_DOUBLEFLT */
158 	"FPU operand fetch fault",		/* 14 T_FPOPFLT */
159 	"invalid TSS fault",			/* 15 T_TSSFLT */
160 	"segment not present fault",		/* 16 T_SEGNPFLT */
161 	"stack fault",				/* 17 T_STKFLT */
162 	"machine check fault",			/* 18 T_MCA */
163 	"SSE FP exception",			/* 19 T_XMM */
164 	"reserved trap",			/* 20 T_RESERVED */
165 };
166 int	trap_types = sizeof trap_type / sizeof trap_type[0];
167 
168 #ifdef DEBUG
169 int	trapdebug = 0;
170 #endif
171 
172 #define	IDTVEC(name)	__CONCAT(X, name)
173 
174 void
175 trap_tss(struct i386tss *tss, int trapno, int code)
176 {
177 	struct trapframe tf;
178 
179 	tf.tf_gs = tss->tss_gs;
180 	tf.tf_fs = tss->tss_fs;
181 	tf.tf_es = tss->__tss_es;
182 	tf.tf_ds = tss->__tss_ds;
183 	tf.tf_edi = tss->__tss_edi;
184 	tf.tf_esi = tss->__tss_esi;
185 	tf.tf_ebp = tss->tss_ebp;
186 	tf.tf_ebx = tss->__tss_ebx;
187 	tf.tf_edx = tss->__tss_edx;
188 	tf.tf_ecx = tss->__tss_ecx;
189 	tf.tf_eax = tss->__tss_eax;
190 	tf.tf_trapno = trapno;
191 	tf.tf_err = code | TC_TSS;
192 	tf.tf_eip = tss->__tss_eip;
193 	tf.tf_cs = tss->__tss_cs;
194 	tf.tf_eflags = tss->__tss_eflags;
195 	tf.tf_esp = tss->tss_esp;
196 	tf.tf_ss = tss->__tss_ss;
197 	trap(tf);
198 }
199 
200 /*
201  * trap(frame):
202  *	Exception, fault, and trap interface to BSD kernel. This
203  * common code is called from assembly language IDT gate entry
204  * routines that prepare a suitable stack frame, and restore this
205  * frame after the exception has been processed. Note that the
206  * effect is as if the arguments were passed call by reference.
207  */
208 /*ARGSUSED*/
209 void
210 trap(frame)
211 	struct trapframe frame;
212 {
213 	register struct proc *p = curproc;
214 	int type = frame.tf_trapno;
215 	struct pcb *pcb;
216 	extern char fusubail[],
217 		    resume_iret[], resume_pop_ds[], resume_pop_es[],
218 		    resume_pop_fs[], resume_pop_gs[],
219 		    IDTVEC(osyscall)[];
220 	struct trapframe *vframe;
221 	int resume;
222 	caddr_t onfault;
223 	int error;
224 	uint32_t cr2;
225 
226 	uvmexp.traps++;
227 
228 	pcb = (p != NULL) ? &p->p_addr->u_pcb : NULL;
229 #ifdef DEBUG
230 	if (trapdebug) {
231 		printf("trap %d code %x eip %x cs %x eflags %x cr2 %x cpl %x\n",
232 		    frame.tf_trapno, frame.tf_err, frame.tf_eip, frame.tf_cs,
233 		    frame.tf_eflags, rcr2(), curcpu()->ci_ilevel);
234 		printf("curproc %p\n", curproc);
235 	}
236 #endif
237 
238 	if (!KVM86MODE && !KERNELMODE(frame.tf_cs, frame.tf_eflags)) {
239 		type |= T_USER;
240 		p->p_md.md_regs = &frame;
241 		pcb->pcb_cr2 = 0;
242 	}
243 
244 	switch (type) {
245 
246 	default:
247 	we_re_toast:
248 #ifdef KSTACK_CHECK_DR0
249 		if (type == T_TRCTRAP) {
250 			u_int mask, dr6 = rdr6();
251 
252 			mask = 1 << 0; /* dr0 */
253 			if (dr6 & mask) {
254 				panic("trap on DR0: maybe kernel stack overflow\n");
255 #if 0
256 				dr6 &= ~mask;
257 				ldr6(dr6);
258 				return;
259 #endif
260 			}
261 		}
262 #endif
263 #ifdef KGDB
264 		if (kgdb_trap(type, &frame))
265 			return;
266 		else {
267 			/*
268 			 * If this is a breakpoint, don't panic
269 			 * if we're not connected.
270 			 */
271 			if (type == T_BPTFLT) {
272 				printf("kgdb: ignored %s\n", trap_type[type]);
273 				return;
274 			}
275 		}
276 #endif
277 #ifdef DDB
278 		if (kdb_trap(type, 0, &frame))
279 			return;
280 #endif
281 		if (frame.tf_trapno < trap_types)
282 			printf("fatal %s", trap_type[frame.tf_trapno]);
283 		else
284 			printf("unknown trap %d", frame.tf_trapno);
285 		printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor");
286 		printf("trap type %d code %x eip %x cs %x eflags %x cr2 %x ilevel %x\n",
287 		    type, frame.tf_err, frame.tf_eip, frame.tf_cs,
288 		    frame.tf_eflags, rcr2(), curcpu()->ci_ilevel);
289 
290 		panic("trap");
291 		/*NOTREACHED*/
292 
293 	case T_PROTFLT:
294 #ifdef KVM86
295 		if (KVM86MODE) {
296 			kvm86_gpfault(&frame);
297 			return;
298 		}
299 #endif
300 	case T_SEGNPFLT:
301 	case T_ALIGNFLT:
302 	case T_TSSFLT:
303 		if (p == NULL)
304 			goto we_re_toast;
305 		/* Check for copyin/copyout fault. */
306 		if (pcb->pcb_onfault != 0) {
307 copyefault:
308 			error = EFAULT;
309 copyfault:
310 			frame.tf_eip = (int)pcb->pcb_onfault;
311 			frame.tf_eax = error;
312 			return;
313 		}
314 
315 		/*
316 		 * Check for failure during return to user mode.
317 		 *
318 		 * We do this by looking at the instruction we faulted on.  The
319 		 * specific instructions we recognize only happen when
320 		 * returning from a trap, syscall, or interrupt.
321 		 *
322 		 * At this point, there are (at least) two trap frames on
323 		 * the kernel stack; we presume here that we faulted while
324 		 * loading our registers out of the outer one.
325 		 *
326 		 * The inner frame does not involve a ring crossing, so it
327 		 * ends right before &frame.tf_esp.  The outer frame has
328 		 * been partially consumed by the INTRFASTEXIT; exactly
329 		 * how much depends which register we were popping when we
330 		 * faulted, so we compute the outer frame address based on
331 		 * register-dependant offsets computed from &frame.tf_esp
332 		 * below.  To decide whether this was a kernel-mode or
333 		 * user-mode error, we look at this outer frame's tf_cs
334 		 * and tf_eflags, which are (fortunately) not consumed until
335 		 * the final instruction of INTRFASTEXIT.
336 		 *
337 		 * XXX
338 		 * The heuristic used here will currently fail for the case of
339 		 * one of the 2 pop instructions faulting when returning from a
340 		 * a fast interrupt.  This should not be possible.  It can be
341 		 * fixed by rearranging the trap frame so that the stack format
342 		 * at this point is the same as on exit from a `slow'
343 		 * interrupt.
344 		 */
345 		switch (*(u_char *)frame.tf_eip) {
346 		case 0xcf:	/* iret */
347 			vframe = (void *)((int)&frame.tf_esp -
348 			    offsetof(struct trapframe, tf_eip));
349 			resume = (int)resume_iret;
350 			break;
351 		case 0x1f:	/* popl %ds */
352 			vframe = (void *)((int)&frame.tf_esp -
353 			    offsetof(struct trapframe, tf_ds));
354 			resume = (int)resume_pop_ds;
355 			break;
356 		case 0x07:	/* popl %es */
357 			vframe = (void *)((int)&frame.tf_esp -
358 			    offsetof(struct trapframe, tf_es));
359 			resume = (int)resume_pop_es;
360 			break;
361 		case 0x0f:	/* 0x0f prefix */
362 			switch (*(u_char *)(frame.tf_eip+1)) {
363 			case 0xa1:		/* popl %fs */
364 				vframe = (void *)((int)&frame.tf_esp -
365 				    offsetof(struct trapframe, tf_fs));
366 				resume = (int)resume_pop_fs;
367 				break;
368 			case 0xa9:		/* popl %gs */
369 				vframe = (void *)((int)&frame.tf_esp -
370 				    offsetof(struct trapframe, tf_gs));
371 				resume = (int)resume_pop_gs;
372 				break;
373 			}
374 			break;
375 		default:
376 			goto we_re_toast;
377 		}
378 		if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags))
379 			goto we_re_toast;
380 
381 		frame.tf_eip = resume;
382 		return;
383 
384 	case T_PROTFLT|T_USER:		/* protection fault */
385 #ifdef VM86
386 		if (frame.tf_eflags & PSL_VM) {
387 			vm86_gpfault(p, type & ~T_USER);
388 			goto out;
389 		}
390 #endif
391 	case T_TSSFLT|T_USER:
392 	case T_SEGNPFLT|T_USER:
393 	case T_STKFLT|T_USER:
394 	case T_ALIGNFLT|T_USER:
395 	case T_NMI|T_USER:
396 		KERNEL_PROC_LOCK(p);
397 		(*p->p_emul->e_trapsignal)(p, SIGBUS, type & ~T_USER);
398 		KERNEL_PROC_UNLOCK(p);
399 		goto out;
400 
401 	case T_PRIVINFLT|T_USER:	/* privileged instruction fault */
402 	case T_FPOPFLT|T_USER:		/* coprocessor operand fault */
403 		KERNEL_PROC_LOCK(p);
404 		(*p->p_emul->e_trapsignal)(p, SIGILL, type & ~T_USER);
405 		KERNEL_PROC_UNLOCK(p);
406 		goto out;
407 
408 	case T_ASTFLT|T_USER:		/* Allow process switch */
409 		uvmexp.softs++;
410 		if (p->p_flag & P_OWEUPC) {
411 			p->p_flag &= ~P_OWEUPC;
412 			KERNEL_PROC_LOCK(p);
413 			ADDUPROF(p);
414 			KERNEL_PROC_UNLOCK(p);
415 		}
416 		/* Allow a forced task switch. */
417 		if (curcpu()->ci_want_resched) /* XXX CSE me? */
418 			preempt(NULL);
419 		goto out;
420 
421 	case T_DNA|T_USER: {
422 #ifdef MATH_EMULATE
423 		int rv;
424 		if ((rv = math_emulate(&frame)) == 0) {
425 			if (frame.tf_eflags & PSL_T)
426 				goto trace;
427 			return;
428 		}
429 		KERNEL_PROC_LOCK(p);
430 		(*p->p_emul->e_trapsignal)(p, rv, type & ~T_USER);
431 		KERNEL_PROC_UNLOCK(p);
432 		goto out;
433 #else
434 		printf("pid %d killed due to lack of floating point\n",
435 		    p->p_pid);
436 		KERNEL_PROC_LOCK(p);
437 		(*p->p_emul->e_trapsignal)(p, SIGKILL, type & ~T_USER);
438 		KERNEL_PROC_UNLOCK(p);
439 		goto out;
440 #endif
441 	}
442 
443 	case T_BOUND|T_USER:
444 	case T_OFLOW|T_USER:
445 	case T_DIVIDE|T_USER:
446 		KERNEL_PROC_LOCK(p);
447 		(*p->p_emul->e_trapsignal)(p, SIGFPE, type & ~T_USER);
448 		KERNEL_PROC_UNLOCK(p);
449 		goto out;
450 
451 	case T_ARITHTRAP|T_USER:
452 		KERNEL_PROC_LOCK(p);
453 		(*p->p_emul->e_trapsignal)(p, SIGFPE,
454 		    frame.tf_err & ~TC_FLAGMASK);
455 		KERNEL_PROC_UNLOCK(p);
456 		goto out;
457 
458 	case T_PAGEFLT:			/* allow page faults in kernel mode */
459 		if (p == 0)
460 			goto we_re_toast;
461 #ifdef LOCKDEBUG
462 		/* If we page-fault while in scheduler, we're doomed. */
463 		if (simple_lock_held(&sched_lock))
464 			goto we_re_toast;
465 #endif
466 		/*
467 		 * fusubail is used by [fs]uswintr() to prevent page faulting
468 		 * from inside the profiling interrupt.
469 		 */
470 		if (pcb->pcb_onfault == fusubail)
471 			goto copyefault;
472 #ifdef MULTIPROCESSOR
473 		/*
474 		 * process doing kernel-mode page fault must have
475 		 * been running with big lock held
476 		 */
477 		if ((p->p_flag & P_BIGLOCK) == 0)
478 			goto we_re_toast;
479 #endif
480 
481 #if 0
482 		/* XXX - check only applies to 386's and 486's with WP off */
483 		if (frame.tf_err & PGEX_P)
484 			goto we_re_toast;
485 #endif
486 		cr2 = rcr2();
487 		KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
488 		goto faultcommon;
489 
490 	case T_PAGEFLT|T_USER: {	/* page fault */
491 		register vaddr_t va;
492 		register struct vmspace *vm;
493 		register struct vm_map *map;
494 		vm_prot_t ftype;
495 		extern struct vm_map *kernel_map;
496 		unsigned nss;
497 
498 		cr2 = rcr2();
499 		KERNEL_PROC_LOCK(p);
500 	faultcommon:
501 		vm = p->p_vmspace;
502 		if (vm == NULL)
503 			goto we_re_toast;
504 		pcb->pcb_cr2 = cr2;
505 		va = trunc_page((vaddr_t)pcb->pcb_cr2);
506 		/*
507 		 * It is only a kernel address space fault iff:
508 		 *	1. (type & T_USER) == 0  and
509 		 *	2. pcb_onfault not set or
510 		 *	3. pcb_onfault set but supervisor space fault
511 		 * The last can occur during an exec() copyin where the
512 		 * argument space is lazy-allocated.
513 		 */
514 		if (type == T_PAGEFLT && va >= KERNBASE)
515 			map = kernel_map;
516 		else
517 			map = &vm->vm_map;
518 		if (frame.tf_err & PGEX_W)
519 			ftype = VM_PROT_WRITE;
520 		else
521 			ftype = VM_PROT_READ;
522 
523 #ifdef DIAGNOSTIC
524 		if (map == kernel_map && va == 0) {
525 			printf("trap: bad kernel access at %lx\n", va);
526 			goto we_re_toast;
527 		}
528 #endif
529 
530 		nss = 0;
531 		if ((caddr_t)va >= vm->vm_maxsaddr
532 		    && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
533 		    && map != kernel_map) {
534 			nss = btoc(USRSTACK-(unsigned)va);
535 			if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
536 				/*
537 				 * We used to fail here. However, it may
538 				 * just have been an mmap()ed page low
539 				 * in the stack, which is legal. If it
540 				 * wasn't, uvm_fault() will fail below.
541 				 *
542 				 * Set nss to 0, since this case is not
543 				 * a "stack extension".
544 				 */
545 				nss = 0;
546 			}
547 		}
548 
549 		/* Fault the original page in. */
550 		onfault = pcb->pcb_onfault;
551 		pcb->pcb_onfault = NULL;
552 		error = uvm_fault(map, va, 0, ftype);
553 		pcb->pcb_onfault = onfault;
554 		if (error == 0) {
555 			if (nss > vm->vm_ssize)
556 				vm->vm_ssize = nss;
557 
558 			if (type == T_PAGEFLT) {
559 				KERNEL_UNLOCK();
560 				return;
561 			}
562 			KERNEL_PROC_UNLOCK(p);
563 			goto out;
564 		}
565 		if (error == EACCES) {
566 			error = EFAULT;
567 		}
568 
569 		if (type == T_PAGEFLT) {
570 			if (pcb->pcb_onfault != 0) {
571 				KERNEL_UNLOCK();
572 				goto copyfault;
573 			}
574 			printf("uvm_fault(%p, 0x%lx, 0, %d) -> %x\n",
575 			    map, va, ftype, error);
576 			goto we_re_toast;
577 		}
578 		if (error == ENOMEM) {
579 			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
580 			       p->p_pid, p->p_comm,
581 			       p->p_cred && p->p_ucred ?
582 			       p->p_ucred->cr_uid : -1);
583 			(*p->p_emul->e_trapsignal)(p, SIGKILL, T_PAGEFLT);
584 		} else {
585 			(*p->p_emul->e_trapsignal)(p, SIGSEGV, T_PAGEFLT);
586 		}
587 		if (type == T_PAGEFLT)
588 			KERNEL_UNLOCK();
589 		else
590 			KERNEL_PROC_UNLOCK(p);
591 		break;
592 	}
593 
594 	case T_TRCTRAP:
595 		/* Check whether they single-stepped into a lcall. */
596 		if (frame.tf_eip == (int)IDTVEC(osyscall))
597 			return;
598 		if (frame.tf_eip == (int)IDTVEC(osyscall) + 1) {
599 			frame.tf_eflags &= ~PSL_T;
600 			return;
601 		}
602 		goto we_re_toast;
603 
604 	case T_BPTFLT|T_USER:		/* bpt instruction fault */
605 	case T_TRCTRAP|T_USER:		/* trace trap */
606 #ifdef MATH_EMULATE
607 	trace:
608 #endif
609 		/*
610 		 * Don't go single-stepping into a RAS.
611 		 */
612 		if ((p->p_nras == 0) ||
613 		    (ras_lookup(p, (caddr_t)frame.tf_eip) == (caddr_t)-1)) {
614 			KERNEL_PROC_LOCK(p);
615 			(*p->p_emul->e_trapsignal)(p, SIGTRAP, type & ~T_USER);
616 			KERNEL_PROC_UNLOCK(p);
617 		}
618 		break;
619 
620 #if	NISA > 0 || NMCA > 0
621 	case T_NMI:
622 #if defined(KGDB) || defined(DDB)
623 		/* NMI can be hooked up to a pushbutton for debugging */
624 		printf ("NMI ... going to debugger\n");
625 #ifdef KGDB
626 
627 		if (kgdb_trap(type, &frame))
628 			return;
629 #endif
630 #ifdef DDB
631 		if (kdb_trap(type, 0, &frame))
632 			return;
633 #endif
634 #endif /* KGDB || DDB */
635 		/* machine/parity/power fail/"kitchen sink" faults */
636 
637 #if NMCA > 0
638 		/* mca_nmi() takes care to call i386_nmi() if appropriate */
639 		if (mca_nmi() != 0)
640 			goto we_re_toast;
641 		else
642 			return;
643 #else /* NISA > 0 */
644 		if (i386_nmi() != 0)
645 			goto we_re_toast;
646 		else
647 			return;
648 #endif /* NMCA > 0 */
649 #endif /* NISA > 0 || NMCA > 0 */
650 	}
651 
652 	if ((type & T_USER) == 0)
653 		return;
654 out:
655 	userret(p);
656 }
657 
658 #if defined(I386_CPU)
659 
660 #ifdef MULTIPROCESSOR
661 /* XXX XXX XXX */
662 #endif
663 /*
664  * Compensate for 386 brain damage (missing URKR)
665  */
666 int
667 trapwrite(addr)
668 	unsigned addr;
669 {
670 	vaddr_t va;
671 	unsigned nss;
672 	struct proc *p;
673 	struct vmspace *vm;
674 
675 	va = trunc_page((vaddr_t)addr);
676 	if (va >= VM_MAXUSER_ADDRESS)
677 		return 1;
678 
679 	nss = 0;
680 	p = curproc;
681 	vm = p->p_vmspace;
682 	if ((caddr_t)va >= vm->vm_maxsaddr) {
683 		nss = btoc(USRSTACK-(unsigned)va);
684 		if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
685 			nss = 0;
686 	}
687 
688 	if (uvm_fault(&vm->vm_map, va, 0, VM_PROT_WRITE) != 0)
689 		return 1;
690 
691 	if (nss > vm->vm_ssize)
692 		vm->vm_ssize = nss;
693 
694 	return 0;
695 }
696 #endif /* I386_CPU */
697