trap.c revision 1.18 1 /* $NetBSD: trap.c,v 1.18 2019/08/07 09:49:40 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33
34 __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.18 2019/08/07 09:49:40 jmcneill Exp $");
35
36 #include "opt_arm_intr_impl.h"
37 #include "opt_compat_netbsd32.h"
38
39 #include <sys/param.h>
40 #include <sys/kauth.h>
41 #include <sys/types.h>
42 #include <sys/atomic.h>
43 #include <sys/cpu.h>
44 #ifdef KDB
45 #include <sys/kdb.h>
46 #endif
47 #include <sys/proc.h>
48 #include <sys/systm.h>
49 #include <sys/signal.h>
50 #include <sys/signalvar.h>
51 #include <sys/siginfo.h>
52
53 #ifdef ARM_INTR_IMPL
54 #include ARM_INTR_IMPL
55 #else
56 #error ARM_INTR_IMPL not defined
57 #endif
58
59 #ifndef ARM_IRQ_HANDLER
60 #error ARM_IRQ_HANDLER not defined
61 #endif
62
63 #include <aarch64/userret.h>
64 #include <aarch64/frame.h>
65 #include <aarch64/machdep.h>
66 #include <aarch64/armreg.h>
67 #include <aarch64/locore.h>
68
69 #ifdef KDB
70 #include <machine/db_machdep.h>
71 #endif
72 #ifdef DDB
73 #include <ddb/db_output.h>
74 #include <machine/db_machdep.h>
75 #endif
76
77 #ifdef DDB
78 int sigill_debug = 0;
79 #endif
80
81 const char * const trap_names[] = {
82 [ESR_EC_UNKNOWN] = "Unknown Reason (Illegal Instruction)",
83 [ESR_EC_SERROR] = "SError Interrupt",
84 [ESR_EC_WFX] = "WFI or WFE instruction execution",
85 [ESR_EC_ILL_STATE] = "Illegal Execution State",
86
87 [ESR_EC_SYS_REG] = "MSR/MRS/SYS instruction",
88 [ESR_EC_SVC_A64] = "SVC Instruction Execution",
89 [ESR_EC_HVC_A64] = "HVC Instruction Execution",
90 [ESR_EC_SMC_A64] = "SMC Instruction Execution",
91
92 [ESR_EC_INSN_ABT_EL0] = "Instruction Abort (EL0)",
93 [ESR_EC_INSN_ABT_EL1] = "Instruction Abort (EL1)",
94 [ESR_EC_DATA_ABT_EL0] = "Data Abort (EL0)",
95 [ESR_EC_DATA_ABT_EL1] = "Data Abort (EL1)",
96
97 [ESR_EC_PC_ALIGNMENT] = "Misaligned PC",
98 [ESR_EC_SP_ALIGNMENT] = "Misaligned SP",
99
100 [ESR_EC_FP_ACCESS] = "Access to SIMD/FP Registers",
101 [ESR_EC_FP_TRAP_A64] = "FP Exception",
102
103 [ESR_EC_BRKPNT_EL0] = "Breakpoint Exception (EL0)",
104 [ESR_EC_BRKPNT_EL1] = "Breakpoint Exception (EL1)",
105 [ESR_EC_SW_STEP_EL0] = "Software Step (EL0)",
106 [ESR_EC_SW_STEP_EL1] = "Software Step (EL1)",
107 [ESR_EC_WTCHPNT_EL0] = "Watchpoint (EL0)",
108 [ESR_EC_WTCHPNT_EL1] = "Watchpoint (EL1)",
109 [ESR_EC_BKPT_INSN_A64] = "BKPT Instruction Execution",
110
111 [ESR_EC_CP15_RT] = "A32: MCR/MRC access to CP15",
112 [ESR_EC_CP15_RRT] = "A32: MCRR/MRRC access to CP15",
113 [ESR_EC_CP14_RT] = "A32: MCR/MRC access to CP14",
114 [ESR_EC_CP14_DT] = "A32: LDC/STC access to CP14",
115 [ESR_EC_CP14_RRT] = "A32: MRRC access to CP14",
116 [ESR_EC_SVC_A32] = "A32: SVC Instruction Execution",
117 [ESR_EC_HVC_A32] = "A32: HVC Instruction Execution",
118 [ESR_EC_SMC_A32] = "A32: SMC Instruction Execution",
119 [ESR_EC_FPID] = "A32: MCR/MRC access to CP10",
120 [ESR_EC_FP_TRAP_A32] = "A32: FP Exception",
121 [ESR_EC_BKPT_INSN_A32] = "A32: BKPT Instruction Execution",
122 [ESR_EC_VECTOR_CATCH] = "A32: Vector Catch Exception"
123 };
124
125 const char *
126 eclass_trapname(uint32_t eclass)
127 {
128 static char trapnamebuf[sizeof("Unknown trap 0x????????")];
129
130 if (eclass >= __arraycount(trap_names) || trap_names[eclass] == NULL) {
131 snprintf(trapnamebuf, sizeof(trapnamebuf),
132 "Unknown trap %#02x", eclass);
133 return trapnamebuf;
134 }
135 return trap_names[eclass];
136 }
137
138 void
139 userret(struct lwp *l)
140 {
141 mi_userret(l);
142 }
143
144 void
145 trap_doast(struct trapframe *tf)
146 {
147 struct lwp * const l = curlwp;
148
149 /*
150 * allow to have a chance of context switch just prior to user
151 * exception return.
152 */
153 #ifdef __HAVE_PREEMPTION
154 kpreempt_disable();
155 #endif
156 struct cpu_info * const ci = curcpu();
157
158 ci->ci_data.cpu_ntrap++;
159
160 KDASSERT(ci->ci_cpl == IPL_NONE);
161 const int want_resched = ci->ci_want_resched;
162 #ifdef __HAVE_PREEMPTION
163 kpreempt_enable();
164 #endif
165
166 if (l->l_pflag & LP_OWEUPC) {
167 l->l_pflag &= ~LP_OWEUPC;
168 ADDUPROF(l);
169 }
170
171 /* Allow a forced task switch. */
172 if (want_resched)
173 preempt();
174 userret(l);
175 }
176
177 void
178 trap_el1h_sync(struct trapframe *tf)
179 {
180 const uint32_t esr = tf->tf_esr;
181 const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
182
183 /* re-enable traps and interrupts */
184 if (!(tf->tf_spsr & SPSR_I))
185 daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
186 else
187 daif_enable(DAIF_D|DAIF_A);
188
189 switch (eclass) {
190 case ESR_EC_INSN_ABT_EL1:
191 case ESR_EC_DATA_ABT_EL1:
192 data_abort_handler(tf, eclass);
193 break;
194
195 case ESR_EC_BRKPNT_EL1:
196 case ESR_EC_SW_STEP_EL1:
197 case ESR_EC_WTCHPNT_EL1:
198 case ESR_EC_BKPT_INSN_A64:
199 #ifdef DDB
200 if (eclass == ESR_EC_BRKPNT_EL1)
201 kdb_trap(DB_TRAP_BREAKPOINT, tf);
202 else if (eclass == ESR_EC_BKPT_INSN_A64)
203 kdb_trap(DB_TRAP_BKPT_INSN, tf);
204 else if (eclass == ESR_EC_WTCHPNT_EL1)
205 kdb_trap(DB_TRAP_WATCHPOINT, tf);
206 else if (eclass == ESR_EC_SW_STEP_EL1)
207 kdb_trap(DB_TRAP_SW_STEP, tf);
208 else
209 kdb_trap(DB_TRAP_UNKNOWN, tf);
210 #else
211 panic("No debugger in kernel");
212 #endif
213 break;
214
215 case ESR_EC_FP_ACCESS:
216 case ESR_EC_FP_TRAP_A64:
217 case ESR_EC_PC_ALIGNMENT:
218 case ESR_EC_SP_ALIGNMENT:
219 case ESR_EC_ILL_STATE:
220 default:
221 panic("Trap: fatal %s: pc=%016" PRIx64 " sp=%016" PRIx64
222 " esr=%08x", eclass_trapname(eclass), tf->tf_pc, tf->tf_sp,
223 esr);
224 break;
225 }
226 }
227
228 void
229 trap_el0_sync(struct trapframe *tf)
230 {
231 struct lwp * const l = curlwp;
232 const uint32_t esr = tf->tf_esr;
233 const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
234
235 /* disable trace */
236 reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
237 /* enable traps and interrupts */
238 daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
239
240 switch (eclass) {
241 case ESR_EC_INSN_ABT_EL0:
242 case ESR_EC_DATA_ABT_EL0:
243 data_abort_handler(tf, eclass);
244 userret(l);
245 break;
246
247 case ESR_EC_SVC_A64:
248 (*l->l_proc->p_md.md_syscall)(tf);
249 break;
250 case ESR_EC_FP_ACCESS:
251 fpu_load(l);
252 userret(l);
253 break;
254 case ESR_EC_FP_TRAP_A64:
255 do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */
256 userret(l);
257 break;
258
259 case ESR_EC_PC_ALIGNMENT:
260 do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr);
261 userret(l);
262 break;
263 case ESR_EC_SP_ALIGNMENT:
264 do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_sp, esr);
265 userret(l);
266 break;
267
268 case ESR_EC_BKPT_INSN_A64:
269 case ESR_EC_BRKPNT_EL0:
270 case ESR_EC_WTCHPNT_EL0:
271 do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr);
272 userret(l);
273 break;
274 case ESR_EC_SW_STEP_EL0:
275 /* disable trace, and send trace trap */
276 tf->tf_spsr &= ~SPSR_SS;
277 do_trapsignal(l, SIGTRAP, TRAP_TRACE, (void *)tf->tf_pc, esr);
278 userret(l);
279 break;
280
281 default:
282 case ESR_EC_UNKNOWN:
283 #ifdef DDB
284 if (sigill_debug) {
285 /* show illegal instruction */
286 printf("TRAP: pid %d (%s), uid %d: %s:"
287 " esr=0x%lx: pc=0x%lx: %s\n",
288 curlwp->l_proc->p_pid, curlwp->l_proc->p_comm,
289 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1,
290 eclass_trapname(eclass), tf->tf_esr, tf->tf_pc,
291 strdisasm(tf->tf_pc));
292 }
293 #endif
294 /* illegal or not implemented instruction */
295 do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr);
296 userret(l);
297 break;
298 }
299 }
300
301 void
302 interrupt(struct trapframe *tf)
303 {
304 struct cpu_info * const ci = curcpu();
305
306 #ifdef STACKCHECKS
307 struct lwp *l = curlwp;
308 void *sp = (void *)reg_sp_read();
309 if (l->l_addr >= sp) {
310 panic("lwp/interrupt stack overflow detected."
311 " lwp=%p, sp=%p, l_addr=%p", l, sp, l->l_addr);
312 }
313 #endif
314
315 /* disable trace */
316 reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
317
318 /* enable traps */
319 daif_enable(DAIF_D|DAIF_A);
320
321 ci->ci_intr_depth++;
322 ARM_IRQ_HANDLER(tf);
323 ci->ci_intr_depth--;
324
325 cpu_dosoftints();
326 }
327
328 void
329 trap_el0_32sync(struct trapframe *tf)
330 {
331 struct lwp * const l = curlwp;
332 const uint32_t esr = tf->tf_esr;
333 const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
334
335 /* disable trace */
336 reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
337 /* enable traps and interrupts */
338 daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
339
340 switch (eclass) {
341 #ifdef COMPAT_NETBSD32
342 case ESR_EC_INSN_ABT_EL0:
343 case ESR_EC_DATA_ABT_EL0:
344 data_abort_handler(tf, eclass);
345 userret(l);
346 break;
347
348 case ESR_EC_SVC_A32:
349 (*l->l_proc->p_md.md_syscall)(tf);
350 break;
351 case ESR_EC_FP_ACCESS:
352 fpu_load(l);
353 userret(l);
354 break;
355 case ESR_EC_FP_TRAP_A32:
356 do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */
357 userret(l);
358 break;
359
360 case ESR_EC_PC_ALIGNMENT:
361 do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr);
362 userret(l);
363 break;
364 case ESR_EC_SP_ALIGNMENT:
365 do_trapsignal(l, SIGBUS, BUS_ADRALN,
366 (void *)tf->tf_reg[13], esr); /* sp is r13 on AArch32 */
367 userret(l);
368 break;
369
370 case ESR_EC_BKPT_INSN_A32:
371 do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr);
372 userret(l);
373 break;
374
375 case ESR_EC_CP15_RT:
376 case ESR_EC_CP15_RRT:
377 case ESR_EC_CP14_RT:
378 case ESR_EC_CP14_DT:
379 case ESR_EC_CP14_RRT:
380 #endif /* COMPAT_NETBSD32 */
381 default:
382 #ifdef DDB
383 if (sigill_debug) {
384 /* show illegal instruction */
385 printf("TRAP: pid %d (%s), uid %d: %s:"
386 " esr=0x%lx: pc=0x%lx: %s\n",
387 curlwp->l_proc->p_pid, curlwp->l_proc->p_comm,
388 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1,
389 eclass_trapname(eclass), tf->tf_esr, tf->tf_pc,
390 strdisasm_aarch32(tf->tf_pc));
391 }
392 #endif
393 /* illegal or not implemented instruction */
394 do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr);
395 userret(l);
396 break;
397 }
398 }
399
400 #define bad_trap_panic(trapfunc) \
401 void \
402 trapfunc(struct trapframe *tf) \
403 { \
404 panic("%s", __func__); \
405 }
406 bad_trap_panic(trap_el1t_sync)
407 bad_trap_panic(trap_el1t_irq)
408 bad_trap_panic(trap_el1t_fiq)
409 bad_trap_panic(trap_el1t_error)
410 bad_trap_panic(trap_el1h_fiq)
411 bad_trap_panic(trap_el1h_error)
412 bad_trap_panic(trap_el0_fiq)
413 bad_trap_panic(trap_el0_error)
414 bad_trap_panic(trap_el0_32fiq)
415 bad_trap_panic(trap_el0_32error)
416
417 void
418 cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb, int val)
419 {
420 tf->tf_reg[19] = fb->fb_reg[FB_X19];
421 tf->tf_reg[20] = fb->fb_reg[FB_X20];
422 tf->tf_reg[21] = fb->fb_reg[FB_X21];
423 tf->tf_reg[22] = fb->fb_reg[FB_X22];
424 tf->tf_reg[23] = fb->fb_reg[FB_X23];
425 tf->tf_reg[24] = fb->fb_reg[FB_X24];
426 tf->tf_reg[25] = fb->fb_reg[FB_X25];
427 tf->tf_reg[26] = fb->fb_reg[FB_X26];
428 tf->tf_reg[27] = fb->fb_reg[FB_X27];
429 tf->tf_reg[28] = fb->fb_reg[FB_X28];
430 tf->tf_reg[29] = fb->fb_reg[FB_X29];
431 tf->tf_sp = fb->fb_reg[FB_SP];
432 tf->tf_pc = fb->fb_reg[FB_LR];
433 tf->tf_reg[0] = val;
434 }
435
436 #ifdef TRAP_SIGDEBUG
437 static void
438 frame_dump(const struct trapframe *tf)
439 {
440 const struct reg *r = &tf->tf_regs;
441
442 printf("trapframe %p\n", tf);
443 for (size_t i = 0; i < __arraycount(r->r_reg); i++) {
444 printf(" r%.2zu %#018" PRIx64 "%c", i, r->r_reg[i],
445 " \n"[i && (i & 1) == 0]);
446 }
447
448 printf("\n");
449 printf(" sp %#018" PRIx64 " pc %#018" PRIx64 "\n",
450 r->r_sp, r->r_pc);
451 printf(" spsr %#018" PRIx64 " tpidr %#018" PRIx64 "\n",
452 r->r_spsr, r->r_tpidr);
453 printf(" esr %#018" PRIx64 " far %#018" PRIx64 "\n",
454 tf->tf_esr, tf->tf_far);
455
456 printf("\n");
457 hexdump(printf, "Stack dump", tf, 256);
458 }
459
460 static void
461 sigdebug(const struct trapframe *tf, const ksiginfo_t *ksi)
462 {
463 struct lwp *l = curlwp;
464 struct proc *p = l->l_proc;
465 const uint32_t eclass = __SHIFTOUT(ksi->ksi_trap, ESR_EC);
466
467 printf("pid %d.%d (%s): signal %d (trap %#x) "
468 "@pc %#" PRIx64 ", addr %p, error=%s\n",
469 p->p_pid, l->l_lid, p->p_comm, ksi->ksi_signo, ksi->ksi_trap,
470 tf->tf_regs.r_pc, ksi->ksi_addr, eclass_trapname(eclass));
471 frame_dump(tf);
472 }
473 #endif
474
475 void do_trapsignal1(
476 #ifdef TRAP_SIGDEBUG
477 const char *func,
478 size_t line,
479 struct trapframe *tf,
480 #endif
481 struct lwp *l, int signo, int code, void *addr, int trap)
482 {
483 ksiginfo_t ksi;
484
485 KSI_INIT_TRAP(&ksi);
486 ksi.ksi_signo = signo;
487 ksi.ksi_code = code;
488 ksi.ksi_addr = addr;
489 ksi.ksi_trap = trap;
490 #ifdef TRAP_SIGDEBUG
491 printf("%s, %zu: ", func, line);
492 sigdebug(tf, &ksi);
493 #endif
494 (*l->l_proc->p_emul->e_trapsignal)(l, &ksi);
495 }
496