FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/trap.c
1 /*-
2 * Copyright (C) 1994, David Greenman
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the University of Utah, and William Jolitz.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * from: @(#)trap.c 7.4 (Berkeley) 5/13/91
38 * $FreeBSD: src/sys/i386/i386/trap.c,v 1.83.2.11 1999/09/05 08:11:18 peter Exp $
39 */
40
41 /*
42 * 386 Trap and System call handling
43 */
44
45 #include "opt_cpu.h"
46 #include "opt_ddb.h"
47 #include "opt_ktrace.h"
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/proc.h>
52 #include <sys/acct.h>
53 #include <sys/kernel.h>
54 #include <sys/syscall.h>
55 #include <sys/sysent.h>
56 #include <sys/queue.h>
57 #include <sys/vmmeter.h>
58 #ifdef KTRACE
59 #include <sys/ktrace.h>
60 #endif
61
62 #include <vm/vm.h>
63 #include <vm/vm_param.h>
64 #include <vm/vm_prot.h>
65 #include <vm/lock.h>
66 #include <vm/pmap.h>
67 #include <vm/vm_kern.h>
68 #include <vm/vm_map.h>
69 #include <vm/vm_page.h>
70 #include <vm/vm_extern.h>
71
72 #include <sys/user.h>
73
74 #include <machine/cpu.h>
75 #include <machine/md_var.h>
76 #include <machine/psl.h>
77 #include <machine/reg.h>
78 #include <machine/trap.h>
79 #include <machine/../isa/isa_device.h>
80
81 #ifdef POWERFAIL_NMI
82 #include <sys/syslog.h>
83 #include <machine/clock.h>
84 #endif
85
86 #include "isa.h"
87 #include "npx.h"
88
89 int (*pmath_emulate) __P((struct trapframe *));
90
91 extern void trap __P((struct trapframe frame));
92 extern int trapwrite __P((unsigned addr));
93 extern void syscall __P((struct trapframe frame));
94
95 static int trap_pfault __P((struct trapframe *, int));
96 static void trap_fatal __P((struct trapframe *));
97 void dblfault_handler __P((void));
98
99 extern inthand_t IDTVEC(syscall);
100
101 #define MAX_TRAP_MSG 28
102 static char *trap_msg[] = {
103 "", /* 0 unused */
104 "privileged instruction fault", /* 1 T_PRIVINFLT */
105 "", /* 2 unused */
106 "breakpoint instruction fault", /* 3 T_BPTFLT */
107 "", /* 4 unused */
108 "", /* 5 unused */
109 "arithmetic trap", /* 6 T_ARITHTRAP */
110 "system forced exception", /* 7 T_ASTFLT */
111 "", /* 8 unused */
112 "general protection fault", /* 9 T_PROTFLT */
113 "trace trap", /* 10 T_TRCTRAP */
114 "", /* 11 unused */
115 "page fault", /* 12 T_PAGEFLT */
116 "", /* 13 unused */
117 "alignment fault", /* 14 T_ALIGNFLT */
118 "", /* 15 unused */
119 "", /* 16 unused */
120 "", /* 17 unused */
121 "integer divide fault", /* 18 T_DIVIDE */
122 "non-maskable interrupt trap", /* 19 T_NMI */
123 "overflow trap", /* 20 T_OFLOW */
124 "FPU bounds check fault", /* 21 T_BOUND */
125 "FPU device not available", /* 22 T_DNA */
126 "double fault", /* 23 T_DOUBLEFLT */
127 "FPU operand fetch fault", /* 24 T_FPOPFLT */
128 "invalid TSS fault", /* 25 T_TSSFLT */
129 "segment not present fault", /* 26 T_SEGNPFLT */
130 "stack fault", /* 27 T_STKFLT */
131 "machine check trap", /* 28 T_MCHK */
132 };
133
134 static void userret __P((struct proc *p, struct trapframe *frame,
135 u_quad_t oticks));
136
137 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
138 extern struct gate_descriptor *t_idt;
139 extern int has_f00f_bug;
140 #endif
141
142 static __inline void
143 userret(p, frame, oticks)
144 struct proc *p;
145 struct trapframe *frame;
146 u_quad_t oticks;
147 {
148 int sig, s;
149
150 while ((sig = CURSIG(p)) != 0)
151 postsig(sig);
152 p->p_priority = p->p_usrpri;
153 if (want_resched) {
154 /*
155 * Since we are curproc, clock will normally just change
156 * our priority without moving us from one queue to another
157 * (since the running process is not on a queue.)
158 * If that happened after we setrunqueue ourselves but before we
159 * mi_switch()'ed, we might not be on the queue indicated by
160 * our priority.
161 */
162 s = splhigh();
163 setrunqueue(p);
164 p->p_stats->p_ru.ru_nivcsw++;
165 mi_switch();
166 splx(s);
167 while ((sig = CURSIG(p)) != 0)
168 postsig(sig);
169 }
170 /*
171 * Charge system time if profiling.
172 */
173 if (p->p_flag & P_PROFIL)
174 addupc_task(p, frame->tf_eip,
175 (u_int)(p->p_sticks - oticks) * psratio);
176
177 curpriority = p->p_priority;
178 }
179
180 /*
181 * Exception, fault, and trap interface to the FreeBSD kernel.
182 * This common code is called from assembly language IDT gate entry
183 * routines that prepare a suitable stack frame, and restore this
184 * frame after the exception has been processed.
185 */
186
187 void
188 trap(frame)
189 struct trapframe frame;
190 {
191 struct proc *p = curproc;
192 u_quad_t sticks = 0;
193 int i = 0, ucode = 0, type, code;
194 #ifdef DEBUG
195 u_long eva;
196 #endif
197
198 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
199 restart:
200 #endif
201 type = frame.tf_trapno;
202 code = frame.tf_err;
203
204 if (ISPL(frame.tf_cs) == SEL_UPL) {
205 /* user trap */
206
207 sticks = p->p_sticks;
208 p->p_md.md_regs = (int *)&frame;
209
210 switch (type) {
211 case T_PRIVINFLT: /* privileged instruction fault */
212 ucode = type;
213 i = SIGILL;
214 break;
215
216 case T_BPTFLT: /* bpt instruction fault */
217 case T_TRCTRAP: /* trace trap */
218 frame.tf_eflags &= ~PSL_T;
219 i = SIGTRAP;
220 break;
221
222 case T_ARITHTRAP: /* arithmetic trap */
223 ucode = code;
224 i = SIGFPE;
225 break;
226
227 case T_ASTFLT: /* Allow process switch */
228 astoff();
229 cnt.v_soft++;
230 if (p->p_flag & P_OWEUPC) {
231 p->p_flag &= ~P_OWEUPC;
232 addupc_task(p, p->p_stats->p_prof.pr_addr,
233 p->p_stats->p_prof.pr_ticks);
234 }
235 goto out;
236
237 case T_PROTFLT: /* general protection fault */
238 case T_SEGNPFLT: /* segment not present fault */
239 case T_STKFLT: /* stack fault */
240 case T_TSSFLT: /* invalid TSS fault */
241 case T_DOUBLEFLT: /* double fault */
242 default:
243 ucode = code + BUS_SEGM_FAULT ;
244 i = SIGBUS;
245 break;
246
247 case T_PAGEFLT: /* page fault */
248 i = trap_pfault(&frame, TRUE);
249 if (i == -1)
250 return;
251 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
252 if (i == -2)
253 goto restart;
254 #endif
255 if (i == 0)
256 goto out;
257
258 ucode = T_PAGEFLT;
259 break;
260
261 case T_DIVIDE: /* integer divide fault */
262 ucode = FPE_INTDIV_TRAP;
263 i = SIGFPE;
264 break;
265
266 #if NISA > 0
267 case T_NMI:
268 #ifdef POWERFAIL_NMI
269 goto handle_powerfail;
270 #else /* !POWERFAIL_NMI */
271 #ifdef DDB
272 /* NMI can be hooked up to a pushbutton for debugging */
273 printf ("NMI ... going to debugger\n");
274 if (kdb_trap (type, 0, &frame))
275 return;
276 #endif /* DDB */
277 /* machine/parity/power fail/"kitchen sink" faults */
278 if (isa_nmi(code) == 0) return;
279 panic("NMI indicates hardware failure");
280 #endif /* POWERFAIL_NMI */
281 #endif /* NISA > 0 */
282
283 case T_OFLOW: /* integer overflow fault */
284 ucode = FPE_INTOVF_TRAP;
285 i = SIGFPE;
286 break;
287
288 case T_BOUND: /* bounds check fault */
289 ucode = FPE_SUBRNG_TRAP;
290 i = SIGFPE;
291 break;
292
293 case T_DNA:
294 #if NNPX > 0
295 /* if a transparent fault (due to context switch "late") */
296 if (npxdna())
297 return;
298 #endif
299 if (!pmath_emulate) {
300 i = SIGFPE;
301 ucode = FPE_FPU_NP_TRAP;
302 break;
303 }
304 i = (*pmath_emulate)(&frame);
305 if (i == 0) {
306 if (!(frame.tf_eflags & PSL_T))
307 return;
308 frame.tf_eflags &= ~PSL_T;
309 i = SIGTRAP;
310 }
311 /* else ucode = emulator_only_knows() XXX */
312 break;
313
314 case T_FPOPFLT: /* FPU operand fetch fault */
315 ucode = T_FPOPFLT;
316 i = SIGILL;
317 break;
318 }
319 } else {
320 /* kernel trap */
321
322 switch (type) {
323 case T_PAGEFLT: /* page fault */
324 (void) trap_pfault(&frame, FALSE);
325 return;
326
327 case T_DNA:
328 #if NNPX > 0
329 /*
330 * The kernel is apparently using npx for copying.
331 * XXX this should be fatal unless the kernel has
332 * registered such use.
333 */
334 if (npxdna())
335 return;
336 #endif
337 break;
338
339 case T_PROTFLT: /* general protection fault */
340 case T_SEGNPFLT: /* segment not present fault */
341 /*
342 * Invalid segment selectors and out of bounds
343 * %eip's and %esp's can be set up in user mode.
344 * This causes a fault in kernel mode when the
345 * kernel tries to return to user mode. We want
346 * to get this fault so that we can fix the
347 * problem here and not have to check all the
348 * selectors and pointers when the user changes
349 * them.
350 */
351 #define MAYBE_DORETI_FAULT(where, whereto) \
352 do { \
353 if (frame.tf_eip == (int)where) { \
354 frame.tf_eip = (int)whereto; \
355 return; \
356 } \
357 } while (0)
358
359 if (intr_nesting_level == 0) {
360 MAYBE_DORETI_FAULT(doreti_iret,
361 doreti_iret_fault);
362 MAYBE_DORETI_FAULT(doreti_popl_ds,
363 doreti_popl_ds_fault);
364 MAYBE_DORETI_FAULT(doreti_popl_es,
365 doreti_popl_es_fault);
366 if (curpcb && curpcb->pcb_onfault) {
367 frame.tf_eip = (int)curpcb->pcb_onfault;
368 return;
369 }
370 }
371 break;
372
373 case T_TSSFLT:
374 /*
375 * PSL_NT can be set in user mode and isn't cleared
376 * automatically when the kernel is entered. This
377 * causes a TSS fault when the kernel attempts to
378 * `iret' because the TSS link is uninitialized. We
379 * want to get this fault so that we can fix the
380 * problem here and not every time the kernel is
381 * entered.
382 */
383 if (frame.tf_eflags & PSL_NT) {
384 frame.tf_eflags &= ~PSL_NT;
385 return;
386 }
387 break;
388
389 case T_TRCTRAP: /* trace trap */
390 if (frame.tf_eip == (int)IDTVEC(syscall)) {
391 /*
392 * We've just entered system mode via the
393 * syscall lcall. Continue single stepping
394 * silently until the syscall handler has
395 * saved the flags.
396 */
397 return;
398 }
399 if (frame.tf_eip == (int)IDTVEC(syscall) + 1) {
400 /*
401 * The syscall handler has now saved the
402 * flags. Stop single stepping it.
403 */
404 frame.tf_eflags &= ~PSL_T;
405 return;
406 }
407 /*
408 * Fall through.
409 */
410 case T_BPTFLT:
411 /*
412 * If DDB is enabled, let it handle the debugger trap.
413 * Otherwise, debugger traps "can't happen".
414 */
415 #ifdef DDB
416 if (kdb_trap (type, 0, &frame))
417 return;
418 #endif
419 break;
420
421 #if NISA > 0
422 case T_NMI:
423 #ifdef POWERFAIL_NMI
424 #ifndef TIMER_FREQ
425 # define TIMER_FREQ 1193182
426 #endif
427 handle_powerfail:
428 {
429 static unsigned lastalert = 0;
430
431 if(time.tv_sec - lastalert > 10)
432 {
433 log(LOG_WARNING, "NMI: power fail\n");
434 sysbeep(TIMER_FREQ/880, hz);
435 lastalert = time.tv_sec;
436 }
437 return;
438 }
439 #else /* !POWERFAIL_NMI */
440 #ifdef DDB
441 /* NMI can be hooked up to a pushbutton for debugging */
442 printf ("NMI ... going to debugger\n");
443 if (kdb_trap (type, 0, &frame))
444 return;
445 #endif /* DDB */
446 /* machine/parity/power fail/"kitchen sink" faults */
447 if (isa_nmi(code) == 0) return;
448 /* FALL THROUGH */
449 #endif /* POWERFAIL_NMI */
450 #endif /* NISA > 0 */
451 }
452
453 trap_fatal(&frame);
454 return;
455 }
456
457 /* Translate fault for emulators (e.g. Linux) */
458 if (*p->p_sysent->sv_transtrap)
459 i = (*p->p_sysent->sv_transtrap)(i, type);
460
461 trapsignal(p, i, ucode);
462
463 #ifdef DEBUG
464 eva = rcr2();
465 if (type <= MAX_TRAP_MSG) {
466 uprintf("fatal process exception: %s",
467 trap_msg[type]);
468 if ((type == T_PAGEFLT) || (type == T_PROTFLT))
469 uprintf(", fault VA = 0x%x", eva);
470 uprintf("\n");
471 }
472 #endif
473
474 out:
475 userret(p, &frame, sticks);
476 }
477
478 #ifdef notyet
479 /*
480 * This version doesn't allow a page fault to user space while
481 * in the kernel. The rest of the kernel needs to be made "safe"
482 * before this can be used. I think the only things remaining
483 * to be made safe are the iBCS2 code and the process tracing/
484 * debugging code.
485 */
486 static int
487 trap_pfault(frame, usermode)
488 struct trapframe *frame;
489 int usermode;
490 {
491 vm_offset_t va;
492 struct vmspace *vm = NULL;
493 vm_map_t map = 0;
494 int rv = 0;
495 vm_prot_t ftype;
496 int eva;
497 struct proc *p = curproc;
498
499 if (frame->tf_err & PGEX_W)
500 ftype = VM_PROT_READ | VM_PROT_WRITE;
501 else
502 ftype = VM_PROT_READ;
503
504 eva = rcr2();
505 va = trunc_page((vm_offset_t)eva);
506
507 if (va < VM_MIN_KERNEL_ADDRESS) {
508 vm_offset_t v;
509 vm_page_t mpte;
510
511 if (p == NULL ||
512 (!usermode && va < VM_MAXUSER_ADDRESS &&
513 (intr_nesting_level != 0 || curpcb == NULL ||
514 curpcb->pcb_onfault == NULL))) {
515 trap_fatal(frame);
516 return (-1);
517 }
518
519 /*
520 * This is a fault on non-kernel virtual memory.
521 * vm is initialized above to NULL. If curproc is NULL
522 * or curproc->p_vmspace is NULL the fault is fatal.
523 */
524 vm = p->p_vmspace;
525 if (vm == NULL)
526 goto nogo;
527
528 map = &vm->vm_map;
529
530 /*
531 * Keep swapout from messing with us during this
532 * critical time.
533 */
534 ++p->p_lock;
535
536 /*
537 * Grow the stack if necessary
538 */
539 if ((caddr_t)va > vm->vm_maxsaddr
540 && (caddr_t)va < (caddr_t)USRSTACK) {
541 if (!grow(p, va)) {
542 rv = KERN_FAILURE;
543 --p->p_lock;
544 goto nogo;
545 }
546 }
547
548 /* Fault in the user page: */
549 rv = vm_fault(map, va, ftype,
550 (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY : 0);
551
552 --p->p_lock;
553 } else {
554 /*
555 * Don't allow user-mode faults in kernel address space.
556 */
557 if (usermode)
558 goto nogo;
559
560 /*
561 * Since we know that kernel virtual address addresses
562 * always have pte pages mapped, we just have to fault
563 * the page.
564 */
565 rv = vm_fault(kernel_map, va, ftype, FALSE);
566 }
567
568 if (rv == KERN_SUCCESS)
569 return (0);
570 nogo:
571 if (!usermode) {
572 if (intr_nesting_level == 0 && curpcb && curpcb->pcb_onfault) {
573 frame->tf_eip = (int)curpcb->pcb_onfault;
574 return (0);
575 }
576 trap_fatal(frame);
577 return (-1);
578 }
579
580 /* kludge to pass faulting virtual address to sendsig */
581 frame->tf_err = eva;
582
583 return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
584 }
585 #endif
586
587 int
588 trap_pfault(frame, usermode)
589 struct trapframe *frame;
590 int usermode;
591 {
592 vm_offset_t va;
593 struct vmspace *vm = NULL;
594 vm_map_t map = 0;
595 int rv = 0;
596 vm_prot_t ftype;
597 int eva;
598 struct proc *p = curproc;
599
600 eva = rcr2();
601 va = trunc_page((vm_offset_t)eva);
602
603 if (va >= KERNBASE) {
604 /*
605 * Don't allow user-mode faults in kernel address space.
606 * An exception: if the faulting address is the invalid
607 * instruction entry in the IDT, then the Intel Pentium
608 * F00F bug workaround was triggered, and we need to
609 * treat it is as an illegal instruction, and not a page
610 * fault.
611 */
612 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
613 if ((eva == (unsigned int)&t_idt[6]) && has_f00f_bug) {
614 frame->tf_trapno = T_PRIVINFLT;
615 return -2;
616 }
617 #endif
618 if (usermode)
619 goto nogo;
620
621 map = kernel_map;
622 } else {
623 /*
624 * This is a fault on non-kernel virtual memory.
625 * vm is initialized above to NULL. If curproc is NULL
626 * or curproc->p_vmspace is NULL the fault is fatal.
627 */
628 if (p != NULL)
629 vm = p->p_vmspace;
630
631 if (vm == NULL)
632 goto nogo;
633
634 map = &vm->vm_map;
635 }
636
637 if (frame->tf_err & PGEX_W)
638 ftype = VM_PROT_READ | VM_PROT_WRITE;
639 else
640 ftype = VM_PROT_READ;
641
642 if (map != kernel_map) {
643 /*
644 * Keep swapout from messing with us during this
645 * critical time.
646 */
647 ++p->p_lock;
648
649 /*
650 * Grow the stack if necessary
651 */
652 if ((caddr_t)va > vm->vm_maxsaddr
653 && (caddr_t)va < (caddr_t)USRSTACK) {
654 if (!grow(p, va)) {
655 rv = KERN_FAILURE;
656 --p->p_lock;
657 goto nogo;
658 }
659 }
660
661 /* Fault in the user page: */
662 rv = vm_fault(map, va, ftype,
663 (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY : 0);
664
665 --p->p_lock;
666 } else {
667 /*
668 * Don't have to worry about process locking or stacks in the kernel.
669 */
670 rv = vm_fault(map, va, ftype, FALSE);
671 }
672
673 if (rv == KERN_SUCCESS)
674 return (0);
675 nogo:
676 if (!usermode) {
677 if (intr_nesting_level == 0 && curpcb && curpcb->pcb_onfault) {
678 frame->tf_eip = (int)curpcb->pcb_onfault;
679 return (0);
680 }
681 trap_fatal(frame);
682 return (-1);
683 }
684
685 /* kludge to pass faulting virtual address to sendsig */
686 frame->tf_err = eva;
687
688 return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
689 }
690
691 static void
692 trap_fatal(frame)
693 struct trapframe *frame;
694 {
695 int code, type, eva, ss, esp;
696 struct soft_segment_descriptor softseg;
697
698 code = frame->tf_err;
699 type = frame->tf_trapno;
700 eva = rcr2();
701 sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg);
702
703 if (type <= MAX_TRAP_MSG)
704 printf("\n\nFatal trap %d: %s while in %s mode\n",
705 type, trap_msg[type],
706 ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel");
707 if (type == T_PAGEFLT) {
708 printf("fault virtual address = 0x%x\n", eva);
709 printf("fault code = %s %s, %s\n",
710 code & PGEX_U ? "user" : "supervisor",
711 code & PGEX_W ? "write" : "read",
712 code & PGEX_P ? "protection violation" : "page not present");
713 }
714 printf("instruction pointer = 0x%x:0x%x\n",
715 frame->tf_cs & 0xffff, frame->tf_eip);
716 if (ISPL(frame->tf_cs) == SEL_UPL) {
717 ss = frame->tf_ss & 0xffff;
718 esp = frame->tf_esp;
719 } else {
720 ss = GSEL(GDATA_SEL, SEL_KPL);
721 esp = (int)&frame->tf_esp;
722 }
723 printf("stack pointer = 0x%x:0x%x\n", ss, esp);
724 printf("frame pointer = 0x%x:0x%x\n", ss, frame->tf_ebp);
725 printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n",
726 softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
727 printf(" = DPL %d, pres %d, def32 %d, gran %d\n",
728 softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32,
729 softseg.ssd_gran);
730 printf("processor eflags = ");
731 if (frame->tf_eflags & PSL_T)
732 printf("trace trap, ");
733 if (frame->tf_eflags & PSL_I)
734 printf("interrupt enabled, ");
735 if (frame->tf_eflags & PSL_NT)
736 printf("nested task, ");
737 if (frame->tf_eflags & PSL_RF)
738 printf("resume, ");
739 if (frame->tf_eflags & PSL_VM)
740 printf("vm86, ");
741 printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12);
742 printf("current process = ");
743 if (curproc) {
744 printf("%lu (%s)\n",
745 (u_long)curproc->p_pid, curproc->p_comm ?
746 curproc->p_comm : "");
747 } else {
748 printf("Idle\n");
749 }
750 printf("interrupt mask = ");
751 if ((cpl & net_imask) == net_imask)
752 printf("net ");
753 if ((cpl & tty_imask) == tty_imask)
754 printf("tty ");
755 if ((cpl & bio_imask) == bio_imask)
756 printf("bio ");
757 if ((cpl & cam_imask) == cam_imask)
758 printf("cam ");
759 if (cpl == 0)
760 printf("none");
761 printf("\n");
762
763 #ifdef KDB
764 if (kdb_trap(&psl))
765 return;
766 #endif
767 #ifdef DDB
768 if (kdb_trap (type, 0, frame))
769 return;
770 #endif
771 if (type <= MAX_TRAP_MSG)
772 panic(trap_msg[type]);
773 else
774 panic("unknown/reserved trap");
775 }
776
777 /*
778 * Double fault handler. Called when a fault occurs while writing
779 * a frame for a trap/exception onto the stack. This usually occurs
780 * when the stack overflows (such is the case with infinite recursion,
781 * for example).
782 *
783 * XXX Note that the current PTD gets replaced by IdlePTD when the
784 * task switch occurs. This means that the stack that was active at
785 * the time of the double fault is not available at <kstack> unless
786 * the machine was idle when the double fault occurred. The downside
787 * of this is that "trace <ebp>" in ddb won't work.
788 */
789 void
790 dblfault_handler()
791 {
792 struct pcb *pcb = curpcb;
793
794 if (pcb != NULL) {
795 printf("\nFatal double fault:\n");
796 printf("eip = 0x%x\n", pcb->pcb_tss.tss_eip);
797 printf("esp = 0x%x\n", pcb->pcb_tss.tss_esp);
798 printf("ebp = 0x%x\n", pcb->pcb_tss.tss_ebp);
799 }
800
801 panic("double fault");
802 }
803
804 /*
805 * Compensate for 386 brain damage (missing URKR).
806 * This is a little simpler than the pagefault handler in trap() because
807 * it the page tables have already been faulted in and high addresses
808 * are thrown out early for other reasons.
809 */
810 int trapwrite(addr)
811 unsigned addr;
812 {
813 struct proc *p;
814 vm_offset_t va;
815 struct vmspace *vm;
816 int rv;
817
818 va = trunc_page((vm_offset_t)addr);
819 /*
820 * XXX - MAX is END. Changed > to >= for temp. fix.
821 */
822 if (va >= VM_MAXUSER_ADDRESS)
823 return (1);
824
825 p = curproc;
826 vm = p->p_vmspace;
827
828 ++p->p_lock;
829
830 if ((caddr_t)va >= vm->vm_maxsaddr
831 && (caddr_t)va < (caddr_t)USRSTACK) {
832 if (!grow(p, va)) {
833 --p->p_lock;
834 return (1);
835 }
836 }
837
838 /*
839 * fault the data page
840 */
841 rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, VM_FAULT_DIRTY);
842
843 --p->p_lock;
844
845 if (rv != KERN_SUCCESS)
846 return 1;
847
848 return (0);
849 }
850
851 /*
852 * System call request from POSIX system call gate interface to kernel.
853 * Like trap(), argument is call by reference.
854 */
855 void
856 syscall(frame)
857 struct trapframe frame;
858 {
859 caddr_t params;
860 int i;
861 struct sysent *callp;
862 struct proc *p = curproc;
863 u_quad_t sticks;
864 int error;
865 int args[8], rval[2];
866 u_int code;
867
868 sticks = p->p_sticks;
869 if (ISPL(frame.tf_cs) != SEL_UPL)
870 panic("syscall");
871
872 p->p_md.md_regs = (int *)&frame;
873 params = (caddr_t)frame.tf_esp + sizeof(int);
874 code = frame.tf_eax;
875 if (p->p_sysent->sv_prepsyscall) {
876 (*p->p_sysent->sv_prepsyscall)(&frame, args, &code, ¶ms);
877 } else {
878 /*
879 * Need to check if this is a 32 bit or 64 bit syscall.
880 */
881 if (code == SYS_syscall) {
882 /*
883 * Code is first argument, followed by actual args.
884 */
885 code = fuword(params);
886 params += sizeof(int);
887 } else if (code == SYS___syscall) {
888 /*
889 * Like syscall, but code is a quad, so as to maintain
890 * quad alignment for the rest of the arguments.
891 */
892 code = fuword(params);
893 params += sizeof(quad_t);
894 }
895 }
896
897 if (p->p_sysent->sv_mask)
898 code &= p->p_sysent->sv_mask;
899
900 if (code >= p->p_sysent->sv_size)
901 callp = &p->p_sysent->sv_table[0];
902 else
903 callp = &p->p_sysent->sv_table[code];
904
905 if (params && (i = callp->sy_narg * sizeof(int)) &&
906 (error = copyin(params, (caddr_t)args, (u_int)i))) {
907 #ifdef KTRACE
908 if (KTRPOINT(p, KTR_SYSCALL))
909 ktrsyscall(p->p_tracep, code, callp->sy_narg, args);
910 #endif
911 goto bad;
912 }
913 #ifdef KTRACE
914 if (KTRPOINT(p, KTR_SYSCALL))
915 ktrsyscall(p->p_tracep, code, callp->sy_narg, args);
916 #endif
917 rval[0] = 0;
918 rval[1] = frame.tf_edx;
919
920 error = (*callp->sy_call)(p, args, rval);
921
922 switch (error) {
923
924 case 0:
925 /*
926 * Reinitialize proc pointer `p' as it may be different
927 * if this is a child returning from fork syscall.
928 */
929 p = curproc;
930 frame.tf_eax = rval[0];
931 frame.tf_edx = rval[1];
932 frame.tf_eflags &= ~PSL_C;
933 break;
934
935 case ERESTART:
936 /*
937 * Reconstruct pc, assuming lcall $X,y is 7 bytes,
938 * int 0x80 is 2 bytes. We saved this in tf_err.
939 */
940 frame.tf_eip -= frame.tf_err;
941 break;
942
943 case EJUSTRETURN:
944 break;
945
946 default:
947 bad:
948 if (p->p_sysent->sv_errsize)
949 if (error >= p->p_sysent->sv_errsize)
950 error = -1; /* XXX */
951 else
952 error = p->p_sysent->sv_errtbl[error];
953 frame.tf_eax = error;
954 frame.tf_eflags |= PSL_C;
955 break;
956 }
957
958 if (frame.tf_eflags & PSL_T) {
959 /* Traced syscall. */
960 frame.tf_eflags &= ~PSL_T;
961 trapsignal(p, SIGTRAP, 0);
962 }
963
964 userret(p, &frame, sticks);
965
966 #ifdef KTRACE
967 if (KTRPOINT(p, KTR_SYSRET))
968 ktrsysret(p->p_tracep, code, error, rval[0]);
969 #endif
970 }
Cache object: b0a289129967ecc4aa1da17fa17f4190
|