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