1 /* $NetBSD: trap.c,v 1.165 2002/02/18 15:58:02 simonb 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.165 2002/02/18 15:58:02 simonb 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_cputype.h" 89 90 #include <sys/param.h> 91 #include <sys/systm.h> 92 #include <sys/proc.h> 93 #include <sys/user.h> 94 #include <sys/acct.h> 95 #include <sys/kernel.h> 96 #include <sys/signal.h> 97 #include <sys/syscall.h> 98 99 #include <uvm/uvm_extern.h> 100 101 #include <machine/cpu.h> 102 #include <machine/cpufunc.h> 103 #include <machine/psl.h> 104 #include <machine/reg.h> 105 #include <machine/trap.h> 106 #include <machine/userret.h> 107 #ifdef DDB 108 #include <machine/db_machdep.h> 109 #endif 110 111 #include "mca.h" 112 #if NMCA > 0 113 #include <machine/mca_machdep.h> 114 #endif 115 116 #include "isa.h" 117 118 #ifdef KGDB 119 #include <sys/kgdb.h> 120 #endif 121 122 #include "npx.h" 123 124 void trap __P((struct trapframe)); 125 #if defined(I386_CPU) 126 int trapwrite __P((unsigned)); 127 #endif 128 129 const char *trap_type[] = { 130 "privileged instruction fault", /* 0 T_PRIVINFLT */ 131 "breakpoint trap", /* 1 T_BPTFLT */ 132 "arithmetic trap", /* 2 T_ARITHTRAP */ 133 "asynchronous system trap", /* 3 T_ASTFLT */ 134 "protection fault", /* 4 T_PROTFLT */ 135 "trace trap", /* 5 T_TRCTRAP */ 136 "page fault", /* 6 T_PAGEFLT */ 137 "alignment fault", /* 7 T_ALIGNFLT */ 138 "integer divide fault", /* 8 T_DIVIDE */ 139 "non-maskable interrupt", /* 9 T_NMI */ 140 "overflow trap", /* 10 T_OFLOW */ 141 "bounds check fault", /* 11 T_BOUND */ 142 "FPU not available fault", /* 12 T_DNA */ 143 "double fault", /* 13 T_DOUBLEFLT */ 144 "FPU operand fetch fault", /* 14 T_FPOPFLT */ 145 "invalid TSS fault", /* 15 T_TSSFLT */ 146 "segment not present fault", /* 16 T_SEGNPFLT */ 147 "stack fault", /* 17 T_STKFLT */ 148 "reserved trap", /* 18 T_RESERVED */ 149 }; 150 int trap_types = sizeof trap_type / sizeof trap_type[0]; 151 152 #ifdef DEBUG 153 int trapdebug = 0; 154 #endif 155 156 #define IDTVEC(name) __CONCAT(X, name) 157 158 /* 159 * trap(frame): 160 * Exception, fault, and trap interface to BSD kernel. This 161 * common code is called from assembly language IDT gate entry 162 * routines that prepare a suitable stack frame, and restore this 163 * frame after the exception has been processed. Note that the 164 * effect is as if the arguments were passed call by reference. 165 */ 166 /*ARGSUSED*/ 167 void 168 trap(frame) 169 struct trapframe frame; 170 { 171 register struct proc *p = curproc; 172 int type = frame.tf_trapno; 173 struct pcb *pcb; 174 extern char fusubail[], 175 resume_iret[], resume_pop_ds[], resume_pop_es[], 176 resume_pop_fs[], resume_pop_gs[], 177 IDTVEC(osyscall)[]; 178 struct trapframe *vframe; 179 int resume; 180 caddr_t onfault; 181 int error; 182 183 uvmexp.traps++; 184 185 pcb = (p != NULL) ? &p->p_addr->u_pcb : NULL; 186 #ifdef DEBUG 187 if (trapdebug) { 188 printf("trap %d code %x eip %x cs %x eflags %x cr2 %x cpl %x\n", 189 frame.tf_trapno, frame.tf_err, frame.tf_eip, frame.tf_cs, 190 frame.tf_eflags, rcr2(), cpl); 191 printf("curproc %p\n", curproc); 192 } 193 #endif 194 195 if (!KERNELMODE(frame.tf_cs, frame.tf_eflags)) { 196 type |= T_USER; 197 p->p_md.md_regs = &frame; 198 pcb->pcb_cr2 = 0; 199 } 200 201 switch (type) { 202 203 default: 204 we_re_toast: 205 #ifdef KGDB 206 if (kgdb_trap(type, &frame)) 207 return; 208 else { 209 /* 210 * If this is a breakpoint, don't panic 211 * if we're not connected. 212 */ 213 if (type == T_BPTFLT) { 214 printf("kgdb: ignored %s\n", trap_type[type]); 215 return; 216 } 217 } 218 #endif 219 #ifdef DDB 220 if (kdb_trap(type, 0, &frame)) 221 return; 222 #endif 223 if (frame.tf_trapno < trap_types) 224 printf("fatal %s", trap_type[frame.tf_trapno]); 225 else 226 printf("unknown trap %d", frame.tf_trapno); 227 printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor"); 228 printf("trap type %d code %x eip %x cs %x eflags %x cr2 %x cpl %x\n", 229 type, frame.tf_err, frame.tf_eip, frame.tf_cs, frame.tf_eflags, rcr2(), cpl); 230 231 panic("trap"); 232 /*NOTREACHED*/ 233 234 case T_PROTFLT: 235 case T_SEGNPFLT: 236 case T_ALIGNFLT: 237 case T_TSSFLT: 238 /* Check for copyin/copyout fault. */ 239 if (pcb->pcb_onfault != 0) { 240 copyefault: 241 error = EFAULT; 242 copyfault: 243 frame.tf_eip = (int)pcb->pcb_onfault; 244 frame.tf_eax = error; 245 return; 246 } 247 248 /* 249 * Check for failure during return to user mode. 250 * 251 * We do this by looking at the instruction we faulted on. The 252 * specific instructions we recognize only happen when 253 * returning from a trap, syscall, or interrupt. 254 * 255 * At this point, there are (at least) two trap frames on 256 * the kernel stack; we presume here that we faulted while 257 * loading our registers out of the outer one. 258 * 259 * The inner frame does not involve a ring crossing, so it 260 * ends right before &frame.tf_esp. The outer frame has 261 * been partially consumed by the INTRFASTEXIT; exactly 262 * how much depends which register we were popping when we 263 * faulted, so we compute the outer frame address based on 264 * register-dependant offsets computed from &frame.tf_esp 265 * below. To decide whether this was a kernel-mode or 266 * user-mode error, we look at this outer frame's tf_cs 267 * and tf_eflags, which are (fortunately) not consumed until 268 * the final instruction of INTRFASTEXIT. 269 * 270 * XXX 271 * The heuristic used here will currently fail for the case of 272 * one of the 2 pop instructions faulting when returning from a 273 * a fast interrupt. This should not be possible. It can be 274 * fixed by rearranging the trap frame so that the stack format 275 * at this point is the same as on exit from a `slow' 276 * interrupt. 277 */ 278 switch (*(u_char *)frame.tf_eip) { 279 case 0xcf: /* iret */ 280 vframe = (void *)((int)&frame.tf_esp - 281 offsetof(struct trapframe, tf_eip)); 282 resume = (int)resume_iret; 283 break; 284 case 0x1f: /* popl %ds */ 285 vframe = (void *)((int)&frame.tf_esp - 286 offsetof(struct trapframe, tf_ds)); 287 resume = (int)resume_pop_ds; 288 break; 289 case 0x07: /* popl %es */ 290 vframe = (void *)((int)&frame.tf_esp - 291 offsetof(struct trapframe, tf_es)); 292 resume = (int)resume_pop_es; 293 break; 294 case 0x0f: /* 0x0f prefix */ 295 switch (*(u_char *)(frame.tf_eip+1)) { 296 case 0xa1: /* popl %fs */ 297 vframe = (void *)((int)&frame.tf_esp - 298 offsetof(struct trapframe, tf_fs)); 299 resume = (int)resume_pop_fs; 300 break; 301 case 0xa9: /* popl %gs */ 302 vframe = (void *)((int)&frame.tf_esp - 303 offsetof(struct trapframe, tf_gs)); 304 resume = (int)resume_pop_gs; 305 break; 306 } 307 break; 308 default: 309 goto we_re_toast; 310 } 311 if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags)) 312 goto we_re_toast; 313 314 frame.tf_eip = resume; 315 return; 316 317 case T_PROTFLT|T_USER: /* protection fault */ 318 #ifdef VM86 319 if (frame.tf_eflags & PSL_VM) { 320 vm86_gpfault(p, type & ~T_USER); 321 goto out; 322 } 323 #endif 324 case T_TSSFLT|T_USER: 325 case T_SEGNPFLT|T_USER: 326 case T_STKFLT|T_USER: 327 case T_ALIGNFLT|T_USER: 328 case T_NMI|T_USER: 329 (*p->p_emul->e_trapsignal)(p, SIGBUS, type & ~T_USER); 330 goto out; 331 332 case T_PRIVINFLT|T_USER: /* privileged instruction fault */ 333 case T_FPOPFLT|T_USER: /* coprocessor operand fault */ 334 (*p->p_emul->e_trapsignal)(p, SIGILL, type & ~T_USER); 335 goto out; 336 337 case T_ASTFLT|T_USER: /* Allow process switch */ 338 uvmexp.softs++; 339 if (p->p_flag & P_OWEUPC) { 340 p->p_flag &= ~P_OWEUPC; 341 ADDUPROF(p); 342 } 343 /* Allow a forced task switch. */ 344 if (want_resched) 345 preempt(NULL); 346 goto out; 347 348 case T_DNA|T_USER: { 349 #ifdef MATH_EMULATE 350 int rv; 351 if ((rv = math_emulate(&frame)) == 0) { 352 if (frame.tf_eflags & PSL_T) 353 goto trace; 354 return; 355 } 356 (*p->p_emul->e_trapsignal)(p, rv, type & ~T_USER); 357 goto out; 358 #else 359 printf("pid %d killed due to lack of floating point\n", 360 p->p_pid); 361 (*p->p_emul->e_trapsignal)(p, SIGKILL, type & ~T_USER); 362 goto out; 363 #endif 364 } 365 366 case T_BOUND|T_USER: 367 case T_OFLOW|T_USER: 368 case T_DIVIDE|T_USER: 369 (*p->p_emul->e_trapsignal)(p, SIGFPE, type & ~T_USER); 370 goto out; 371 372 case T_ARITHTRAP|T_USER: 373 (*p->p_emul->e_trapsignal)(p, SIGFPE, frame.tf_err); 374 goto out; 375 376 case T_PAGEFLT: /* allow page faults in kernel mode */ 377 if (p == 0) 378 goto we_re_toast; 379 /* 380 * fusubail is used by [fs]uswintr() to prevent page faulting 381 * from inside the profiling interrupt. 382 */ 383 if (pcb->pcb_onfault == fusubail) 384 goto copyefault; 385 #if 0 386 /* XXX - check only applies to 386's and 486's with WP off */ 387 if (frame.tf_err & PGEX_P) 388 goto we_re_toast; 389 #endif 390 /* FALLTHROUGH */ 391 392 case T_PAGEFLT|T_USER: { /* page fault */ 393 register vaddr_t va; 394 register struct vmspace *vm = p->p_vmspace; 395 register struct vm_map *map; 396 vm_prot_t ftype; 397 extern struct vm_map *kernel_map; 398 unsigned nss; 399 400 if (vm == NULL) 401 goto we_re_toast; 402 pcb->pcb_cr2 = rcr2(); 403 va = trunc_page((vaddr_t)pcb->pcb_cr2); 404 /* 405 * It is only a kernel address space fault iff: 406 * 1. (type & T_USER) == 0 and 407 * 2. pcb_onfault not set or 408 * 3. pcb_onfault set but supervisor space fault 409 * The last can occur during an exec() copyin where the 410 * argument space is lazy-allocated. 411 */ 412 if (type == T_PAGEFLT && va >= KERNBASE) 413 map = kernel_map; 414 else 415 map = &vm->vm_map; 416 if (frame.tf_err & PGEX_W) 417 ftype = VM_PROT_WRITE; 418 else 419 ftype = VM_PROT_READ; 420 421 #ifdef DIAGNOSTIC 422 if (map == kernel_map && va == 0) { 423 printf("trap: bad kernel access at %lx\n", va); 424 goto we_re_toast; 425 } 426 #endif 427 428 nss = 0; 429 if ((caddr_t)va >= vm->vm_maxsaddr 430 && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS 431 && map != kernel_map) { 432 nss = btoc(USRSTACK-(unsigned)va); 433 if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) { 434 /* 435 * We used to fail here. However, it may 436 * just have been an mmap()ed page low 437 * in the stack, which is legal. If it 438 * wasn't, uvm_fault() will fail below. 439 * 440 * Set nss to 0, since this case is not 441 * a "stack extension". 442 */ 443 nss = 0; 444 } 445 } 446 447 /* Fault the original page in. */ 448 onfault = pcb->pcb_onfault; 449 pcb->pcb_onfault = NULL; 450 error = uvm_fault(map, va, 0, ftype); 451 pcb->pcb_onfault = onfault; 452 if (error == 0) { 453 if (nss > vm->vm_ssize) 454 vm->vm_ssize = nss; 455 456 if (type == T_PAGEFLT) 457 return; 458 goto out; 459 } 460 if (error == EACCES) { 461 error = EFAULT; 462 } 463 464 if (type == T_PAGEFLT) { 465 if (pcb->pcb_onfault != 0) 466 goto copyfault; 467 printf("uvm_fault(%p, 0x%lx, 0, %d) -> %x\n", 468 map, va, ftype, error); 469 goto we_re_toast; 470 } 471 if (error == ENOMEM) { 472 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 473 p->p_pid, p->p_comm, 474 p->p_cred && p->p_ucred ? 475 p->p_ucred->cr_uid : -1); 476 (*p->p_emul->e_trapsignal)(p, SIGKILL, T_PAGEFLT); 477 } else { 478 (*p->p_emul->e_trapsignal)(p, SIGSEGV, T_PAGEFLT); 479 } 480 break; 481 } 482 483 case T_TRCTRAP: 484 /* Check whether they single-stepped into a lcall. */ 485 if (frame.tf_eip == (int)IDTVEC(osyscall)) 486 return; 487 if (frame.tf_eip == (int)IDTVEC(osyscall) + 1) { 488 frame.tf_eflags &= ~PSL_T; 489 return; 490 } 491 goto we_re_toast; 492 493 case T_BPTFLT|T_USER: /* bpt instruction fault */ 494 case T_TRCTRAP|T_USER: /* trace trap */ 495 #ifdef MATH_EMULATE 496 trace: 497 #endif 498 (*p->p_emul->e_trapsignal)(p, SIGTRAP, type & ~T_USER); 499 break; 500 501 #if NISA > 0 || NMCA > 0 502 case T_NMI: 503 #if defined(KGDB) || defined(DDB) 504 /* NMI can be hooked up to a pushbutton for debugging */ 505 printf ("NMI ... going to debugger\n"); 506 #ifdef KGDB 507 508 if (kgdb_trap(type, &frame)) 509 return; 510 #endif 511 #ifdef DDB 512 if (kdb_trap(type, 0, &frame)) 513 return; 514 #endif 515 #endif /* KGDB || DDB */ 516 /* machine/parity/power fail/"kitchen sink" faults */ 517 518 #if NMCA > 0 519 /* mca_nmi() takes care to call isa_nmi() if appropriate */ 520 if (mca_nmi() != 0) 521 goto we_re_toast; 522 else 523 return; 524 #else /* NISA > 0 */ 525 if (isa_nmi() != 0) 526 goto we_re_toast; 527 else 528 return; 529 #endif /* NMCA > 0 */ 530 #endif /* NISA > 0 || NMCA > 0 */ 531 } 532 533 if ((type & T_USER) == 0) 534 return; 535 out: 536 userret(p); 537 } 538 539 #if defined(I386_CPU) 540 /* 541 * Compensate for 386 brain damage (missing URKR) 542 */ 543 int 544 trapwrite(addr) 545 unsigned addr; 546 { 547 vaddr_t va; 548 unsigned nss; 549 struct proc *p; 550 struct vmspace *vm; 551 552 va = trunc_page((vaddr_t)addr); 553 if (va >= VM_MAXUSER_ADDRESS) 554 return 1; 555 556 nss = 0; 557 p = curproc; 558 vm = p->p_vmspace; 559 if ((caddr_t)va >= vm->vm_maxsaddr) { 560 nss = btoc(USRSTACK-(unsigned)va); 561 if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) 562 nss = 0; 563 } 564 565 if (uvm_fault(&vm->vm_map, va, 0, VM_PROT_WRITE) != 0) 566 return 1; 567 568 if (nss > vm->vm_ssize) 569 vm->vm_ssize = nss; 570 571 return 0; 572 } 573 #endif /* I386_CPU */ 574