| @@ -1,770 +1,807 @@ | | | @@ -1,770 +1,807 @@ |
1 | | | 1 | |
2 | /* $NetBSD: trap.c,v 1.284 2017/02/23 03:34:22 kamil Exp $ */ | | 2 | /* $NetBSD: trap.c,v 1.285 2017/03/09 00:16:51 chs Exp $ */ |
3 | | | 3 | |
4 | /*- | | 4 | /*- |
5 | * Copyright (c) 1998, 2000, 2005, 2006, 2007, 2008 The NetBSD Foundation, Inc. | | 5 | * Copyright (c) 1998, 2000, 2005, 2006, 2007, 2008 The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Charles M. Hannum. | | 9 | * by Charles M. Hannum. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. | | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright | | 16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the | | 17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. | | 18 | * documentation and/or other materials provided with the distribution. |
19 | * | | 19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /*- | | 33 | /*- |
34 | * Copyright (c) 1990 The Regents of the University of California. | | 34 | * Copyright (c) 1990 The Regents of the University of California. |
35 | * All rights reserved. | | 35 | * All rights reserved. |
36 | * | | 36 | * |
37 | * This code is derived from software contributed to Berkeley by | | 37 | * This code is derived from software contributed to Berkeley by |
38 | * the University of Utah, and William Jolitz. | | 38 | * the University of Utah, and William Jolitz. |
39 | * | | 39 | * |
40 | * Redistribution and use in source and binary forms, with or without | | 40 | * Redistribution and use in source and binary forms, with or without |
41 | * modification, are permitted provided that the following conditions | | 41 | * modification, are permitted provided that the following conditions |
42 | * are met: | | 42 | * are met: |
43 | * 1. Redistributions of source code must retain the above copyright | | 43 | * 1. Redistributions of source code must retain the above copyright |
44 | * notice, this list of conditions and the following disclaimer. | | 44 | * notice, this list of conditions and the following disclaimer. |
45 | * 2. Redistributions in binary form must reproduce the above copyright | | 45 | * 2. Redistributions in binary form must reproduce the above copyright |
46 | * notice, this list of conditions and the following disclaimer in the | | 46 | * notice, this list of conditions and the following disclaimer in the |
47 | * documentation and/or other materials provided with the distribution. | | 47 | * documentation and/or other materials provided with the distribution. |
48 | * 3. Neither the name of the University nor the names of its contributors | | 48 | * 3. Neither the name of the University nor the names of its contributors |
49 | * may be used to endorse or promote products derived from this software | | 49 | * may be used to endorse or promote products derived from this software |
50 | * without specific prior written permission. | | 50 | * without specific prior written permission. |
51 | * | | 51 | * |
52 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 52 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
54 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 54 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
55 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 55 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
56 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 56 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
57 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 57 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
58 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 58 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
59 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 59 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
60 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 60 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
61 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 61 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
62 | * SUCH DAMAGE. | | 62 | * SUCH DAMAGE. |
63 | * | | 63 | * |
64 | * @(#)trap.c 7.4 (Berkeley) 5/13/91 | | 64 | * @(#)trap.c 7.4 (Berkeley) 5/13/91 |
65 | */ | | 65 | */ |
66 | | | 66 | |
67 | /* | | 67 | /* |
68 | * 386 Trap and System call handling | | 68 | * 386 Trap and System call handling |
69 | */ | | 69 | */ |
70 | | | 70 | |
71 | #include <sys/cdefs.h> | | 71 | #include <sys/cdefs.h> |
72 | __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.284 2017/02/23 03:34:22 kamil Exp $"); | | 72 | __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.285 2017/03/09 00:16:51 chs Exp $"); |
73 | | | 73 | |
74 | #include "opt_ddb.h" | | 74 | #include "opt_ddb.h" |
75 | #include "opt_kgdb.h" | | 75 | #include "opt_kgdb.h" |
76 | #include "opt_lockdebug.h" | | 76 | #include "opt_lockdebug.h" |
77 | #include "opt_multiprocessor.h" | | 77 | #include "opt_multiprocessor.h" |
78 | #include "opt_vm86.h" | | 78 | #include "opt_vm86.h" |
79 | #include "opt_xen.h" | | 79 | #include "opt_xen.h" |
80 | #include "opt_dtrace.h" | | 80 | #include "opt_dtrace.h" |
81 | | | 81 | |
82 | #include <sys/param.h> | | 82 | #include <sys/param.h> |
83 | #include <sys/systm.h> | | 83 | #include <sys/systm.h> |
84 | #include <sys/proc.h> | | 84 | #include <sys/proc.h> |
85 | #include <sys/acct.h> | | 85 | #include <sys/acct.h> |
86 | #include <sys/kauth.h> | | 86 | #include <sys/kauth.h> |
87 | #include <sys/kernel.h> | | 87 | #include <sys/kernel.h> |
88 | #include <sys/kmem.h> | | 88 | #include <sys/kmem.h> |
89 | #include <sys/ras.h> | | 89 | #include <sys/ras.h> |
90 | #include <sys/signal.h> | | 90 | #include <sys/signal.h> |
91 | #include <sys/syscall.h> | | 91 | #include <sys/syscall.h> |
92 | #include <sys/cpu.h> | | 92 | #include <sys/cpu.h> |
93 | #include <sys/ucontext.h> | | 93 | #include <sys/ucontext.h> |
94 | | | 94 | |
95 | #include <uvm/uvm_extern.h> | | 95 | #include <uvm/uvm_extern.h> |
96 | | | 96 | |
97 | #include <machine/cpufunc.h> | | 97 | #include <machine/cpufunc.h> |
98 | #include <machine/psl.h> | | 98 | #include <machine/psl.h> |
99 | #include <machine/reg.h> | | 99 | #include <machine/reg.h> |
100 | #include <machine/trap.h> | | 100 | #include <machine/trap.h> |
101 | #include <machine/userret.h> | | 101 | #include <machine/userret.h> |
102 | #include <machine/db_machdep.h> | | 102 | #include <machine/db_machdep.h> |
103 | | | 103 | |
104 | #include "mca.h" | | 104 | #include "mca.h" |
105 | #if NMCA > 0 | | 105 | #if NMCA > 0 |
106 | #include <machine/mca_machdep.h> | | 106 | #include <machine/mca_machdep.h> |
107 | #endif | | 107 | #endif |
108 | | | 108 | |
109 | #include <x86/nmi.h> | | 109 | #include <x86/nmi.h> |
110 | | | 110 | |
111 | #include "isa.h" | | 111 | #include "isa.h" |
112 | | | 112 | |
113 | #include <sys/kgdb.h> | | 113 | #include <sys/kgdb.h> |
114 | | | 114 | |
115 | #ifdef KDTRACE_HOOKS | | 115 | #ifdef KDTRACE_HOOKS |
116 | #include <sys/dtrace_bsd.h> | | 116 | #include <sys/dtrace_bsd.h> |
117 | | | 117 | |
118 | /* | | 118 | /* |
119 | * This is a hook which is initialized by the dtrace module | | 119 | * This is a hook which is initialized by the dtrace module |
120 | * to handle traps which might occur during DTrace probe | | 120 | * to handle traps which might occur during DTrace probe |
121 | * execution. | | 121 | * execution. |
122 | */ | | 122 | */ |
123 | dtrace_trap_func_t dtrace_trap_func = NULL; | | 123 | dtrace_trap_func_t dtrace_trap_func = NULL; |
124 | | | 124 | |
125 | dtrace_doubletrap_func_t dtrace_doubletrap_func = NULL; | | 125 | dtrace_doubletrap_func_t dtrace_doubletrap_func = NULL; |
126 | #endif | | 126 | #endif |
127 | | | 127 | |
128 | | | | |
129 | void trap(struct trapframe *); | | 128 | void trap(struct trapframe *); |
130 | void trap_tss(struct i386tss *, int, int); | | 129 | void trap_tss(struct i386tss *, int, int); |
131 | void trap_return_fault_return(struct trapframe *) __dead; | | 130 | void trap_return_fault_return(struct trapframe *) __dead; |
132 | | | 131 | |
133 | const char * const trap_type[] = { | | 132 | const char * const trap_type[] = { |
134 | "privileged instruction fault", /* 0 T_PRIVINFLT */ | | 133 | "privileged instruction fault", /* 0 T_PRIVINFLT */ |
135 | "breakpoint trap", /* 1 T_BPTFLT */ | | 134 | "breakpoint trap", /* 1 T_BPTFLT */ |
136 | "arithmetic trap", /* 2 T_ARITHTRAP */ | | 135 | "arithmetic trap", /* 2 T_ARITHTRAP */ |
137 | "asynchronous system trap", /* 3 T_ASTFLT */ | | 136 | "asynchronous system trap", /* 3 T_ASTFLT */ |
138 | "protection fault", /* 4 T_PROTFLT */ | | 137 | "protection fault", /* 4 T_PROTFLT */ |
139 | "trace trap", /* 5 T_TRCTRAP */ | | 138 | "trace trap", /* 5 T_TRCTRAP */ |
140 | "page fault", /* 6 T_PAGEFLT */ | | 139 | "page fault", /* 6 T_PAGEFLT */ |
141 | "alignment fault", /* 7 T_ALIGNFLT */ | | 140 | "alignment fault", /* 7 T_ALIGNFLT */ |
142 | "integer divide fault", /* 8 T_DIVIDE */ | | 141 | "integer divide fault", /* 8 T_DIVIDE */ |
143 | "non-maskable interrupt", /* 9 T_NMI */ | | 142 | "non-maskable interrupt", /* 9 T_NMI */ |
144 | "overflow trap", /* 10 T_OFLOW */ | | 143 | "overflow trap", /* 10 T_OFLOW */ |
145 | "bounds check fault", /* 11 T_BOUND */ | | 144 | "bounds check fault", /* 11 T_BOUND */ |
146 | "FPU not available fault", /* 12 T_DNA */ | | 145 | "FPU not available fault", /* 12 T_DNA */ |
147 | "double fault", /* 13 T_DOUBLEFLT */ | | 146 | "double fault", /* 13 T_DOUBLEFLT */ |
148 | "FPU operand fetch fault", /* 14 T_FPOPFLT */ | | 147 | "FPU operand fetch fault", /* 14 T_FPOPFLT */ |
149 | "invalid TSS fault", /* 15 T_TSSFLT */ | | 148 | "invalid TSS fault", /* 15 T_TSSFLT */ |
150 | "segment not present fault", /* 16 T_SEGNPFLT */ | | 149 | "segment not present fault", /* 16 T_SEGNPFLT */ |
151 | "stack fault", /* 17 T_STKFLT */ | | 150 | "stack fault", /* 17 T_STKFLT */ |
152 | "machine check fault", /* 18 T_MCA */ | | 151 | "machine check fault", /* 18 T_MCA */ |
153 | "SSE FP exception", /* 19 T_XMM */ | | 152 | "SSE FP exception", /* 19 T_XMM */ |
154 | "reserved trap", /* 20 T_RESERVED */ | | 153 | "reserved trap", /* 20 T_RESERVED */ |
155 | }; | | 154 | }; |
156 | int trap_types = __arraycount(trap_type); | | 155 | int trap_types = __arraycount(trap_type); |
157 | | | 156 | |
158 | #ifdef DEBUG | | 157 | #ifdef DEBUG |
159 | int trapdebug = 0; | | 158 | int trapdebug = 0; |
160 | #endif | | 159 | #endif |
161 | | | 160 | |
162 | #define IDTVEC(name) __CONCAT(X, name) | | 161 | #define IDTVEC(name) __CONCAT(X, name) |
163 | | | 162 | |
| | | 163 | #ifdef TRAP_SIGDEBUG |
| | | 164 | static void frame_dump(struct trapframe *, struct pcb *); |
| | | 165 | #endif |
| | | 166 | |
164 | void | | 167 | void |
165 | trap_tss(struct i386tss *tss, int trapno, int code) | | 168 | trap_tss(struct i386tss *tss, int trapno, int code) |
166 | { | | 169 | { |
167 | struct trapframe tf; | | 170 | struct trapframe tf; |
168 | | | 171 | |
169 | tf.tf_gs = tss->tss_gs; | | 172 | tf.tf_gs = tss->tss_gs; |
170 | tf.tf_fs = tss->tss_fs; | | 173 | tf.tf_fs = tss->tss_fs; |
171 | tf.tf_es = tss->__tss_es; | | 174 | tf.tf_es = tss->__tss_es; |
172 | tf.tf_ds = tss->__tss_ds; | | 175 | tf.tf_ds = tss->__tss_ds; |
173 | tf.tf_edi = tss->__tss_edi; | | 176 | tf.tf_edi = tss->__tss_edi; |
174 | tf.tf_esi = tss->__tss_esi; | | 177 | tf.tf_esi = tss->__tss_esi; |
175 | tf.tf_ebp = tss->tss_ebp; | | 178 | tf.tf_ebp = tss->tss_ebp; |
176 | tf.tf_ebx = tss->__tss_ebx; | | 179 | tf.tf_ebx = tss->__tss_ebx; |
177 | tf.tf_edx = tss->__tss_edx; | | 180 | tf.tf_edx = tss->__tss_edx; |
178 | tf.tf_ecx = tss->__tss_ecx; | | 181 | tf.tf_ecx = tss->__tss_ecx; |
179 | tf.tf_eax = tss->__tss_eax; | | 182 | tf.tf_eax = tss->__tss_eax; |
180 | tf.tf_trapno = trapno; | | 183 | tf.tf_trapno = trapno; |
181 | tf.tf_err = code | TC_TSS; | | 184 | tf.tf_err = code | TC_TSS; |
182 | tf.tf_eip = tss->__tss_eip; | | 185 | tf.tf_eip = tss->__tss_eip; |
183 | tf.tf_cs = tss->__tss_cs; | | 186 | tf.tf_cs = tss->__tss_cs; |
184 | tf.tf_eflags = tss->__tss_eflags; | | 187 | tf.tf_eflags = tss->__tss_eflags; |
185 | tf.tf_esp = tss->tss_esp; | | 188 | tf.tf_esp = tss->tss_esp; |
186 | tf.tf_ss = tss->__tss_ss; | | 189 | tf.tf_ss = tss->__tss_ss; |
187 | trap(&tf); | | 190 | trap(&tf); |
188 | } | | 191 | } |
189 | | | 192 | |
190 | static void * | | 193 | static void * |
191 | onfault_handler(const struct pcb *pcb, const struct trapframe *tf) | | 194 | onfault_handler(const struct pcb *pcb, const struct trapframe *tf) |
192 | { | | 195 | { |
193 | struct onfault_table { | | 196 | struct onfault_table { |
194 | uintptr_t start; | | 197 | uintptr_t start; |
195 | uintptr_t end; | | 198 | uintptr_t end; |
196 | void *handler; | | 199 | void *handler; |
197 | }; | | 200 | }; |
198 | extern const struct onfault_table onfault_table[]; | | 201 | extern const struct onfault_table onfault_table[]; |
199 | const struct onfault_table *p; | | 202 | const struct onfault_table *p; |
200 | uintptr_t pc; | | 203 | uintptr_t pc; |
201 | | | 204 | |
202 | if (pcb->pcb_onfault != NULL) { | | 205 | if (pcb->pcb_onfault != NULL) { |
203 | return pcb->pcb_onfault; | | 206 | return pcb->pcb_onfault; |
204 | } | | 207 | } |
205 | | | 208 | |
206 | pc = tf->tf_eip; | | 209 | pc = tf->tf_eip; |
207 | for (p = onfault_table; p->start; p++) { | | 210 | for (p = onfault_table; p->start; p++) { |
208 | if (p->start <= pc && pc < p->end) { | | 211 | if (p->start <= pc && pc < p->end) { |
209 | return p->handler; | | 212 | return p->handler; |
210 | } | | 213 | } |
211 | } | | 214 | } |
212 | return NULL; | | 215 | return NULL; |
213 | } | | 216 | } |
214 | | | 217 | |
215 | static void | | 218 | static void |
216 | trap_print(const struct trapframe *frame, const lwp_t *l) | | 219 | trap_print(const struct trapframe *frame, const lwp_t *l) |
217 | { | | 220 | { |
218 | const int type = frame->tf_trapno; | | 221 | const int type = frame->tf_trapno; |
219 | | | 222 | |
220 | if (frame->tf_trapno < trap_types) { | | 223 | if (frame->tf_trapno < trap_types) { |
221 | printf("fatal %s", trap_type[type]); | | 224 | printf("fatal %s", trap_type[type]); |
222 | } else { | | 225 | } else { |
223 | printf("unknown trap %d", type); | | 226 | printf("unknown trap %d", type); |
224 | } | | 227 | } |
225 | printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor"); | | 228 | printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor"); |
226 | | | 229 | |
227 | printf("trap type %d code %x eip %x cs %x eflags %x cr2 %lx " | | 230 | printf("trap type %d code %#x eip %#x cs %#x eflags %#x cr2 %#lx " |
228 | "ilevel %x esp %x\n", | | 231 | "ilevel %#x esp %#x\n", |
229 | type, frame->tf_err, frame->tf_eip, frame->tf_cs, frame->tf_eflags, | | 232 | type, frame->tf_err, frame->tf_eip, frame->tf_cs, frame->tf_eflags, |
230 | (long)rcr2(), curcpu()->ci_ilevel, frame->tf_esp); | | 233 | (long)rcr2(), curcpu()->ci_ilevel, frame->tf_esp); |
231 | | | 234 | |
232 | printf("curlwp %p pid %d lid %d lowest kstack %p\n", | | 235 | printf("curlwp %p pid %d lid %d lowest kstack %p\n", |
233 | l, l->l_proc->p_pid, l->l_lid, KSTACK_LOWEST_ADDR(l)); | | 236 | l, l->l_proc->p_pid, l->l_lid, KSTACK_LOWEST_ADDR(l)); |
234 | } | | 237 | } |
235 | | | 238 | |
236 | /* | | 239 | /* |
237 | * trap(frame): exception, fault, and trap interface to BSD kernel. | | 240 | * trap(frame): exception, fault, and trap interface to BSD kernel. |
238 | * | | 241 | * |
239 | * This common code is called from assembly language IDT gate entry routines | | 242 | * This common code is called from assembly language IDT gate entry routines |
240 | * that prepare a suitable stack frame, and restore this frame after the | | 243 | * that prepare a suitable stack frame, and restore this frame after the |
241 | * exception has been processed. Note that the effect is as if the arguments | | 244 | * exception has been processed. Note that the effect is as if the arguments |
242 | * were passed call by reference. | | 245 | * were passed call by reference. |
243 | */ | | 246 | */ |
244 | void | | 247 | void |
245 | trap(struct trapframe *frame) | | 248 | trap(struct trapframe *frame) |
246 | { | | 249 | { |
247 | struct lwp *l = curlwp; | | 250 | struct lwp *l = curlwp; |
248 | struct proc *p; | | 251 | struct proc *p; |
249 | struct pcb *pcb; | | 252 | struct pcb *pcb; |
250 | extern char fusubail[], kcopy_fault[], return_address_fault[], | | 253 | extern char fusubail[], kcopy_fault[], return_address_fault[], |
251 | IDTVEC(osyscall)[]; | | 254 | IDTVEC(osyscall)[]; |
252 | struct trapframe *vframe; | | 255 | struct trapframe *vframe; |
253 | ksiginfo_t ksi; | | 256 | ksiginfo_t ksi; |
254 | void *onfault; | | 257 | void *onfault; |
255 | int type, error; | | 258 | int type, error; |
256 | uint32_t cr2; | | 259 | uint32_t cr2; |
257 | bool pfail; | | 260 | bool pfail; |
258 | | | 261 | |
259 | if (__predict_true(l != NULL)) { | | 262 | if (__predict_true(l != NULL)) { |
260 | pcb = lwp_getpcb(l); | | 263 | pcb = lwp_getpcb(l); |
261 | p = l->l_proc; | | 264 | p = l->l_proc; |
262 | } else { | | 265 | } else { |
263 | /* | | 266 | /* |
264 | * this can happen eg. on break points in early on boot. | | 267 | * this can happen eg. on break points in early on boot. |
265 | */ | | 268 | */ |
266 | pcb = NULL; | | 269 | pcb = NULL; |
267 | p = NULL; | | 270 | p = NULL; |
268 | } | | 271 | } |
269 | type = frame->tf_trapno; | | 272 | type = frame->tf_trapno; |
270 | | | 273 | |
271 | #ifdef DEBUG | | 274 | #ifdef DEBUG |
272 | if (trapdebug) { | | 275 | if (trapdebug) { |
273 | trap_print(frame, l); | | 276 | trap_print(frame, l); |
274 | } | | 277 | } |
275 | #endif | | 278 | #endif |
276 | if (type != T_NMI && !KERNELMODE(frame->tf_cs, frame->tf_eflags)) { | | 279 | if (type != T_NMI && !KERNELMODE(frame->tf_cs, frame->tf_eflags)) { |
277 | type |= T_USER; | | 280 | type |= T_USER; |
278 | l->l_md.md_regs = frame; | | 281 | l->l_md.md_regs = frame; |
279 | pcb->pcb_cr2 = 0; | | 282 | pcb->pcb_cr2 = 0; |
280 | LWP_CACHE_CREDS(l, p); | | 283 | LWP_CACHE_CREDS(l, p); |
281 | } | | 284 | } |
282 | | | 285 | |
283 | #ifdef KDTRACE_HOOKS | | 286 | #ifdef KDTRACE_HOOKS |
284 | /* | | 287 | /* |
285 | * A trap can occur while DTrace executes a probe. Before | | 288 | * A trap can occur while DTrace executes a probe. Before |
286 | * executing the probe, DTrace blocks re-scheduling and sets | | 289 | * executing the probe, DTrace blocks re-scheduling and sets |
287 | * a flag in its per-cpu flags to indicate that it doesn't | | 290 | * a flag in its per-cpu flags to indicate that it doesn't |
288 | * want to fault. On returning from the the probe, the no-fault | | 291 | * want to fault. On returning from the the probe, the no-fault |
289 | * flag is cleared and finally re-scheduling is enabled. | | 292 | * flag is cleared and finally re-scheduling is enabled. |
290 | * | | 293 | * |
291 | * If the DTrace kernel module has registered a trap handler, | | 294 | * If the DTrace kernel module has registered a trap handler, |
292 | * call it and if it returns non-zero, assume that it has | | 295 | * call it and if it returns non-zero, assume that it has |
293 | * handled the trap and modified the trap frame so that this | | 296 | * handled the trap and modified the trap frame so that this |
294 | * function can return normally. | | 297 | * function can return normally. |
295 | */ | | 298 | */ |
296 | if ((type == T_PROTFLT || type == T_PAGEFLT) && | | 299 | if ((type == T_PROTFLT || type == T_PAGEFLT) && |
297 | dtrace_trap_func != NULL) { | | 300 | dtrace_trap_func != NULL) { |
298 | if ((*dtrace_trap_func)(frame, type)) { | | 301 | if ((*dtrace_trap_func)(frame, type)) { |
299 | return; | | 302 | return; |
300 | } | | 303 | } |
301 | } | | 304 | } |
302 | #endif | | 305 | #endif |
303 | | | 306 | |
304 | switch (type) { | | 307 | switch (type) { |
305 | | | 308 | |
306 | default: | | 309 | default: |
307 | we_re_toast: | | 310 | we_re_toast: |
308 | if (type != T_TRCTRAP) | | 311 | if (type != T_TRCTRAP) |
309 | trap_print(frame, l); | | 312 | trap_print(frame, l); |
310 | | | 313 | |
311 | if (kdb_trap(type, 0, frame)) | | 314 | if (kdb_trap(type, 0, frame)) |
312 | return; | | 315 | return; |
313 | if (kgdb_trap(type, frame)) | | 316 | if (kgdb_trap(type, frame)) |
314 | return; | | 317 | return; |
315 | /* | | 318 | /* |
316 | * If this is a breakpoint, don't panic if we're not connected. | | 319 | * If this is a breakpoint, don't panic if we're not connected. |
317 | */ | | 320 | */ |
318 | if (type == T_BPTFLT && kgdb_disconnected()) { | | 321 | if (type == T_BPTFLT && kgdb_disconnected()) { |
319 | printf("kgdb: ignored %s\n", trap_type[type]); | | 322 | printf("kgdb: ignored %s\n", trap_type[type]); |
320 | return; | | 323 | return; |
321 | } | | 324 | } |
322 | panic("trap"); | | 325 | panic("trap"); |
323 | /*NOTREACHED*/ | | 326 | /*NOTREACHED*/ |
324 | | | 327 | |
325 | case T_PROTFLT: | | 328 | case T_PROTFLT: |
326 | case T_SEGNPFLT: | | 329 | case T_SEGNPFLT: |
327 | case T_ALIGNFLT: | | 330 | case T_ALIGNFLT: |
328 | case T_TSSFLT: | | 331 | case T_TSSFLT: |
329 | if (p == NULL) | | 332 | if (p == NULL) |
330 | goto we_re_toast; | | 333 | goto we_re_toast; |
331 | /* Check for copyin/copyout fault. */ | | 334 | /* Check for copyin/copyout fault. */ |
332 | onfault = onfault_handler(pcb, frame); | | 335 | onfault = onfault_handler(pcb, frame); |
333 | if (onfault != NULL) { | | 336 | if (onfault != NULL) { |
334 | copyefault: | | 337 | copyefault: |
335 | error = EFAULT; | | 338 | error = EFAULT; |
336 | copyfault: | | 339 | copyfault: |
337 | frame->tf_eip = (uintptr_t)onfault; | | 340 | frame->tf_eip = (uintptr_t)onfault; |
338 | frame->tf_eax = error; | | 341 | frame->tf_eax = error; |
339 | return; | | 342 | return; |
340 | } | | 343 | } |
341 | | | 344 | |
342 | /* | | 345 | /* |
343 | * Check for failure during return to user mode. | | 346 | * Check for failure during return to user mode. |
344 | * This can happen loading invalid values into the segment | | 347 | * This can happen loading invalid values into the segment |
345 | * registers, or during the 'iret' itself. | | 348 | * registers, or during the 'iret' itself. |
346 | * | | 349 | * |
347 | * We do this by looking at the instruction we faulted on. | | 350 | * We do this by looking at the instruction we faulted on. |
348 | * The specific instructions we recognize only happen when | | 351 | * The specific instructions we recognize only happen when |
349 | * returning from a trap, syscall, or interrupt. | | 352 | * returning from a trap, syscall, or interrupt. |
350 | */ | | 353 | */ |
351 | | | 354 | |
352 | kernelfault: | | 355 | kernelfault: |
353 | KSI_INIT_TRAP(&ksi); | | 356 | KSI_INIT_TRAP(&ksi); |
354 | ksi.ksi_signo = SIGSEGV; | | 357 | ksi.ksi_signo = SIGSEGV; |
355 | ksi.ksi_code = SEGV_ACCERR; | | 358 | ksi.ksi_code = SEGV_ACCERR; |
356 | ksi.ksi_trap = type; | | 359 | ksi.ksi_trap = type; |
357 | | | 360 | |
358 | switch (*(u_char *)frame->tf_eip) { | | 361 | switch (*(u_char *)frame->tf_eip) { |
359 | case 0xcf: /* iret */ | | 362 | case 0xcf: /* iret */ |
360 | /* | | 363 | /* |
361 | * The 'iret' instruction faulted, so we have the | | 364 | * The 'iret' instruction faulted, so we have the |
362 | * 'user' registers saved after the kernel %eip:%cs:%fl | | 365 | * 'user' registers saved after the kernel %eip:%cs:%fl |
363 | * of the 'iret' and below that the user %eip:%cs:%fl | | 366 | * of the 'iret' and below that the user %eip:%cs:%fl |
364 | * the 'iret' was processing. | | 367 | * the 'iret' was processing. |
365 | * We must delete the 3 words of kernel return address | | 368 | * We must delete the 3 words of kernel return address |
366 | * from the stack to generate a normal stack frame | | 369 | * from the stack to generate a normal stack frame |
367 | * (eg for sending a SIGSEGV). | | 370 | * (eg for sending a SIGSEGV). |
368 | */ | | 371 | */ |
369 | vframe = (void *)((int *)frame + 3); | | 372 | vframe = (void *)((int *)frame + 3); |
370 | if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags)) | | 373 | if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags)) |
371 | goto we_re_toast; | | 374 | goto we_re_toast; |
372 | memmove(vframe, frame, | | 375 | memmove(vframe, frame, |
373 | offsetof(struct trapframe, tf_eip)); | | 376 | offsetof(struct trapframe, tf_eip)); |
374 | /* Set the faulting address to the user %eip */ | | 377 | /* Set the faulting address to the user %eip */ |
375 | ksi.ksi_addr = (void *)vframe->tf_eip; | | 378 | ksi.ksi_addr = (void *)vframe->tf_eip; |
376 | break; | | 379 | break; |
377 | case 0x8e: | | 380 | case 0x8e: |
378 | switch (*(uint32_t *)frame->tf_eip) { | | 381 | switch (*(uint32_t *)frame->tf_eip) { |
379 | case 0x8e242c8e: /* mov (%esp,%gs), then */ | | 382 | case 0x8e242c8e: /* mov (%esp,%gs), then */ |
380 | case 0x0424648e: /* mov 0x4(%esp),%fs */ | | 383 | case 0x0424648e: /* mov 0x4(%esp),%fs */ |
381 | case 0x0824448e: /* mov 0x8(%esp),%es */ | | 384 | case 0x0824448e: /* mov 0x8(%esp),%es */ |
382 | case 0x0c245c8e: /* mov 0xc(%esp),%ds */ | | 385 | case 0x0c245c8e: /* mov 0xc(%esp),%ds */ |
383 | break; | | 386 | break; |
384 | default: | | 387 | default: |
385 | goto we_re_toast; | | 388 | goto we_re_toast; |
386 | } | | 389 | } |
387 | /* | | 390 | /* |
388 | * We faulted loading one of the user segment registers. | | 391 | * We faulted loading one of the user segment registers. |
389 | * The stack frame containing the user registers is | | 392 | * The stack frame containing the user registers is |
390 | * still valid and is just below the %eip:%cs:%fl of | | 393 | * still valid and is just below the %eip:%cs:%fl of |
391 | * the kernel fault frame. | | 394 | * the kernel fault frame. |
392 | */ | | 395 | */ |
393 | vframe = (void *)(&frame->tf_eflags + 1); | | 396 | vframe = (void *)(&frame->tf_eflags + 1); |
394 | if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags)) | | 397 | if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags)) |
395 | goto we_re_toast; | | 398 | goto we_re_toast; |
396 | /* There is no valid address for the fault */ | | 399 | /* There is no valid address for the fault */ |
397 | break; | | 400 | break; |
398 | default: | | 401 | default: |
399 | goto we_re_toast; | | 402 | goto we_re_toast; |
400 | } | | 403 | } |
401 | /* | | 404 | /* |
402 | * We might have faulted trying to execute the | | 405 | * We might have faulted trying to execute the |
403 | * trampoline for a local (nested) signal handler. | | 406 | * trampoline for a local (nested) signal handler. |
404 | * Only generate SIGSEGV if the user %cs isn't changed. | | 407 | * Only generate SIGSEGV if the user %cs isn't changed. |
405 | * (This is only strictly necessary in the 'iret' case.) | | 408 | * (This is only strictly necessary in the 'iret' case.) |
406 | */ | | 409 | */ |
407 | if (!pmap_exec_fixup(&p->p_vmspace->vm_map, vframe, pcb)) { | | 410 | if (!pmap_exec_fixup(&p->p_vmspace->vm_map, vframe, pcb)) { |
408 | /* Save outer frame for any signal return */ | | 411 | /* Save outer frame for any signal return */ |
409 | l->l_md.md_regs = vframe; | | 412 | l->l_md.md_regs = vframe; |
410 | (*p->p_emul->e_trapsignal)(l, &ksi); | | 413 | (*p->p_emul->e_trapsignal)(l, &ksi); |
411 | } | | 414 | } |
412 | /* Return to user by reloading the user frame */ | | 415 | /* Return to user by reloading the user frame */ |
413 | trap_return_fault_return(vframe); | | 416 | trap_return_fault_return(vframe); |
414 | /* NOTREACHED */ | | 417 | /* NOTREACHED */ |
415 | | | 418 | |
416 | case T_PROTFLT|T_USER: /* protection fault */ | | 419 | case T_PROTFLT|T_USER: /* protection fault */ |
417 | case T_TSSFLT|T_USER: | | 420 | case T_TSSFLT|T_USER: |
418 | case T_SEGNPFLT|T_USER: | | 421 | case T_SEGNPFLT|T_USER: |
419 | case T_STKFLT|T_USER: | | 422 | case T_STKFLT|T_USER: |
420 | case T_ALIGNFLT|T_USER: | | 423 | case T_ALIGNFLT|T_USER: |
421 | KSI_INIT_TRAP(&ksi); | | 424 | KSI_INIT_TRAP(&ksi); |
422 | | | 425 | |
423 | ksi.ksi_addr = (void *)rcr2(); | | 426 | ksi.ksi_addr = (void *)rcr2(); |
424 | switch (type) { | | 427 | switch (type) { |
425 | case T_SEGNPFLT|T_USER: | | 428 | case T_SEGNPFLT|T_USER: |
426 | case T_STKFLT|T_USER: | | 429 | case T_STKFLT|T_USER: |
427 | ksi.ksi_signo = SIGBUS; | | 430 | ksi.ksi_signo = SIGBUS; |
428 | ksi.ksi_code = BUS_ADRERR; | | 431 | ksi.ksi_code = BUS_ADRERR; |
429 | break; | | 432 | break; |
430 | case T_TSSFLT|T_USER: | | 433 | case T_TSSFLT|T_USER: |
431 | ksi.ksi_signo = SIGBUS; | | 434 | ksi.ksi_signo = SIGBUS; |
432 | ksi.ksi_code = BUS_OBJERR; | | 435 | ksi.ksi_code = BUS_OBJERR; |
433 | break; | | 436 | break; |
434 | case T_ALIGNFLT|T_USER: | | 437 | case T_ALIGNFLT|T_USER: |
435 | ksi.ksi_signo = SIGBUS; | | 438 | ksi.ksi_signo = SIGBUS; |
436 | ksi.ksi_code = BUS_ADRALN; | | 439 | ksi.ksi_code = BUS_ADRALN; |
437 | break; | | 440 | break; |
438 | case T_PROTFLT|T_USER: | | 441 | case T_PROTFLT|T_USER: |
439 | #ifdef VM86 | | 442 | #ifdef VM86 |
440 | if (frame->tf_eflags & PSL_VM) { | | 443 | if (frame->tf_eflags & PSL_VM) { |
441 | vm86_gpfault(l, type & ~T_USER); | | 444 | vm86_gpfault(l, type & ~T_USER); |
442 | goto out; | | 445 | goto out; |
443 | } | | 446 | } |
444 | #endif | | 447 | #endif |
445 | /* | | 448 | /* |
446 | * If pmap_exec_fixup does something, | | 449 | * If pmap_exec_fixup does something, |
447 | * let's retry the trap. | | 450 | * let's retry the trap. |
448 | */ | | 451 | */ |
449 | if (pmap_exec_fixup(&p->p_vmspace->vm_map, frame, pcb)){ | | 452 | if (pmap_exec_fixup(&p->p_vmspace->vm_map, frame, pcb)){ |
450 | goto out; | | 453 | goto out; |
451 | } | | 454 | } |
452 | ksi.ksi_signo = SIGSEGV; | | 455 | ksi.ksi_signo = SIGSEGV; |
453 | ksi.ksi_code = SEGV_ACCERR; | | 456 | ksi.ksi_code = SEGV_ACCERR; |
454 | break; | | 457 | break; |
455 | default: | | 458 | default: |
456 | KASSERT(0); | | 459 | KASSERT(0); |
457 | break; | | 460 | break; |
458 | } | | 461 | } |
459 | goto trapsignal; | | 462 | goto trapsignal; |
460 | | | 463 | |
461 | case T_PRIVINFLT|T_USER: /* privileged instruction fault */ | | 464 | case T_PRIVINFLT|T_USER: /* privileged instruction fault */ |
462 | case T_FPOPFLT|T_USER: /* coprocessor operand fault */ | | 465 | case T_FPOPFLT|T_USER: /* coprocessor operand fault */ |
463 | KSI_INIT_TRAP(&ksi); | | 466 | KSI_INIT_TRAP(&ksi); |
464 | ksi.ksi_signo = SIGILL; | | 467 | ksi.ksi_signo = SIGILL; |
465 | ksi.ksi_addr = (void *) frame->tf_eip; | | 468 | ksi.ksi_addr = (void *) frame->tf_eip; |
466 | switch (type) { | | 469 | switch (type) { |
467 | case T_PRIVINFLT|T_USER: | | 470 | case T_PRIVINFLT|T_USER: |
468 | ksi.ksi_code = ILL_PRVOPC; | | 471 | ksi.ksi_code = ILL_PRVOPC; |
469 | break; | | 472 | break; |
470 | case T_FPOPFLT|T_USER: | | 473 | case T_FPOPFLT|T_USER: |
471 | ksi.ksi_code = ILL_COPROC; | | 474 | ksi.ksi_code = ILL_COPROC; |
472 | break; | | 475 | break; |
473 | default: | | 476 | default: |
474 | ksi.ksi_code = 0; | | 477 | ksi.ksi_code = 0; |
475 | break; | | 478 | break; |
476 | } | | 479 | } |
477 | goto trapsignal; | | 480 | goto trapsignal; |
478 | | | 481 | |
479 | case T_ASTFLT|T_USER: | | 482 | case T_ASTFLT|T_USER: |
480 | /* Allow process switch. */ | | 483 | /* Allow process switch. */ |
481 | //curcpu()->ci_data.cpu_nast++; | | 484 | //curcpu()->ci_data.cpu_nast++; |
482 | if (l->l_pflag & LP_OWEUPC) { | | 485 | if (l->l_pflag & LP_OWEUPC) { |
483 | l->l_pflag &= ~LP_OWEUPC; | | 486 | l->l_pflag &= ~LP_OWEUPC; |
484 | ADDUPROF(l); | | 487 | ADDUPROF(l); |
485 | } | | 488 | } |
486 | /* Allow a forced task switch. */ | | 489 | /* Allow a forced task switch. */ |
487 | if (curcpu()->ci_want_resched) { | | 490 | if (curcpu()->ci_want_resched) { |
488 | preempt(); | | 491 | preempt(); |
489 | } | | 492 | } |
490 | goto out; | | 493 | goto out; |
491 | | | 494 | |
492 | case T_BOUND|T_USER: | | 495 | case T_BOUND|T_USER: |
493 | case T_OFLOW|T_USER: | | 496 | case T_OFLOW|T_USER: |
494 | case T_DIVIDE|T_USER: | | 497 | case T_DIVIDE|T_USER: |
495 | KSI_INIT_TRAP(&ksi); | | 498 | KSI_INIT_TRAP(&ksi); |
496 | ksi.ksi_signo = SIGFPE; | | 499 | ksi.ksi_signo = SIGFPE; |
497 | ksi.ksi_addr = (void *)frame->tf_eip; | | 500 | ksi.ksi_addr = (void *)frame->tf_eip; |
498 | switch (type) { | | 501 | switch (type) { |
499 | case T_BOUND|T_USER: | | 502 | case T_BOUND|T_USER: |
500 | ksi.ksi_code = FPE_FLTSUB; | | 503 | ksi.ksi_code = FPE_FLTSUB; |
501 | break; | | 504 | break; |
502 | case T_OFLOW|T_USER: | | 505 | case T_OFLOW|T_USER: |
503 | ksi.ksi_code = FPE_INTOVF; | | 506 | ksi.ksi_code = FPE_INTOVF; |
504 | break; | | 507 | break; |
505 | case T_DIVIDE|T_USER: | | 508 | case T_DIVIDE|T_USER: |
506 | ksi.ksi_code = FPE_INTDIV; | | 509 | ksi.ksi_code = FPE_INTDIV; |
507 | break; | | 510 | break; |
508 | default: | | 511 | default: |
509 | ksi.ksi_code = 0; | | 512 | ksi.ksi_code = 0; |
510 | break; | | 513 | break; |
511 | } | | 514 | } |
512 | goto trapsignal; | | 515 | goto trapsignal; |
513 | | | 516 | |
514 | case T_PAGEFLT: | | 517 | case T_PAGEFLT: |
515 | /* Allow page faults in kernel mode. */ | | 518 | /* Allow page faults in kernel mode. */ |
516 | if (__predict_false(l == NULL)) | | 519 | if (__predict_false(l == NULL)) |
517 | goto we_re_toast; | | 520 | goto we_re_toast; |
518 | | | 521 | |
519 | /* | | 522 | /* |
520 | * fusubail is used by [fs]uswintr() to prevent page faulting | | 523 | * fusubail is used by [fs]uswintr() to prevent page faulting |
521 | * from inside the profiling interrupt. | | 524 | * from inside the profiling interrupt. |
522 | */ | | 525 | */ |
523 | onfault = pcb->pcb_onfault; | | 526 | onfault = pcb->pcb_onfault; |
524 | if (onfault == fusubail || onfault == return_address_fault) { | | 527 | if (onfault == fusubail || onfault == return_address_fault) { |
525 | goto copyefault; | | 528 | goto copyefault; |
526 | } | | 529 | } |
527 | if (cpu_intr_p() || (l->l_pflag & LP_INTR) != 0) { | | 530 | if (cpu_intr_p() || (l->l_pflag & LP_INTR) != 0) { |
528 | goto we_re_toast; | | 531 | goto we_re_toast; |
529 | } | | 532 | } |
530 | | | 533 | |
531 | cr2 = rcr2(); | | 534 | cr2 = rcr2(); |
532 | | | 535 | |
533 | if (frame->tf_err & PGEX_X) { | | 536 | if (frame->tf_err & PGEX_X) { |
534 | /* SMEP might have brought us here */ | | 537 | /* SMEP might have brought us here */ |
535 | if (cr2 > VM_MIN_ADDRESS && cr2 <= VM_MAXUSER_ADDRESS) | | 538 | if (cr2 > VM_MIN_ADDRESS && cr2 <= VM_MAXUSER_ADDRESS) |
536 | panic("prevented execution of %p (SMEP)", | | 539 | panic("prevented execution of %p (SMEP)", |
537 | (void *)cr2); | | 540 | (void *)cr2); |
538 | } | | 541 | } |
539 | | | 542 | |
540 | goto faultcommon; | | 543 | goto faultcommon; |
541 | | | 544 | |
542 | case T_PAGEFLT|T_USER: { /* page fault */ | | 545 | case T_PAGEFLT|T_USER: { /* page fault */ |
543 | register vaddr_t va; | | 546 | register vaddr_t va; |
544 | register struct vmspace *vm; | | 547 | register struct vmspace *vm; |
545 | register struct vm_map *map; | | 548 | register struct vm_map *map; |
546 | vm_prot_t ftype; | | 549 | vm_prot_t ftype; |
547 | extern struct vm_map *kernel_map; | | 550 | extern struct vm_map *kernel_map; |
548 | | | 551 | |
549 | cr2 = rcr2(); | | 552 | cr2 = rcr2(); |
550 | faultcommon: | | 553 | faultcommon: |
551 | vm = p->p_vmspace; | | 554 | vm = p->p_vmspace; |
552 | if (__predict_false(vm == NULL)) { | | 555 | if (__predict_false(vm == NULL)) { |
553 | goto we_re_toast; | | 556 | goto we_re_toast; |
554 | } | | 557 | } |
555 | pcb->pcb_cr2 = cr2; | | 558 | pcb->pcb_cr2 = cr2; |
556 | va = trunc_page((vaddr_t)cr2); | | 559 | va = trunc_page((vaddr_t)cr2); |
557 | /* | | 560 | /* |
558 | * It is only a kernel address space fault iff: | | 561 | * It is only a kernel address space fault iff: |
559 | * 1. (type & T_USER) == 0 and | | 562 | * 1. (type & T_USER) == 0 and |
560 | * 2. pcb_onfault not set or | | 563 | * 2. pcb_onfault not set or |
561 | * 3. pcb_onfault set but supervisor space fault | | 564 | * 3. pcb_onfault set but supervisor space fault |
562 | * The last can occur during an exec() copyin where the | | 565 | * The last can occur during an exec() copyin where the |
563 | * argument space is lazy-allocated. | | 566 | * argument space is lazy-allocated. |
564 | */ | | 567 | */ |
565 | if (type == T_PAGEFLT && va >= VM_MIN_KERNEL_ADDRESS) | | 568 | if (type == T_PAGEFLT && va >= VM_MIN_KERNEL_ADDRESS) |
566 | map = kernel_map; | | 569 | map = kernel_map; |
567 | else | | 570 | else |
568 | map = &vm->vm_map; | | 571 | map = &vm->vm_map; |
569 | if (frame->tf_err & PGEX_W) | | 572 | if (frame->tf_err & PGEX_W) |
570 | ftype = VM_PROT_WRITE; | | 573 | ftype = VM_PROT_WRITE; |
571 | else if (frame->tf_err & PGEX_X) | | 574 | else if (frame->tf_err & PGEX_X) |
572 | ftype = VM_PROT_EXECUTE; | | 575 | ftype = VM_PROT_EXECUTE; |
573 | else | | 576 | else |
574 | ftype = VM_PROT_READ; | | 577 | ftype = VM_PROT_READ; |
575 | | | 578 | |
576 | #ifdef DIAGNOSTIC | | 579 | #ifdef DIAGNOSTIC |
577 | if (map == kernel_map && va == 0) { | | 580 | if (map == kernel_map && va == 0) { |
578 | printf("trap: bad kernel access at %lx\n", va); | | 581 | printf("trap: bad kernel access at %lx\n", va); |
579 | goto we_re_toast; | | 582 | goto we_re_toast; |
580 | } | | 583 | } |
581 | #endif | | 584 | #endif |
582 | /* Fault the original page in. */ | | 585 | /* Fault the original page in. */ |
583 | onfault = pcb->pcb_onfault; | | 586 | onfault = pcb->pcb_onfault; |
584 | pcb->pcb_onfault = NULL; | | 587 | pcb->pcb_onfault = NULL; |
585 | error = uvm_fault(map, va, ftype); | | 588 | error = uvm_fault(map, va, ftype); |
586 | pcb->pcb_onfault = onfault; | | 589 | pcb->pcb_onfault = onfault; |
587 | if (error == 0) { | | 590 | if (error == 0) { |
588 | if (map != kernel_map && (void *)va >= vm->vm_maxsaddr) | | 591 | if (map != kernel_map && (void *)va >= vm->vm_maxsaddr) |
589 | uvm_grow(p, va); | | 592 | uvm_grow(p, va); |
590 | | | 593 | |
591 | pfail = false; | | 594 | pfail = false; |
592 | while (type == T_PAGEFLT) { | | 595 | while (type == T_PAGEFLT) { |
593 | /* | | 596 | /* |
594 | * we need to switch pmap now if we're in | | 597 | * we need to switch pmap now if we're in |
595 | * the middle of copyin/out. | | 598 | * the middle of copyin/out. |
596 | * | | 599 | * |
597 | * but we don't need to do so for kcopy as | | 600 | * but we don't need to do so for kcopy as |
598 | * it never touch userspace. | | 601 | * it never touch userspace. |
599 | */ | | 602 | */ |
600 | kpreempt_disable(); | | 603 | kpreempt_disable(); |
601 | if (curcpu()->ci_want_pmapload) { | | 604 | if (curcpu()->ci_want_pmapload) { |
602 | onfault = onfault_handler(pcb, frame); | | 605 | onfault = onfault_handler(pcb, frame); |
603 | if (onfault != kcopy_fault) { | | 606 | if (onfault != kcopy_fault) { |
604 | pmap_load(); | | 607 | pmap_load(); |
605 | } | | 608 | } |
606 | } | | 609 | } |
607 | /* | | 610 | /* |
608 | * We need to keep the pmap loaded and | | 611 | * We need to keep the pmap loaded and |
609 | * so avoid being preempted until back | | 612 | * so avoid being preempted until back |
610 | * into the copy functions. Disable | | 613 | * into the copy functions. Disable |
611 | * interrupts at the hardware level before | | 614 | * interrupts at the hardware level before |
612 | * re-enabling preemption. Interrupts | | 615 | * re-enabling preemption. Interrupts |
613 | * will be re-enabled by 'iret' when | | 616 | * will be re-enabled by 'iret' when |
614 | * returning back out of the trap stub. | | 617 | * returning back out of the trap stub. |
615 | * They'll only be re-enabled when the | | 618 | * They'll only be re-enabled when the |
616 | * program counter is once again in | | 619 | * program counter is once again in |
617 | * the copy functions, and so visible | | 620 | * the copy functions, and so visible |
618 | * to cpu_kpreempt_exit(). | | 621 | * to cpu_kpreempt_exit(). |
619 | */ | | 622 | */ |
620 | #ifndef XEN | | 623 | #ifndef XEN |
621 | x86_disable_intr(); | | 624 | x86_disable_intr(); |
622 | #endif | | 625 | #endif |
623 | l->l_nopreempt--; | | 626 | l->l_nopreempt--; |
624 | if (l->l_nopreempt > 0 || !l->l_dopreempt || | | 627 | if (l->l_nopreempt > 0 || !l->l_dopreempt || |
625 | pfail) { | | 628 | pfail) { |
626 | return; | | 629 | return; |
627 | } | | 630 | } |
628 | #ifndef XEN | | 631 | #ifndef XEN |
629 | x86_enable_intr(); | | 632 | x86_enable_intr(); |
630 | #endif | | 633 | #endif |
631 | /* | | 634 | /* |
632 | * If preemption fails for some reason, | | 635 | * If preemption fails for some reason, |
633 | * don't retry it. The conditions won't | | 636 | * don't retry it. The conditions won't |
634 | * change under our nose. | | 637 | * change under our nose. |
635 | */ | | 638 | */ |
636 | pfail = kpreempt(0); | | 639 | pfail = kpreempt(0); |
637 | } | | 640 | } |
638 | goto out; | | 641 | goto out; |
639 | } | | 642 | } |
640 | | | 643 | |
641 | if (type == T_PAGEFLT) { | | 644 | if (type == T_PAGEFLT) { |
642 | onfault = onfault_handler(pcb, frame); | | 645 | onfault = onfault_handler(pcb, frame); |
643 | if (onfault != NULL) | | 646 | if (onfault != NULL) |
644 | goto copyfault; | | 647 | goto copyfault; |
645 | printf("uvm_fault(%p, %#lx, %d) -> %#x\n", | | 648 | printf("uvm_fault(%p, %#lx, %d) -> %#x\n", |
646 | map, va, ftype, error); | | 649 | map, va, ftype, error); |
647 | goto kernelfault; | | 650 | goto kernelfault; |
648 | } | | 651 | } |
649 | | | 652 | |
650 | KSI_INIT_TRAP(&ksi); | | 653 | KSI_INIT_TRAP(&ksi); |
651 | ksi.ksi_trap = type & ~T_USER; | | 654 | ksi.ksi_trap = type & ~T_USER; |
652 | ksi.ksi_addr = (void *)cr2; | | 655 | ksi.ksi_addr = (void *)cr2; |
653 | switch (error) { | | 656 | switch (error) { |
654 | case EINVAL: | | 657 | case EINVAL: |
655 | ksi.ksi_signo = SIGBUS; | | 658 | ksi.ksi_signo = SIGBUS; |
656 | ksi.ksi_code = BUS_ADRERR; | | 659 | ksi.ksi_code = BUS_ADRERR; |
657 | break; | | 660 | break; |
658 | case EACCES: | | 661 | case EACCES: |
659 | ksi.ksi_signo = SIGSEGV; | | 662 | ksi.ksi_signo = SIGSEGV; |
660 | ksi.ksi_code = SEGV_ACCERR; | | 663 | ksi.ksi_code = SEGV_ACCERR; |
661 | error = EFAULT; | | 664 | error = EFAULT; |
662 | break; | | 665 | break; |
663 | case ENOMEM: | | 666 | case ENOMEM: |
664 | ksi.ksi_signo = SIGKILL; | | 667 | ksi.ksi_signo = SIGKILL; |
665 | printf("UVM: pid %d.%d (%s), uid %d killed: " | | 668 | printf("UVM: pid %d.%d (%s), uid %d killed: " |
666 | "out of swap\n", p->p_pid, l->l_lid, p->p_comm, | | 669 | "out of swap\n", p->p_pid, l->l_lid, p->p_comm, |
667 | l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); | | 670 | l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); |
668 | break; | | 671 | break; |
669 | default: | | 672 | default: |
670 | ksi.ksi_signo = SIGSEGV; | | 673 | ksi.ksi_signo = SIGSEGV; |
671 | ksi.ksi_code = SEGV_MAPERR; | | 674 | ksi.ksi_code = SEGV_MAPERR; |
672 | break; | | 675 | break; |
673 | } | | 676 | } |
674 | | | 677 | |
675 | #ifdef TRAP_SIGDEBUG | | 678 | #ifdef TRAP_SIGDEBUG |
676 | printf("pid %d.%d (%s): signal %d at eip %x addr %lx " | | 679 | printf("pid %d.%d (%s): signal %d at eip %#x addr %#lx " |
677 | "error %d\n", p->p_pid, l->l_lid, p->p_comm, ksi.ksi_signo, | | 680 | "error %d\n", p->p_pid, l->l_lid, p->p_comm, ksi.ksi_signo, |
678 | frame->tf_eip, va, error); | | 681 | frame->tf_eip, va, error); |
679 | #endif | | 682 | #endif |
680 | (*p->p_emul->e_trapsignal)(l, &ksi); | | 683 | (*p->p_emul->e_trapsignal)(l, &ksi); |
681 | break; | | 684 | break; |
682 | } | | 685 | } |
683 | | | 686 | |
684 | case T_TRCTRAP: | | 687 | case T_TRCTRAP: |
685 | /* | | 688 | /* |
686 | * Ignore debug register trace traps due to | | 689 | * Ignore debug register trace traps due to |
687 | * accesses in the user's address space, which | | 690 | * accesses in the user's address space, which |
688 | * can happen under several conditions such as | | 691 | * can happen under several conditions such as |
689 | * if a user sets a watchpoint on a buffer and | | 692 | * if a user sets a watchpoint on a buffer and |
690 | * then passes that buffer to a system call. | | 693 | * then passes that buffer to a system call. |
691 | * We still want to get TRCTRAPS for addresses | | 694 | * We still want to get TRCTRAPS for addresses |
692 | * in kernel space because that is useful when | | 695 | * in kernel space because that is useful when |
693 | * debugging the kernel. | | 696 | * debugging the kernel. |
694 | */ | | 697 | */ |
695 | if (x86_dbregs_user_trap()) | | 698 | if (x86_dbregs_user_trap()) |
696 | break; | | 699 | break; |
697 | | | 700 | |
698 | /* Check whether they single-stepped into a lcall. */ | | 701 | /* Check whether they single-stepped into a lcall. */ |
699 | if (frame->tf_eip == (int)IDTVEC(osyscall)) | | 702 | if (frame->tf_eip == (int)IDTVEC(osyscall)) |
700 | return; | | 703 | return; |
701 | if (frame->tf_eip == (int)IDTVEC(osyscall) + 1) { | | 704 | if (frame->tf_eip == (int)IDTVEC(osyscall) + 1) { |
702 | frame->tf_eflags &= ~PSL_T; | | 705 | frame->tf_eflags &= ~PSL_T; |
703 | return; | | 706 | return; |
704 | } | | 707 | } |
705 | goto we_re_toast; | | 708 | goto we_re_toast; |
706 | | | 709 | |
707 | case T_BPTFLT|T_USER: /* bpt instruction fault */ | | 710 | case T_BPTFLT|T_USER: /* bpt instruction fault */ |
708 | case T_TRCTRAP|T_USER: /* trace trap */ | | 711 | case T_TRCTRAP|T_USER: /* trace trap */ |
709 | /* | | 712 | /* |
710 | * Don't go single-stepping into a RAS. | | 713 | * Don't go single-stepping into a RAS. |
711 | */ | | 714 | */ |
712 | if (p->p_raslist == NULL || | | 715 | if (p->p_raslist == NULL || |
713 | (ras_lookup(p, (void *)frame->tf_eip) == (void *)-1)) { | | 716 | (ras_lookup(p, (void *)frame->tf_eip) == (void *)-1)) { |
714 | KSI_INIT_TRAP(&ksi); | | 717 | KSI_INIT_TRAP(&ksi); |
715 | ksi.ksi_signo = SIGTRAP; | | 718 | ksi.ksi_signo = SIGTRAP; |
716 | ksi.ksi_trap = type & ~T_USER; | | 719 | ksi.ksi_trap = type & ~T_USER; |
717 | if (x86_dbregs_user_trap()) { | | 720 | if (x86_dbregs_user_trap()) { |
718 | x86_dbregs_store_dr6(l); | | 721 | x86_dbregs_store_dr6(l); |
719 | ksi.ksi_code = TRAP_DBREG; | | 722 | ksi.ksi_code = TRAP_DBREG; |
720 | } else if (type == (T_BPTFLT|T_USER)) | | 723 | } else if (type == (T_BPTFLT|T_USER)) |
721 | ksi.ksi_code = TRAP_BRKPT; | | 724 | ksi.ksi_code = TRAP_BRKPT; |
722 | else | | 725 | else |
723 | ksi.ksi_code = TRAP_TRACE; | | 726 | ksi.ksi_code = TRAP_TRACE; |
724 | ksi.ksi_addr = (void *)frame->tf_eip; | | 727 | ksi.ksi_addr = (void *)frame->tf_eip; |
725 | (*p->p_emul->e_trapsignal)(l, &ksi); | | 728 | (*p->p_emul->e_trapsignal)(l, &ksi); |
726 | } | | 729 | } |
727 | break; | | 730 | break; |
728 | | | 731 | |
729 | case T_NMI: | | 732 | case T_NMI: |
730 | if (nmi_dispatch(frame)) | | 733 | if (nmi_dispatch(frame)) |
731 | return; | | 734 | return; |
732 | /* NMI can be hooked up to a pushbutton for debugging */ | | 735 | /* NMI can be hooked up to a pushbutton for debugging */ |
733 | if (kgdb_trap(type, frame)) | | 736 | if (kgdb_trap(type, frame)) |
734 | return; | | 737 | return; |
735 | if (kdb_trap(type, 0, frame)) | | 738 | if (kdb_trap(type, 0, frame)) |
736 | return; | | 739 | return; |
737 | /* machine/parity/power fail/"kitchen sink" faults */ | | 740 | /* machine/parity/power fail/"kitchen sink" faults */ |
738 | #if NMCA > 0 | | 741 | #if NMCA > 0 |
739 | mca_nmi(); | | 742 | mca_nmi(); |
740 | #endif | | 743 | #endif |
741 | x86_nmi(); | | 744 | x86_nmi(); |
742 | } | | 745 | } |
743 | | | 746 | |
744 | if ((type & T_USER) == 0) | | 747 | if ((type & T_USER) == 0) |
745 | return; | | 748 | return; |
746 | out: | | 749 | out: |
747 | userret(l); | | 750 | userret(l); |
748 | return; | | 751 | return; |
749 | trapsignal: | | 752 | trapsignal: |
750 | ksi.ksi_trap = type & ~T_USER; | | 753 | ksi.ksi_trap = type & ~T_USER; |
751 | (*p->p_emul->e_trapsignal)(l, &ksi); | | 754 | (*p->p_emul->e_trapsignal)(l, &ksi); |
752 | userret(l); | | 755 | userret(l); |
753 | } | | 756 | } |
754 | | | 757 | |
755 | /* | | 758 | /* |
756 | * startlwp: start of a new LWP. | | 759 | * startlwp: start of a new LWP. |
757 | */ | | 760 | */ |
758 | void | | 761 | void |
759 | startlwp(void *arg) | | 762 | startlwp(void *arg) |
760 | { | | 763 | { |
761 | ucontext_t *uc = arg; | | 764 | ucontext_t *uc = arg; |
762 | lwp_t *l = curlwp; | | 765 | lwp_t *l = curlwp; |
763 | int error __diagused; | | 766 | int error __diagused; |
764 | | | 767 | |
765 | error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); | | 768 | error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); |
766 | KASSERT(error == 0); | | 769 | KASSERT(error == 0); |
767 | | | 770 | |
768 | kmem_free(uc, sizeof(ucontext_t)); | | 771 | kmem_free(uc, sizeof(ucontext_t)); |
769 | userret(l); | | 772 | userret(l); |
770 | } | | 773 | } |
| | | 774 | |
| | | 775 | #ifdef TRAP_SIGDEBUG |
| | | 776 | void |
| | | 777 | frame_dump(struct trapframe *tf, struct pcb *pcb) |
| | | 778 | { |
| | | 779 | int i; |
| | | 780 | unsigned long *p; |
| | | 781 | uint64_t fsd, gsd; |
| | | 782 | |
| | | 783 | printf("trapframe %p\n", tf); |
| | | 784 | printf("eip 0x%08x esp 0x%08x efl 0x%08x\n", |
| | | 785 | tf->tf_eip, tf->tf_esp, tf->tf_eflags); |
| | | 786 | printf("edi 0x%08x esi 0x%08x edx 0x%08x\n", |
| | | 787 | tf->tf_edi, tf->tf_esi, tf->tf_edx); |
| | | 788 | printf("ecx 0x%08x\n", |
| | | 789 | tf->tf_ecx); |
| | | 790 | printf("ebp 0x%08x ebx 0x%08x eax 0x%08x\n", |
| | | 791 | tf->tf_ebp, tf->tf_ebx, tf->tf_eax); |
| | | 792 | printf("cs 0x%04x ds 0x%04x es 0x%04x " |
| | | 793 | "fs 0x%04x gs 0x%04x ss 0x%04x\n", |
| | | 794 | tf->tf_cs & 0xffff, tf->tf_ds & 0xffff, tf->tf_es & 0xffff, |
| | | 795 | tf->tf_fs & 0xffff, tf->tf_gs & 0xffff, tf->tf_ss & 0xffff); |
| | | 796 | memcpy(&fsd, &pcb->pcb_fsd, sizeof(fsd)); |
| | | 797 | memcpy(&gsd, &pcb->pcb_gsd, sizeof(gsd)); |
| | | 798 | printf("fsbase 0x%016llx gsbase 0x%016llx\n", fsd, gsd); |
| | | 799 | printf("\n"); |
| | | 800 | printf("Stack dump:\n"); |
| | | 801 | for (i = 0, p = (unsigned long *) tf; i < 20; i ++, p += 8) |
| | | 802 | printf(" 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx" |
| | | 803 | " 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx\n", |
| | | 804 | p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); |
| | | 805 | printf("\n"); |
| | | 806 | } |
| | | 807 | #endif |