| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: trap.c,v 1.92 2017/02/23 03:34:22 kamil Exp $ */ | | 1 | /* $NetBSD: trap.c,v 1.93 2017/03/09 00:16:07 chs Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Charles M. Hannum. | | 8 | * by Charles M. Hannum. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -58,27 +58,27 @@ | | | @@ -58,27 +58,27 @@ |
58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
61 | * SUCH DAMAGE. | | 61 | * SUCH DAMAGE. |
62 | * | | 62 | * |
63 | * @(#)trap.c 7.4 (Berkeley) 5/13/91 | | 63 | * @(#)trap.c 7.4 (Berkeley) 5/13/91 |
64 | */ | | 64 | */ |
65 | | | 65 | |
66 | /* | | 66 | /* |
67 | * 386 Trap and System call handling | | 67 | * 386 Trap and System call handling |
68 | */ | | 68 | */ |
69 | | | 69 | |
70 | #include <sys/cdefs.h> | | 70 | #include <sys/cdefs.h> |
71 | __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.92 2017/02/23 03:34:22 kamil Exp $"); | | 71 | __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.93 2017/03/09 00:16:07 chs Exp $"); |
72 | | | 72 | |
73 | #include "opt_ddb.h" | | 73 | #include "opt_ddb.h" |
74 | #include "opt_kgdb.h" | | 74 | #include "opt_kgdb.h" |
75 | #include "opt_xen.h" | | 75 | #include "opt_xen.h" |
76 | #include "opt_dtrace.h" | | 76 | #include "opt_dtrace.h" |
77 | | | 77 | |
78 | #include <sys/param.h> | | 78 | #include <sys/param.h> |
79 | #include <sys/systm.h> | | 79 | #include <sys/systm.h> |
80 | #include <sys/proc.h> | | 80 | #include <sys/proc.h> |
81 | #include <sys/acct.h> | | 81 | #include <sys/acct.h> |
82 | #include <sys/kauth.h> | | 82 | #include <sys/kauth.h> |
83 | #include <sys/kernel.h> | | 83 | #include <sys/kernel.h> |
84 | #include <sys/kmem.h> | | 84 | #include <sys/kmem.h> |
| @@ -144,27 +144,27 @@ const char * const trap_type[] = { | | | @@ -144,27 +144,27 @@ const char * const trap_type[] = { |
144 | "machine check fault", /* 18 T_MCA */ | | 144 | "machine check fault", /* 18 T_MCA */ |
145 | "SSE FP exception", /* 19 T_XMM */ | | 145 | "SSE FP exception", /* 19 T_XMM */ |
146 | "reserved trap", /* 20 T_RESERVED */ | | 146 | "reserved trap", /* 20 T_RESERVED */ |
147 | }; | | 147 | }; |
148 | int trap_types = __arraycount(trap_type); | | 148 | int trap_types = __arraycount(trap_type); |
149 | | | 149 | |
150 | #ifdef DEBUG | | 150 | #ifdef DEBUG |
151 | int trapdebug = 0; | | 151 | int trapdebug = 0; |
152 | #endif | | 152 | #endif |
153 | | | 153 | |
154 | #define IDTVEC(name) __CONCAT(X, name) | | 154 | #define IDTVEC(name) __CONCAT(X, name) |
155 | | | 155 | |
156 | #ifdef TRAP_SIGDEBUG | | 156 | #ifdef TRAP_SIGDEBUG |
157 | static void frame_dump(struct trapframe *); | | 157 | static void frame_dump(struct trapframe *, struct pcb *); |
158 | #endif | | 158 | #endif |
159 | | | 159 | |
160 | static void * | | 160 | static void * |
161 | onfault_handler(const struct pcb *pcb, const struct trapframe *tf) | | 161 | onfault_handler(const struct pcb *pcb, const struct trapframe *tf) |
162 | { | | 162 | { |
163 | struct onfault_table { | | 163 | struct onfault_table { |
164 | uintptr_t start; | | 164 | uintptr_t start; |
165 | uintptr_t end; | | 165 | uintptr_t end; |
166 | void *handler; | | 166 | void *handler; |
167 | }; | | 167 | }; |
168 | extern const struct onfault_table onfault_table[]; | | 168 | extern const struct onfault_table onfault_table[]; |
169 | const struct onfault_table *p; | | 169 | const struct onfault_table *p; |
170 | uintptr_t pc; | | 170 | uintptr_t pc; |
| @@ -184,28 +184,28 @@ onfault_handler(const struct pcb *pcb, c | | | @@ -184,28 +184,28 @@ onfault_handler(const struct pcb *pcb, c |
184 | | | 184 | |
185 | static void | | 185 | static void |
186 | trap_print(const struct trapframe *frame, const lwp_t *l) | | 186 | trap_print(const struct trapframe *frame, const lwp_t *l) |
187 | { | | 187 | { |
188 | const int type = frame->tf_trapno; | | 188 | const int type = frame->tf_trapno; |
189 | | | 189 | |
190 | if (frame->tf_trapno < trap_types) { | | 190 | if (frame->tf_trapno < trap_types) { |
191 | printf("fatal %s", trap_type[type]); | | 191 | printf("fatal %s", trap_type[type]); |
192 | } else { | | 192 | } else { |
193 | printf("unknown trap %d", type); | | 193 | printf("unknown trap %d", type); |
194 | } | | 194 | } |
195 | printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor"); | | 195 | printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor"); |
196 | | | 196 | |
197 | printf("trap type %d code %lx rip %lx cs %lx rflags %lx cr2 %lx " | | 197 | printf("trap type %d code %#lx rip %#lx cs %#lx rflags %#lx cr2 %#lx " |
198 | "ilevel %x rsp %lx\n", | | 198 | "ilevel %#x rsp %#lx\n", |
199 | type, frame->tf_err, (u_long)frame->tf_rip, frame->tf_cs, | | 199 | type, frame->tf_err, (u_long)frame->tf_rip, frame->tf_cs, |
200 | frame->tf_rflags, rcr2(), curcpu()->ci_ilevel, frame->tf_rsp); | | 200 | frame->tf_rflags, rcr2(), curcpu()->ci_ilevel, frame->tf_rsp); |
201 | | | 201 | |
202 | printf("curlwp %p pid %d.%d lowest kstack %p\n", | | 202 | printf("curlwp %p pid %d.%d lowest kstack %p\n", |
203 | l, l->l_proc->p_pid, l->l_lid, KSTACK_LOWEST_ADDR(l)); | | 203 | l, l->l_proc->p_pid, l->l_lid, KSTACK_LOWEST_ADDR(l)); |
204 | } | | 204 | } |
205 | | | 205 | |
206 | /* | | 206 | /* |
207 | * trap(frame): exception, fault, and trap interface to BSD kernel. | | 207 | * trap(frame): exception, fault, and trap interface to BSD kernel. |
208 | * | | 208 | * |
209 | * This common code is called from assembly language IDT gate entry routines | | 209 | * This common code is called from assembly language IDT gate entry routines |
210 | * that prepare a suitable stack frame, and restore this frame after the | | 210 | * that prepare a suitable stack frame, and restore this frame after the |
211 | * exception has been processed. Note that the effect is as if the arguments | | 211 | * exception has been processed. Note that the effect is as if the arguments |
| @@ -398,29 +398,29 @@ kernelfault: | | | @@ -398,29 +398,29 @@ kernelfault: |
398 | l->l_md.md_regs = vframe; | | 398 | l->l_md.md_regs = vframe; |
399 | (*p->p_emul->e_trapsignal)(l, &ksi); | | 399 | (*p->p_emul->e_trapsignal)(l, &ksi); |
400 | /* Return to user by reloading the user frame */ | | 400 | /* Return to user by reloading the user frame */ |
401 | trap_return_fault_return(vframe); | | 401 | trap_return_fault_return(vframe); |
402 | /* NOTREACHED */ | | 402 | /* NOTREACHED */ |
403 | #endif | | 403 | #endif |
404 | | | 404 | |
405 | case T_PROTFLT|T_USER: /* protection fault */ | | 405 | case T_PROTFLT|T_USER: /* protection fault */ |
406 | case T_TSSFLT|T_USER: | | 406 | case T_TSSFLT|T_USER: |
407 | case T_SEGNPFLT|T_USER: | | 407 | case T_SEGNPFLT|T_USER: |
408 | case T_STKFLT|T_USER: | | 408 | case T_STKFLT|T_USER: |
409 | case T_ALIGNFLT|T_USER: | | 409 | case T_ALIGNFLT|T_USER: |
410 | #ifdef TRAP_SIGDEBUG | | 410 | #ifdef TRAP_SIGDEBUG |
411 | printf("pid %d.%d (%s): BUS/SEGV (%x) at rip %lx addr %lx\n", | | 411 | printf("pid %d.%d (%s): BUS/SEGV (%#x) at rip %#lx addr %#lx\n", |
412 | p->p_pid, l->l_lid, p->p_comm, type, frame->tf_rip, rcr2()); | | 412 | p->p_pid, l->l_lid, p->p_comm, type, frame->tf_rip, rcr2()); |
413 | frame_dump(frame); | | 413 | frame_dump(frame, pcb); |
414 | #endif | | 414 | #endif |
415 | KSI_INIT_TRAP(&ksi); | | 415 | KSI_INIT_TRAP(&ksi); |
416 | ksi.ksi_trap = type & ~T_USER; | | 416 | ksi.ksi_trap = type & ~T_USER; |
417 | ksi.ksi_addr = (void *)rcr2(); | | 417 | ksi.ksi_addr = (void *)rcr2(); |
418 | switch (type) { | | 418 | switch (type) { |
419 | case T_SEGNPFLT|T_USER: | | 419 | case T_SEGNPFLT|T_USER: |
420 | case T_STKFLT|T_USER: | | 420 | case T_STKFLT|T_USER: |
421 | ksi.ksi_signo = SIGBUS; | | 421 | ksi.ksi_signo = SIGBUS; |
422 | ksi.ksi_code = BUS_ADRERR; | | 422 | ksi.ksi_code = BUS_ADRERR; |
423 | break; | | 423 | break; |
424 | case T_TSSFLT|T_USER: | | 424 | case T_TSSFLT|T_USER: |
425 | ksi.ksi_signo = SIGBUS; | | 425 | ksi.ksi_signo = SIGBUS; |
426 | ksi.ksi_code = BUS_OBJERR; | | 426 | ksi.ksi_code = BUS_OBJERR; |
| @@ -432,29 +432,29 @@ kernelfault: | | | @@ -432,29 +432,29 @@ kernelfault: |
432 | case T_PROTFLT|T_USER: | | 432 | case T_PROTFLT|T_USER: |
433 | ksi.ksi_signo = SIGSEGV; | | 433 | ksi.ksi_signo = SIGSEGV; |
434 | ksi.ksi_code = SEGV_ACCERR; | | 434 | ksi.ksi_code = SEGV_ACCERR; |
435 | break; | | 435 | break; |
436 | default: | | 436 | default: |
437 | KASSERT(0); | | 437 | KASSERT(0); |
438 | break; | | 438 | break; |
439 | } | | 439 | } |
440 | goto trapsignal; | | 440 | goto trapsignal; |
441 | | | 441 | |
442 | case T_PRIVINFLT|T_USER: /* privileged instruction fault */ | | 442 | case T_PRIVINFLT|T_USER: /* privileged instruction fault */ |
443 | case T_FPOPFLT|T_USER: /* coprocessor operand fault */ | | 443 | case T_FPOPFLT|T_USER: /* coprocessor operand fault */ |
444 | #ifdef TRAP_SIGDEBUG | | 444 | #ifdef TRAP_SIGDEBUG |
445 | printf("pid %d.%d (%s): ILL at rip %lx addr %lx\n", | | 445 | printf("pid %d.%d (%s): ILL at rip %#lx addr %#lx\n", |
446 | p->p_pid, l->l_lid, p->p_comm, frame->tf_rip, rcr2()); | | 446 | p->p_pid, l->l_lid, p->p_comm, frame->tf_rip, rcr2()); |
447 | frame_dump(frame); | | 447 | frame_dump(frame, pcb); |
448 | #endif | | 448 | #endif |
449 | KSI_INIT_TRAP(&ksi); | | 449 | KSI_INIT_TRAP(&ksi); |
450 | ksi.ksi_signo = SIGILL; | | 450 | ksi.ksi_signo = SIGILL; |
451 | ksi.ksi_trap = type & ~T_USER; | | 451 | ksi.ksi_trap = type & ~T_USER; |
452 | ksi.ksi_addr = (void *) frame->tf_rip; | | 452 | ksi.ksi_addr = (void *) frame->tf_rip; |
453 | switch (type) { | | 453 | switch (type) { |
454 | case T_PRIVINFLT|T_USER: | | 454 | case T_PRIVINFLT|T_USER: |
455 | ksi.ksi_code = ILL_PRVOPC; | | 455 | ksi.ksi_code = ILL_PRVOPC; |
456 | break; | | 456 | break; |
457 | case T_FPOPFLT|T_USER: | | 457 | case T_FPOPFLT|T_USER: |
458 | ksi.ksi_code = ILL_COPROC; | | 458 | ksi.ksi_code = ILL_COPROC; |
459 | break; | | 459 | break; |
460 | default: | | 460 | default: |
| @@ -660,27 +660,27 @@ faultcommon: | | | @@ -660,27 +660,27 @@ faultcommon: |
660 | l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); | | 660 | l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); |
661 | break; | | 661 | break; |
662 | default: | | 662 | default: |
663 | ksi.ksi_signo = SIGSEGV; | | 663 | ksi.ksi_signo = SIGSEGV; |
664 | ksi.ksi_code = SEGV_MAPERR; | | 664 | ksi.ksi_code = SEGV_MAPERR; |
665 | break; | | 665 | break; |
666 | } | | 666 | } |
667 | | | 667 | |
668 | #ifdef TRAP_SIGDEBUG | | 668 | #ifdef TRAP_SIGDEBUG |
669 | printf("pid %d.%d (%s): signal %d at rip %#lx addr %#lx " | | 669 | printf("pid %d.%d (%s): signal %d at rip %#lx addr %#lx " |
670 | "error %d trap %d cr2 %p\n", p->p_pid, l->l_lid, p->p_comm, | | 670 | "error %d trap %d cr2 %p\n", p->p_pid, l->l_lid, p->p_comm, |
671 | ksi.ksi_signo, frame->tf_rip, va, error, ksi.ksi_trap, | | 671 | ksi.ksi_signo, frame->tf_rip, va, error, ksi.ksi_trap, |
672 | ksi.ksi_addr); | | 672 | ksi.ksi_addr); |
673 | frame_dump(frame); | | 673 | frame_dump(frame, pcb); |
674 | #endif | | 674 | #endif |
675 | (*p->p_emul->e_trapsignal)(l, &ksi); | | 675 | (*p->p_emul->e_trapsignal)(l, &ksi); |
676 | break; | | 676 | break; |
677 | } | | 677 | } |
678 | | | 678 | |
679 | case T_TRCTRAP: | | 679 | case T_TRCTRAP: |
680 | /* | | 680 | /* |
681 | * Ignore debug register trace traps due to | | 681 | * Ignore debug register trace traps due to |
682 | * accesses in the user's address space, which | | 682 | * accesses in the user's address space, which |
683 | * can happen under several conditions such as | | 683 | * can happen under several conditions such as |
684 | * if a user sets a watchpoint on a buffer and | | 684 | * if a user sets a watchpoint on a buffer and |
685 | * then passes that buffer to a system call. | | 685 | * then passes that buffer to a system call. |
686 | * We still want to get TRCTRAPS for addresses | | 686 | * We still want to get TRCTRAPS for addresses |
| @@ -753,42 +753,46 @@ startlwp(void *arg) | | | @@ -753,42 +753,46 @@ startlwp(void *arg) |
753 | { | | 753 | { |
754 | ucontext_t *uc = arg; | | 754 | ucontext_t *uc = arg; |
755 | lwp_t *l = curlwp; | | 755 | lwp_t *l = curlwp; |
756 | int error __diagused; | | 756 | int error __diagused; |
757 | | | 757 | |
758 | error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); | | 758 | error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); |
759 | KASSERT(error == 0); | | 759 | KASSERT(error == 0); |
760 | | | 760 | |
761 | kmem_free(uc, sizeof(ucontext_t)); | | 761 | kmem_free(uc, sizeof(ucontext_t)); |
762 | userret(l); | | 762 | userret(l); |
763 | } | | 763 | } |
764 | | | 764 | |
765 | #ifdef TRAP_SIGDEBUG | | 765 | #ifdef TRAP_SIGDEBUG |
766 | static void | | 766 | void |
767 | frame_dump(struct trapframe *tf) | | 767 | frame_dump(struct trapframe *tf, struct pcb *pcb) |
768 | { | | 768 | { |
769 | int i; | | 769 | int i; |
770 | unsigned long *p; | | 770 | unsigned long *p; |
771 | | | 771 | |
772 | printf("rip %p rsp %p rfl %p\n", | | 772 | printf("trapframe %p\n", tf); |
773 | (void *)tf->tf_rip, (void *)tf->tf_rsp, (void *)tf->tf_rflags); | | 773 | printf("rip 0x%016lx rsp 0x%016lx rfl 0x%016lx\n", |
774 | printf("rdi %p rsi %p rdx %p\n", | | 774 | tf->tf_rip, tf->tf_rsp, tf->tf_rflags); |
775 | (void *)tf->tf_rdi, (void *)tf->tf_rsi, (void *)tf->tf_rdx); | | 775 | printf("rdi 0x%016lx rsi 0x%016lx rdx 0x%016lx\n", |
776 | printf("rcx %p r8 %p r9 %p\n", | | 776 | tf->tf_rdi, tf->tf_rsi, tf->tf_rdx); |
777 | (void *)tf->tf_rcx, (void *)tf->tf_r8, (void *)tf->tf_r9); | | 777 | printf("rcx 0x%016lx r8 0x%016lx r9 0x%016lx\n", |
778 | printf("r10 %p r11 %p r12 %p\n", | | 778 | tf->tf_rcx, tf->tf_r8, tf->tf_r9); |
779 | (void *)tf->tf_r10, (void *)tf->tf_r11, (void *)tf->tf_r12); | | 779 | printf("r10 0x%016lx r11 0x%016lx r12 0x%016lx\n", |
780 | printf("r13 %p r14 %p r15 %p\n", | | 780 | tf->tf_r10, tf->tf_r11, tf->tf_r12); |
781 | (void *)tf->tf_r13, (void *)tf->tf_r14, (void *)tf->tf_r15); | | 781 | printf("r13 0x%016lx r14 0x%016lx r15 0x%016lx\n", |
782 | printf("rbp %p rbx %p rax %p\n", | | 782 | tf->tf_r13, tf->tf_r14, tf->tf_r15); |
783 | (void *)tf->tf_rbp, (void *)tf->tf_rbx, (void *)tf->tf_rax); | | 783 | printf("rbp 0x%016lx rbx 0x%016lx rax 0x%016lx\n", |
784 | printf("cs %lx ds %lx es %lx fs %lx gs %lx ss %lx\n", | | 784 | tf->tf_rbp, tf->tf_rbx, tf->tf_rax); |
| | | 785 | printf("cs 0x%04lx ds 0x%04lx es 0x%04lx " |
| | | 786 | "fs 0x%04lx gs 0x%04lx ss 0x%04lx\n", |
785 | tf->tf_cs & 0xffff, tf->tf_ds & 0xffff, tf->tf_es & 0xffff, | | 787 | tf->tf_cs & 0xffff, tf->tf_ds & 0xffff, tf->tf_es & 0xffff, |
786 | tf->tf_fs & 0xffff, tf->tf_gs & 0xffff, tf->tf_ss & 0xffff); | | 788 | tf->tf_fs & 0xffff, tf->tf_gs & 0xffff, tf->tf_ss & 0xffff); |
787 | | | 789 | printf("fsbase 0x%016lx gsbase 0x%016lx\n", |
| | | 790 | pcb->pcb_fs, pcb->pcb_gs); |
788 | printf("\n"); | | 791 | printf("\n"); |
789 | printf("Stack dump:\n"); | | 792 | printf("Stack dump:\n"); |
790 | for (i = 0, p = (unsigned long *) tf; i < 20; i ++, p += 4) | | 793 | for (i = 0, p = (unsigned long *) tf; i < 20; i ++, p += 4) |
791 | printf(" 0x%.16lx 0x%.16lx 0x%.16lx 0x%.16lx\n", *p, p[1], p[2], p[3]); | | 794 | printf(" 0x%.16lx 0x%.16lx 0x%.16lx 0x%.16lx\n", |
| | | 795 | p[0], p[1], p[2], p[3]); |
792 | printf("\n"); | | 796 | printf("\n"); |
793 | } | | 797 | } |
794 | #endif | | 798 | #endif |