| @@ -1,396 +1,406 @@ | | | @@ -1,396 +1,406 @@ |
1 | /* $NetBSD: trap.c,v 1.132 2013/10/25 16:30:52 martin Exp $ */ | | 1 | /* $NetBSD: trap.c,v 1.133 2015/03/03 13:23:48 martin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1994 Ludd, University of Lule}, Sweden. | | 4 | * Copyright (c) 1994 Ludd, University of Lule}, Sweden. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. All advertising materials mentioning features or use of this software | | 15 | * 3. All advertising materials mentioning features or use of this software |
16 | * must display the following acknowledgement: | | 16 | * must display the following acknowledgement: |
17 | * This product includes software developed at Ludd, University of Lule}. | | 17 | * This product includes software developed at Ludd, University of Lule}. |
18 | * 4. The name of the author may not be used to endorse or promote products | | 18 | * 4. The name of the author may not be used to endorse or promote products |
19 | * derived from this software without specific prior written permission | | 19 | * derived from this software without specific prior written permission |
20 | * | | 20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
24 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 24 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* All bugs are subject to removal without further notice */ | | 33 | /* All bugs are subject to removal without further notice */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.132 2013/10/25 16:30:52 martin Exp $"); | | 36 | __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.133 2015/03/03 13:23:48 martin Exp $"); |
37 | | | 37 | |
38 | #include "opt_ddb.h" | | 38 | #include "opt_ddb.h" |
39 | #include "opt_multiprocessor.h" | | 39 | #include "opt_multiprocessor.h" |
40 | | | 40 | |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/systm.h> | | 42 | #include <sys/systm.h> |
43 | #include <sys/cpu.h> | | 43 | #include <sys/cpu.h> |
44 | #include <sys/exec.h> | | 44 | #include <sys/exec.h> |
45 | #include <sys/kauth.h> | | 45 | #include <sys/kauth.h> |
46 | #include <sys/proc.h> | | 46 | #include <sys/proc.h> |
47 | #include <sys/signalvar.h> | | 47 | #include <sys/signalvar.h> |
48 | | | 48 | |
49 | #include <uvm/uvm_extern.h> | | 49 | #include <uvm/uvm_extern.h> |
50 | | | 50 | |
51 | #include <machine/trap.h> | | 51 | #include <machine/trap.h> |
52 | #include <machine/userret.h> | | 52 | #include <machine/userret.h> |
53 | | | 53 | |
54 | #ifdef DDB | | 54 | #ifdef DDB |
55 | #include <machine/db_machdep.h> | | 55 | #include <machine/db_machdep.h> |
56 | #endif | | 56 | #endif |
57 | #include <vax/vax/db_disasm.h> | | 57 | #include <vax/vax/db_disasm.h> |
58 | #include <kern/syscalls.c> | | 58 | #include <kern/syscalls.c> |
59 | #include <sys/ktrace.h> | | 59 | #include <sys/ktrace.h> |
60 | | | 60 | |
61 | #ifdef TRAPDEBUG | | 61 | #ifdef TRAPDEBUG |
62 | volatile int faultdebug = 0; | | 62 | volatile int faultdebug = 0; |
63 | #endif | | 63 | #endif |
64 | | | 64 | |
65 | int cpu_printfataltraps = 0; | | 65 | int cpu_printfataltraps = 0; |
66 | | | 66 | |
67 | void trap (struct trapframe *); | | 67 | void trap (struct trapframe *); |
68 | | | 68 | |
69 | const char * const traptypes[]={ | | 69 | const char * const traptypes[]={ |
70 | "reserved addressing", | | 70 | "reserved addressing", |
71 | "privileged instruction", | | 71 | "privileged instruction", |
72 | "reserved operand", | | 72 | "reserved operand", |
73 | "breakpoint instruction", | | 73 | "breakpoint instruction", |
74 | "XFC instruction", | | 74 | "XFC instruction", |
75 | "system call ", | | 75 | "system call ", |
76 | "arithmetic trap", | | 76 | "arithmetic trap", |
77 | "asynchronous system trap", | | 77 | "asynchronous system trap", |
78 | "page table length fault", | | 78 | "page table length fault", |
79 | "translation violation fault", | | 79 | "translation violation fault", |
80 | "trace trap", | | 80 | "trace trap", |
81 | "compatibility mode fault", | | 81 | "compatibility mode fault", |
82 | "access violation fault", | | 82 | "access violation fault", |
83 | "", | | 83 | "", |
84 | "", | | 84 | "", |
85 | "KSP invalid", | | 85 | "KSP invalid", |
86 | "", | | 86 | "", |
87 | "kernel debugger trap" | | 87 | "kernel debugger trap" |
88 | }; | | 88 | }; |
89 | int no_traps = 18; | | 89 | int no_traps = 18; |
90 | | | 90 | |
91 | #define USERMODE_P(tf) ((((tf)->tf_psl) & (PSL_U)) == PSL_U) | | 91 | #define USERMODE_P(tf) ((((tf)->tf_psl) & (PSL_U)) == PSL_U) |
92 | | | 92 | |
93 | void | | 93 | void |
94 | trap(struct trapframe *tf) | | 94 | trap(struct trapframe *tf) |
95 | { | | 95 | { |
96 | u_int sig = 0, type = tf->tf_trap, code = 0; | | 96 | u_int sig = 0, type = tf->tf_trap, code = 0; |
97 | u_int rv, addr; | | 97 | u_int rv, addr; |
98 | bool trapsig = true; | | 98 | bool trapsig = true; |
99 | const bool usermode = USERMODE_P(tf); | | 99 | const bool usermode = USERMODE_P(tf); |
100 | struct lwp * const l = curlwp; | | 100 | struct lwp * const l = curlwp; |
101 | struct proc * const p = l->l_proc; | | 101 | struct proc * const p = l->l_proc; |
102 | struct pcb * const pcb = lwp_getpcb(l); | | 102 | struct pcb * const pcb = lwp_getpcb(l); |
103 | u_quad_t oticks = 0; | | 103 | u_quad_t oticks = 0; |
104 | struct vmspace *vm; | | 104 | struct vmspace *vm; |
105 | struct vm_map *map; | | 105 | struct vm_map *map; |
106 | vm_prot_t ftype; | | 106 | vm_prot_t ftype; |
107 | void *onfault = pcb->pcb_onfault; | | 107 | void *onfault = pcb->pcb_onfault; |
108 | | | 108 | |
109 | KASSERT(p != NULL); | | 109 | KASSERT(p != NULL); |
110 | curcpu()->ci_data.cpu_ntrap++; | | 110 | curcpu()->ci_data.cpu_ntrap++; |
111 | if (usermode) { | | 111 | if (usermode) { |
112 | type |= T_USER; | | 112 | type |= T_USER; |
113 | oticks = p->p_sticks; | | 113 | oticks = p->p_sticks; |
114 | l->l_md.md_utf = tf; | | 114 | l->l_md.md_utf = tf; |
115 | LWP_CACHE_CREDS(l, p); | | 115 | LWP_CACHE_CREDS(l, p); |
116 | } | | 116 | } |
117 | | | 117 | |
118 | type &= ~(T_WRITE|T_PTEFETCH); | | 118 | type &= ~(T_WRITE|T_PTEFETCH); |
119 | | | 119 | |
120 | | | 120 | |
121 | #ifdef TRAPDEBUG | | 121 | #ifdef TRAPDEBUG |
122 | if(tf->tf_trap==7) goto fram; | | 122 | if(tf->tf_trap==7) goto fram; |
123 | if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", | | 123 | if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", |
124 | tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); | | 124 | tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); |
125 | fram: | | 125 | fram: |
126 | #endif | | 126 | #endif |
127 | switch (type) { | | 127 | switch (type) { |
128 | | | 128 | |
129 | default: | | 129 | default: |
130 | #ifdef DDB | | 130 | #ifdef DDB |
131 | kdb_trap(tf); | | 131 | kdb_trap(tf); |
132 | #endif | | 132 | #endif |
133 | panic("trap: type %x, code %x, pc %x, psl %x", | | 133 | panic("trap: type %x, code %x, pc %x, psl %x", |
134 | (u_int)tf->tf_trap, (u_int)tf->tf_code, | | 134 | (u_int)tf->tf_trap, (u_int)tf->tf_code, |
135 | (u_int)tf->tf_pc, (u_int)tf->tf_psl); | | 135 | (u_int)tf->tf_pc, (u_int)tf->tf_psl); |
136 | | | 136 | |
137 | case T_KSPNOTVAL: | | 137 | case T_KSPNOTVAL: |
138 | panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)", | | 138 | panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)", |
139 | p->p_pid, l->l_lid, l->l_name ? l->l_name : "??", | | 139 | p->p_pid, l->l_lid, l->l_name ? l->l_name : "??", |
140 | mfpr(PR_KSP), (u_int)tf->tf_pc, pcb, | | 140 | mfpr(PR_KSP), (u_int)tf->tf_pc, pcb, |
141 | (u_int)tf->tf_fp, (u_int)tf->tf_psl); | | 141 | (u_int)tf->tf_fp, (u_int)tf->tf_psl); |
142 | | | 142 | |
143 | case T_TRANSFLT|T_USER: | | 143 | case T_TRANSFLT|T_USER: |
144 | case T_TRANSFLT: | | 144 | case T_TRANSFLT: |
145 | /* | | 145 | /* |
146 | * BUG! BUG! BUG! BUG! BUG! | | 146 | * BUG! BUG! BUG! BUG! BUG! |
147 | * Due to a hardware bug (at in least KA65x CPUs) a double | | 147 | * Due to a hardware bug (at in least KA65x CPUs) a double |
148 | * page table fetch trap will cause a translation fault | | 148 | * page table fetch trap will cause a translation fault |
149 | * even if access in the SPT PTE entry specifies 'no access'. | | 149 | * even if access in the SPT PTE entry specifies 'no access'. |
150 | * In for example section 6.4.2 in VAX Architecture | | 150 | * In for example section 6.4.2 in VAX Architecture |
151 | * Reference Manual it states that if a page both are invalid | | 151 | * Reference Manual it states that if a page both are invalid |
152 | * and have no access set, a 'access violation fault' occurs. | | 152 | * and have no access set, a 'access violation fault' occurs. |
153 | * Therefore, we must fall through here... | | 153 | * Therefore, we must fall through here... |
154 | */ | | 154 | */ |
155 | #ifdef nohwbug | | 155 | #ifdef nohwbug |
156 | panic("translation fault"); | | 156 | panic("translation fault"); |
157 | #endif | | 157 | #endif |
158 | | | 158 | |
159 | case T_PTELEN|T_USER: /* Page table length exceeded */ | | 159 | case T_PTELEN|T_USER: /* Page table length exceeded */ |
160 | case T_ACCFLT|T_USER: | | 160 | case T_ACCFLT|T_USER: |
161 | if (tf->tf_code < 0) { /* Check for kernel space */ | | 161 | if (tf->tf_code < 0) { /* Check for kernel space */ |
162 | sig = SIGSEGV; | | 162 | sig = SIGSEGV; |
163 | code = SEGV_ACCERR; | | 163 | code = SEGV_ACCERR; |
164 | break; | | 164 | break; |
165 | } | | 165 | } |
166 | | | 166 | |
167 | case T_PTELEN: | | 167 | case T_PTELEN: |
168 | #ifndef MULTIPROCESSOR | | 168 | #ifndef MULTIPROCESSOR |
169 | /* | | 169 | /* |
170 | * If we referred to an address beyond the end of the system | | 170 | * If we referred to an address beyond the end of the system |
171 | * page table, it may be due to a failed CAS | | 171 | * page table, it may be due to a failed CAS |
172 | * restartable-atomic-sequence. If it is, restart it at the | | 172 | * restartable-atomic-sequence. If it is, restart it at the |
173 | * beginning and restart. | | 173 | * beginning and restart. |
174 | */ | | 174 | */ |
175 | { | | 175 | { |
176 | extern const uint8_t cas32_ras_start[], cas32_ras_end[]; | | 176 | extern const uint8_t cas32_ras_start[], cas32_ras_end[]; |
177 | if (tf->tf_code == CASMAGIC | | 177 | if (tf->tf_code == CASMAGIC |
178 | && tf->tf_pc >= (uintptr_t) cas32_ras_start | | 178 | && tf->tf_pc >= (uintptr_t) cas32_ras_start |
179 | && tf->tf_pc < (uintptr_t) cas32_ras_end) { | | 179 | && tf->tf_pc < (uintptr_t) cas32_ras_end) { |
180 | tf->tf_pc = (uintptr_t) cas32_ras_start; | | 180 | tf->tf_pc = (uintptr_t) cas32_ras_start; |
181 | trapsig = false; | | 181 | trapsig = false; |
182 | break; | | 182 | break; |
183 | } | | 183 | } |
184 | } | | 184 | } |
185 | /* FALLTHROUGH */ | | 185 | /* FALLTHROUGH */ |
186 | #endif | | 186 | #endif |
187 | case T_ACCFLT: | | 187 | case T_ACCFLT: |
188 | #ifdef TRAPDEBUG | | 188 | #ifdef TRAPDEBUG |
189 | if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", | | 189 | if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", |
190 | tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); | | 190 | tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); |
191 | #endif | | 191 | #endif |
192 | #ifdef DIAGNOSTIC | | 192 | #ifdef DIAGNOSTIC |
193 | if (p == 0) | | 193 | if (p == 0) |
194 | panic("trap: access fault: addr %lx code %lx", | | 194 | panic("trap: access fault: addr %lx code %lx", |
195 | tf->tf_pc, tf->tf_code); | | 195 | tf->tf_pc, tf->tf_code); |
196 | if (tf->tf_psl & PSL_IS) | | 196 | if (tf->tf_psl & PSL_IS) |
197 | panic("trap: pflt on IS"); | | 197 | panic("trap: pflt on IS"); |
198 | #endif | | 198 | #endif |
199 | | | 199 | |
200 | /* | | 200 | /* |
201 | * Page tables are allocated in pmap_enter(). We get | | 201 | * Page tables are allocated in pmap_enter(). We get |
202 | * info from below if it is a page table fault, but | | 202 | * info from below if it is a page table fault, but |
203 | * UVM may want to map in pages without faults, so | | 203 | * UVM may want to map in pages without faults, so |
204 | * because we must check for PTE pages anyway we don't | | 204 | * because we must check for PTE pages anyway we don't |
205 | * bother doing it here. | | 205 | * bother doing it here. |
206 | */ | | 206 | */ |
207 | addr = trunc_page(tf->tf_code); | | 207 | addr = trunc_page(tf->tf_code); |
208 | if (!usermode && (tf->tf_code < 0)) { | | 208 | if (!usermode && (tf->tf_code < 0)) { |
209 | vm = NULL; | | 209 | vm = NULL; |
210 | map = kernel_map; | | 210 | map = kernel_map; |
211 | | | 211 | |
212 | } else { | | 212 | } else { |
213 | vm = p->p_vmspace; | | 213 | vm = p->p_vmspace; |
214 | map = &vm->vm_map; | | 214 | map = &vm->vm_map; |
215 | } | | 215 | } |
216 | | | 216 | |
217 | if (tf->tf_trap & T_WRITE) | | 217 | if (tf->tf_trap & T_WRITE) |
218 | ftype = VM_PROT_WRITE; | | 218 | ftype = VM_PROT_WRITE; |
219 | else | | 219 | else |
220 | ftype = VM_PROT_READ; | | 220 | ftype = VM_PROT_READ; |
221 | | | 221 | |
222 | pcb->pcb_onfault = NULL; | | 222 | pcb->pcb_onfault = NULL; |
223 | rv = uvm_fault(map, addr, ftype); | | 223 | rv = uvm_fault(map, addr, ftype); |
224 | pcb->pcb_onfault = onfault; | | 224 | pcb->pcb_onfault = onfault; |
225 | if (rv != 0) { | | 225 | if (rv != 0) { |
226 | if (!usermode) { | | 226 | if (!usermode) { |
227 | if (onfault) { | | 227 | if (onfault) { |
228 | pcb->pcb_onfault = NULL; | | 228 | pcb->pcb_onfault = NULL; |
229 | tf->tf_pc = (unsigned)onfault; | | 229 | tf->tf_pc = (unsigned)onfault; |
230 | tf->tf_psl &= ~PSL_FPD; | | 230 | tf->tf_psl &= ~PSL_FPD; |
231 | tf->tf_r0 = rv; | | 231 | tf->tf_r0 = rv; |
232 | return; | | 232 | return; |
233 | } | | 233 | } |
234 | printf("r0=%08lx r1=%08lx r2=%08lx r3=%08lx ", | | 234 | printf("r0=%08lx r1=%08lx r2=%08lx r3=%08lx ", |
235 | tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3); | | 235 | tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3); |
236 | printf("r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n", | | 236 | printf("r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n", |
237 | tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7); | | 237 | tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7); |
238 | printf( | | 238 | printf( |
239 | "r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n", | | 239 | "r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n", |
240 | tf->tf_r8, tf->tf_r9, tf->tf_r10, | | 240 | tf->tf_r8, tf->tf_r9, tf->tf_r10, |
241 | tf->tf_r11); | | 241 | tf->tf_r11); |
242 | printf("ap=%08lx fp=%08lx sp=%08lx pc=%08lx\n", | | 242 | printf("ap=%08lx fp=%08lx sp=%08lx pc=%08lx\n", |
243 | tf->tf_ap, tf->tf_fp, tf->tf_sp, tf->tf_pc); | | 243 | tf->tf_ap, tf->tf_fp, tf->tf_sp, tf->tf_pc); |
244 | panic("SEGV in kernel mode: pc %#lx addr %#lx", | | 244 | panic("SEGV in kernel mode: pc %#lx addr %#lx", |
245 | tf->tf_pc, tf->tf_code); | | 245 | tf->tf_pc, tf->tf_code); |
246 | } | | 246 | } |
247 | code = SEGV_ACCERR; | | 247 | switch (rv) { |
248 | if (rv == ENOMEM) { | | 248 | case ENOMEM: |
249 | printf("UVM: pid %d (%s), uid %d killed: " | | 249 | printf("UVM: pid %d (%s), uid %d killed: " |
250 | "out of swap\n", | | 250 | "out of swap\n", |
251 | p->p_pid, p->p_comm, | | 251 | p->p_pid, p->p_comm, |
252 | l->l_cred ? | | 252 | l->l_cred ? |
253 | kauth_cred_geteuid(l->l_cred) : -1); | | 253 | kauth_cred_geteuid(l->l_cred) : -1); |
254 | sig = SIGKILL; | | 254 | sig = SIGKILL; |
255 | } else { | | 255 | code = SI_NOINFO; |
| | | 256 | break; |
| | | 257 | case EINVAL: |
| | | 258 | code = BUS_ADRERR; |
| | | 259 | sig = SIGBUS; |
| | | 260 | break; |
| | | 261 | case EACCES: |
| | | 262 | code = SEGV_ACCERR; |
256 | sig = SIGSEGV; | | 263 | sig = SIGSEGV; |
257 | if (rv != EACCES) | | 264 | break; |
258 | code = SEGV_MAPERR; | | 265 | default: |
| | | 266 | code = SEGV_MAPERR; |
| | | 267 | sig = SIGSEGV; |
| | | 268 | break; |
259 | } | | 269 | } |
260 | } else { | | 270 | } else { |
261 | trapsig = false; | | 271 | trapsig = false; |
262 | if (map != kernel_map && addr > 0 | | 272 | if (map != kernel_map && addr > 0 |
263 | && (void *)addr >= vm->vm_maxsaddr) | | 273 | && (void *)addr >= vm->vm_maxsaddr) |
264 | uvm_grow(p, addr); | | 274 | uvm_grow(p, addr); |
265 | } | | 275 | } |
266 | break; | | 276 | break; |
267 | | | 277 | |
268 | case T_BPTFLT|T_USER: | | 278 | case T_BPTFLT|T_USER: |
269 | sig = SIGTRAP; | | 279 | sig = SIGTRAP; |
270 | code = TRAP_BRKPT; | | 280 | code = TRAP_BRKPT; |
271 | break; | | 281 | break; |
272 | case T_TRCTRAP|T_USER: | | 282 | case T_TRCTRAP|T_USER: |
273 | sig = SIGTRAP; | | 283 | sig = SIGTRAP; |
274 | code = TRAP_TRACE; | | 284 | code = TRAP_TRACE; |
275 | tf->tf_psl &= ~PSL_T; | | 285 | tf->tf_psl &= ~PSL_T; |
276 | break; | | 286 | break; |
277 | | | 287 | |
278 | case T_PRIVINFLT|T_USER: | | 288 | case T_PRIVINFLT|T_USER: |
279 | sig = SIGILL; | | 289 | sig = SIGILL; |
280 | code = ILL_PRVOPC; | | 290 | code = ILL_PRVOPC; |
281 | break; | | 291 | break; |
282 | case T_RESADFLT|T_USER: | | 292 | case T_RESADFLT|T_USER: |
283 | sig = SIGILL; | | 293 | sig = SIGILL; |
284 | code = ILL_ILLADR; | | 294 | code = ILL_ILLADR; |
285 | break; | | 295 | break; |
286 | case T_RESOPFLT|T_USER: | | 296 | case T_RESOPFLT|T_USER: |
287 | sig = SIGILL; | | 297 | sig = SIGILL; |
288 | code = ILL_ILLOPC; | | 298 | code = ILL_ILLOPC; |
289 | break; | | 299 | break; |
290 | | | 300 | |
291 | case T_XFCFLT|T_USER: | | 301 | case T_XFCFLT|T_USER: |
292 | sig = SIGEMT; | | 302 | sig = SIGEMT; |
293 | break; | | 303 | break; |
294 | | | 304 | |
295 | case T_ARITHFLT|T_USER: | | 305 | case T_ARITHFLT|T_USER: |
296 | sig = SIGFPE; | | 306 | sig = SIGFPE; |
297 | switch (tf->tf_code) { | | 307 | switch (tf->tf_code) { |
298 | case ATRP_INTOVF: code = FPE_INTOVF; break; | | 308 | case ATRP_INTOVF: code = FPE_INTOVF; break; |
299 | case ATRP_INTDIV: code = FPE_INTDIV; break; | | 309 | case ATRP_INTDIV: code = FPE_INTDIV; break; |
300 | case ATRP_FLTOVF: code = FPE_FLTOVF; break; | | 310 | case ATRP_FLTOVF: code = FPE_FLTOVF; break; |
301 | case ATRP_FLTDIV: code = FPE_FLTDIV; break; | | 311 | case ATRP_FLTDIV: code = FPE_FLTDIV; break; |
302 | case ATRP_FLTUND: code = FPE_FLTUND; break; | | 312 | case ATRP_FLTUND: code = FPE_FLTUND; break; |
303 | case ATRP_DECOVF: code = FPE_INTOVF; break; | | 313 | case ATRP_DECOVF: code = FPE_INTOVF; break; |
304 | case ATRP_FLTSUB: code = FPE_FLTSUB; break; | | 314 | case ATRP_FLTSUB: code = FPE_FLTSUB; break; |
305 | case AFLT_FLTDIV: code = FPE_FLTDIV; break; | | 315 | case AFLT_FLTDIV: code = FPE_FLTDIV; break; |
306 | case AFLT_FLTUND: code = FPE_FLTUND; break; | | 316 | case AFLT_FLTUND: code = FPE_FLTUND; break; |
307 | case AFLT_FLTOVF: code = FPE_FLTOVF; break; | | 317 | case AFLT_FLTOVF: code = FPE_FLTOVF; break; |
308 | default: code = FPE_FLTINV; break; | | 318 | default: code = FPE_FLTINV; break; |
309 | } | | 319 | } |
310 | break; | | 320 | break; |
311 | | | 321 | |
312 | case T_ASTFLT|T_USER: | | 322 | case T_ASTFLT|T_USER: |
313 | mtpr(AST_NO,PR_ASTLVL); | | 323 | mtpr(AST_NO,PR_ASTLVL); |
314 | trapsig = false; | | 324 | trapsig = false; |
315 | if (curcpu()->ci_want_resched) | | 325 | if (curcpu()->ci_want_resched) |
316 | preempt(); | | 326 | preempt(); |
317 | break; | | 327 | break; |
318 | | | 328 | |
319 | #ifdef DDB | | 329 | #ifdef DDB |
320 | case T_BPTFLT: /* Kernel breakpoint */ | | 330 | case T_BPTFLT: /* Kernel breakpoint */ |
321 | case T_KDBTRAP: | | 331 | case T_KDBTRAP: |
322 | case T_KDBTRAP|T_USER: | | 332 | case T_KDBTRAP|T_USER: |
323 | case T_TRCTRAP: | | 333 | case T_TRCTRAP: |
324 | kdb_trap(tf); | | 334 | kdb_trap(tf); |
325 | return; | | 335 | return; |
326 | #endif | | 336 | #endif |
327 | } | | 337 | } |
328 | if (trapsig) { | | 338 | if (trapsig) { |
329 | ksiginfo_t ksi; | | 339 | ksiginfo_t ksi; |
330 | if ((sig == SIGSEGV || sig == SIGILL) | | 340 | if ((sig == SIGSEGV || sig == SIGILL) |
331 | && cpu_printfataltraps | | 341 | && cpu_printfataltraps |
332 | && (p->p_slflag & PSL_TRACED) == 0 | | 342 | && (p->p_slflag & PSL_TRACED) == 0 |
333 | && !sigismember(&p->p_sigctx.ps_sigcatch, sig)) | | 343 | && !sigismember(&p->p_sigctx.ps_sigcatch, sig)) |
334 | printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", | | 344 | printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", |
335 | p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap, | | 345 | p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap, |
336 | tf->tf_code, tf->tf_pc, tf->tf_psl); | | 346 | tf->tf_code, tf->tf_pc, tf->tf_psl); |
337 | KSI_INIT_TRAP(&ksi); | | 347 | KSI_INIT_TRAP(&ksi); |
338 | ksi.ksi_signo = sig; | | 348 | ksi.ksi_signo = sig; |
339 | ksi.ksi_trap = tf->tf_trap; | | 349 | ksi.ksi_trap = tf->tf_trap; |
340 | ksi.ksi_addr = (void *)tf->tf_code; | | 350 | ksi.ksi_addr = (void *)tf->tf_code; |
341 | ksi.ksi_code = code; | | 351 | ksi.ksi_code = code; |
342 | | | 352 | |
343 | /* | | 353 | /* |
344 | * Arithmetic exceptions can be of two kinds: | | 354 | * Arithmetic exceptions can be of two kinds: |
345 | * - traps (codes 1..7), where pc points to the | | 355 | * - traps (codes 1..7), where pc points to the |
346 | * next instruction to execute. | | 356 | * next instruction to execute. |
347 | * - faults (codes 8..10), where pc points to the | | 357 | * - faults (codes 8..10), where pc points to the |
348 | * faulting instruction. | | 358 | * faulting instruction. |
349 | * In the latter case, we need to advance pc by ourselves | | 359 | * In the latter case, we need to advance pc by ourselves |
350 | * to prevent a signal loop. | | 360 | * to prevent a signal loop. |
351 | * | | 361 | * |
352 | * XXX this is gross -- miod | | 362 | * XXX this is gross -- miod |
353 | */ | | 363 | */ |
354 | if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8)) | | 364 | if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8)) |
355 | tf->tf_pc = skip_opcode(tf->tf_pc); | | 365 | tf->tf_pc = skip_opcode(tf->tf_pc); |
356 | | | 366 | |
357 | trapsignal(l, &ksi); | | 367 | trapsignal(l, &ksi); |
358 | } | | 368 | } |
359 | | | 369 | |
360 | if (!usermode) | | 370 | if (!usermode) |
361 | return; | | 371 | return; |
362 | | | 372 | |
363 | userret(l, tf, oticks); | | 373 | userret(l, tf, oticks); |
364 | } | | 374 | } |
365 | | | 375 | |
366 | void | | 376 | void |
367 | setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) | | 377 | setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) |
368 | { | | 378 | { |
369 | struct trapframe * const tf = l->l_md.md_utf; | | 379 | struct trapframe * const tf = l->l_md.md_utf; |
370 | | | 380 | |
371 | tf->tf_pc = pack->ep_entry + 2; | | 381 | tf->tf_pc = pack->ep_entry + 2; |
372 | tf->tf_sp = stack; | | 382 | tf->tf_sp = stack; |
373 | tf->tf_r6 = stack; /* for ELF */ | | 383 | tf->tf_r6 = stack; /* for ELF */ |
374 | tf->tf_r7 = 0; /* for ELF */ | | 384 | tf->tf_r7 = 0; /* for ELF */ |
375 | tf->tf_r8 = 0; /* for ELF */ | | 385 | tf->tf_r8 = 0; /* for ELF */ |
376 | tf->tf_r9 = l->l_proc->p_psstrp; /* for ELF */ | | 386 | tf->tf_r9 = l->l_proc->p_psstrp; /* for ELF */ |
377 | } | | 387 | } |
378 | | | 388 | |
379 | | | 389 | |
380 | /* | | 390 | /* |
381 | * Start a new LWP | | 391 | * Start a new LWP |
382 | */ | | 392 | */ |
383 | void | | 393 | void |
384 | startlwp(void *arg) | | 394 | startlwp(void *arg) |
385 | { | | 395 | { |
386 | ucontext_t * const uc = arg; | | 396 | ucontext_t * const uc = arg; |
387 | lwp_t * const l = curlwp; | | 397 | lwp_t * const l = curlwp; |
388 | int error __diagused; | | 398 | int error __diagused; |
389 | | | 399 | |
390 | error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); | | 400 | error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); |
391 | KASSERT(error == 0); | | 401 | KASSERT(error == 0); |
392 | | | 402 | |
393 | kmem_free(uc, sizeof(ucontext_t)); | | 403 | kmem_free(uc, sizeof(ucontext_t)); |
394 | /* XXX - profiling spoiled here */ | | 404 | /* XXX - profiling spoiled here */ |
395 | userret(l, l->l_md.md_utf, l->l_proc->p_sticks); | | 405 | userret(l, l->l_md.md_utf, l->l_proc->p_sticks); |
396 | } | | 406 | } |