trap.c revision 1.27 1 /* $NetBSD: trap.c,v 1.27 2020/04/13 05:40:25 maxv 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.27 2020/04/13 05:40:25 maxv Exp $");
35
36 #include "opt_arm_intr_impl.h"
37 #include "opt_compat_netbsd32.h"
38 #include "opt_dtrace.h"
39
40 #include <sys/param.h>
41 #include <sys/kauth.h>
42 #include <sys/types.h>
43 #include <sys/atomic.h>
44 #include <sys/cpu.h>
45 #ifdef KDB
46 #include <sys/kdb.h>
47 #endif
48 #include <sys/proc.h>
49 #include <sys/systm.h>
50 #include <sys/signal.h>
51 #include <sys/signalvar.h>
52 #include <sys/siginfo.h>
53
54 #ifdef ARM_INTR_IMPL
55 #include ARM_INTR_IMPL
56 #else
57 #error ARM_INTR_IMPL not defined
58 #endif
59
60 #ifndef ARM_IRQ_HANDLER
61 #error ARM_IRQ_HANDLER not defined
62 #endif
63
64 #include <aarch64/userret.h>
65 #include <aarch64/frame.h>
66 #include <aarch64/machdep.h>
67 #include <aarch64/armreg.h>
68 #include <aarch64/locore.h>
69
70 #ifdef KDB
71 #include <machine/db_machdep.h>
72 #endif
73 #ifdef DDB
74 #include <ddb/db_output.h>
75 #include <machine/db_machdep.h>
76 #endif
77 #ifdef KDTRACE_HOOKS
78 #include <sys/dtrace_bsd.h>
79 #endif
80
81 #ifdef DDB
82 int sigill_debug = 0;
83 #endif
84
85 #ifdef KDTRACE_HOOKS
86 dtrace_doubletrap_func_t dtrace_doubletrap_func = NULL;
87 dtrace_trap_func_t dtrace_trap_func = NULL;
88 int (*dtrace_invop_jump_addr)(struct trapframe *);
89 #endif
90
91 const char * const trap_names[] = {
92 [ESR_EC_UNKNOWN] = "Unknown Reason (Illegal Instruction)",
93 [ESR_EC_SERROR] = "SError Interrupt",
94 [ESR_EC_WFX] = "WFI or WFE instruction execution",
95 [ESR_EC_ILL_STATE] = "Illegal Execution State",
96
97 [ESR_EC_BTE_A64] = "Branch Target Exception",
98
99 [ESR_EC_SYS_REG] = "MSR/MRS/SYS instruction",
100 [ESR_EC_SVC_A64] = "SVC Instruction Execution",
101 [ESR_EC_HVC_A64] = "HVC Instruction Execution",
102 [ESR_EC_SMC_A64] = "SMC Instruction Execution",
103
104 [ESR_EC_INSN_ABT_EL0] = "Instruction Abort (EL0)",
105 [ESR_EC_INSN_ABT_EL1] = "Instruction Abort (EL1)",
106 [ESR_EC_DATA_ABT_EL0] = "Data Abort (EL0)",
107 [ESR_EC_DATA_ABT_EL1] = "Data Abort (EL1)",
108
109 [ESR_EC_PC_ALIGNMENT] = "Misaligned PC",
110 [ESR_EC_SP_ALIGNMENT] = "Misaligned SP",
111
112 [ESR_EC_FP_ACCESS] = "Access to SIMD/FP Registers",
113 [ESR_EC_FP_TRAP_A64] = "FP Exception",
114
115 [ESR_EC_BRKPNT_EL0] = "Breakpoint Exception (EL0)",
116 [ESR_EC_BRKPNT_EL1] = "Breakpoint Exception (EL1)",
117 [ESR_EC_SW_STEP_EL0] = "Software Step (EL0)",
118 [ESR_EC_SW_STEP_EL1] = "Software Step (EL1)",
119 [ESR_EC_WTCHPNT_EL0] = "Watchpoint (EL0)",
120 [ESR_EC_WTCHPNT_EL1] = "Watchpoint (EL1)",
121 [ESR_EC_BKPT_INSN_A64] = "BKPT Instruction Execution",
122
123 [ESR_EC_CP15_RT] = "A32: MCR/MRC access to CP15",
124 [ESR_EC_CP15_RRT] = "A32: MCRR/MRRC access to CP15",
125 [ESR_EC_CP14_RT] = "A32: MCR/MRC access to CP14",
126 [ESR_EC_CP14_DT] = "A32: LDC/STC access to CP14",
127 [ESR_EC_CP14_RRT] = "A32: MRRC access to CP14",
128 [ESR_EC_SVC_A32] = "A32: SVC Instruction Execution",
129 [ESR_EC_HVC_A32] = "A32: HVC Instruction Execution",
130 [ESR_EC_SMC_A32] = "A32: SMC Instruction Execution",
131 [ESR_EC_FPID] = "A32: MCR/MRC access to CP10",
132 [ESR_EC_FP_TRAP_A32] = "A32: FP Exception",
133 [ESR_EC_BKPT_INSN_A32] = "A32: BKPT Instruction Execution",
134 [ESR_EC_VECTOR_CATCH] = "A32: Vector Catch Exception"
135 };
136
137 const char *
138 eclass_trapname(uint32_t eclass)
139 {
140 static char trapnamebuf[sizeof("Unknown trap 0x????????")];
141
142 if (eclass >= __arraycount(trap_names) || trap_names[eclass] == NULL) {
143 snprintf(trapnamebuf, sizeof(trapnamebuf),
144 "Unknown trap %#02x", eclass);
145 return trapnamebuf;
146 }
147 return trap_names[eclass];
148 }
149
150 void
151 userret(struct lwp *l)
152 {
153 mi_userret(l);
154 }
155
156 void
157 trap_doast(struct trapframe *tf)
158 {
159 struct lwp * const l = curlwp;
160
161 /*
162 * allow to have a chance of context switch just prior to user
163 * exception return.
164 */
165 #ifdef __HAVE_PREEMPTION
166 kpreempt_disable();
167 #endif
168 struct cpu_info * const ci = curcpu();
169
170 ci->ci_data.cpu_ntrap++;
171
172 KDASSERT(ci->ci_cpl == IPL_NONE);
173 #ifdef __HAVE_PREEMPTION
174 kpreempt_enable();
175 #endif
176
177 if (l->l_pflag & LP_OWEUPC) {
178 l->l_pflag &= ~LP_OWEUPC;
179 ADDUPROF(l);
180 }
181
182 userret(l);
183 }
184
185 void
186 trap_el1h_sync(struct trapframe *tf)
187 {
188 const uint32_t esr = tf->tf_esr;
189 const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
190
191 /* re-enable traps and interrupts */
192 if (!(tf->tf_spsr & SPSR_I))
193 daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
194 else
195 daif_enable(DAIF_D|DAIF_A);
196
197 #ifdef KDTRACE_HOOKS
198 if (dtrace_trap_func != NULL && (*dtrace_trap_func)(tf, eclass))
199 return;
200 #endif
201
202 switch (eclass) {
203 case ESR_EC_INSN_ABT_EL1:
204 case ESR_EC_DATA_ABT_EL1:
205 data_abort_handler(tf, eclass);
206 break;
207
208 case ESR_EC_BKPT_INSN_A64:
209 #ifdef KDTRACE_HOOKS
210 if (__SHIFTOUT(esr, ESR_ISS) == 0x40d &&
211 dtrace_invop_jump_addr != 0) {
212 (*dtrace_invop_jump_addr)(tf);
213 break;
214 }
215 /* FALLTHROUGH */
216 #endif
217 case ESR_EC_BRKPNT_EL1:
218 case ESR_EC_SW_STEP_EL1:
219 case ESR_EC_WTCHPNT_EL1:
220 #ifdef DDB
221 if (eclass == ESR_EC_BRKPNT_EL1)
222 kdb_trap(DB_TRAP_BREAKPOINT, tf);
223 else if (eclass == ESR_EC_BKPT_INSN_A64)
224 kdb_trap(DB_TRAP_BKPT_INSN, tf);
225 else if (eclass == ESR_EC_WTCHPNT_EL1)
226 kdb_trap(DB_TRAP_WATCHPOINT, tf);
227 else if (eclass == ESR_EC_SW_STEP_EL1)
228 kdb_trap(DB_TRAP_SW_STEP, tf);
229 else
230 kdb_trap(DB_TRAP_UNKNOWN, tf);
231 #else
232 panic("No debugger in kernel");
233 #endif
234 break;
235
236 case ESR_EC_FP_ACCESS:
237 case ESR_EC_FP_TRAP_A64:
238 case ESR_EC_PC_ALIGNMENT:
239 case ESR_EC_SP_ALIGNMENT:
240 case ESR_EC_ILL_STATE:
241 case ESR_EC_BTE_A64:
242 default:
243 panic("Trap: fatal %s: pc=%016" PRIx64 " sp=%016" PRIx64
244 " esr=%08x", eclass_trapname(eclass), tf->tf_pc, tf->tf_sp,
245 esr);
246 break;
247 }
248 }
249
250 void
251 trap_el0_sync(struct trapframe *tf)
252 {
253 struct lwp * const l = curlwp;
254 const uint32_t esr = tf->tf_esr;
255 const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
256
257 /* disable trace */
258 reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
259 /* enable traps and interrupts */
260 daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
261
262 switch (eclass) {
263 case ESR_EC_INSN_ABT_EL0:
264 case ESR_EC_DATA_ABT_EL0:
265 data_abort_handler(tf, eclass);
266 userret(l);
267 break;
268
269 case ESR_EC_SVC_A64:
270 (*l->l_proc->p_md.md_syscall)(tf);
271 break;
272 case ESR_EC_FP_ACCESS:
273 fpu_load(l);
274 userret(l);
275 break;
276 case ESR_EC_FP_TRAP_A64:
277 do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */
278 userret(l);
279 break;
280
281 case ESR_EC_PC_ALIGNMENT:
282 do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr);
283 userret(l);
284 break;
285 case ESR_EC_SP_ALIGNMENT:
286 do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_sp, esr);
287 userret(l);
288 break;
289
290 case ESR_EC_BKPT_INSN_A64:
291 case ESR_EC_BRKPNT_EL0:
292 case ESR_EC_WTCHPNT_EL0:
293 do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr);
294 userret(l);
295 break;
296 case ESR_EC_SW_STEP_EL0:
297 /* disable trace, and send trace trap */
298 tf->tf_spsr &= ~SPSR_SS;
299 do_trapsignal(l, SIGTRAP, TRAP_TRACE, (void *)tf->tf_pc, esr);
300 userret(l);
301 break;
302
303 default:
304 case ESR_EC_UNKNOWN:
305 #ifdef DDB
306 if (sigill_debug) {
307 /* show illegal instruction */
308 printf("TRAP: pid %d (%s), uid %d: %s:"
309 " esr=0x%lx: pc=0x%lx: %s\n",
310 curlwp->l_proc->p_pid, curlwp->l_proc->p_comm,
311 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1,
312 eclass_trapname(eclass), tf->tf_esr, tf->tf_pc,
313 strdisasm(tf->tf_pc));
314 }
315 #endif
316 /* illegal or not implemented instruction */
317 do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr);
318 userret(l);
319 break;
320 }
321 }
322
323 void
324 interrupt(struct trapframe *tf)
325 {
326 struct cpu_info * const ci = curcpu();
327
328 #ifdef STACKCHECKS
329 struct lwp *l = curlwp;
330 void *sp = (void *)reg_sp_read();
331 if (l->l_addr >= sp) {
332 panic("lwp/interrupt stack overflow detected."
333 " lwp=%p, sp=%p, l_addr=%p", l, sp, l->l_addr);
334 }
335 #endif
336
337 /* disable trace */
338 reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
339
340 /* enable traps */
341 daif_enable(DAIF_D|DAIF_A);
342
343 ci->ci_intr_depth++;
344 ARM_IRQ_HANDLER(tf);
345 ci->ci_intr_depth--;
346
347 cpu_dosoftints();
348 }
349
350 #ifdef COMPAT_NETBSD32
351
352 /*
353 * 32-bit length Thumb instruction. See ARMv7 DDI0406A A6.3.
354 */
355 #define THUMB_32BIT(hi) (((hi) & 0xe000) == 0xe000 && ((hi) & 0x1800))
356
357 static int
358 fetch_arm_insn(struct trapframe *tf, uint32_t *insn)
359 {
360
361 /* THUMB? */
362 if (tf->tf_spsr & SPSR_A32_T) {
363 uint16_t *pc = (uint16_t *)(tf->tf_pc & ~1UL); /* XXX */
364 uint16_t hi, lo;
365
366 if (ufetch_16(pc, &hi))
367 return -1;
368
369 if (!THUMB_32BIT(hi)) {
370 /* 16-bit Thumb instruction */
371 *insn = hi;
372 return 2;
373 }
374
375 /* 32-bit Thumb instruction */
376 if (ufetch_16(pc + 1, &lo))
377 return -1;
378
379 *insn = ((uint32_t)hi << 16) | lo;
380 return 4;
381 }
382
383 if (ufetch_32((uint32_t *)tf->tf_pc, insn))
384 return -1;
385
386 return 4;
387 }
388
389 enum emul_arm_result {
390 EMUL_ARM_SUCCESS = 0,
391 EMUL_ARM_UNKNOWN,
392 EMUL_ARM_FAULT,
393 };
394
395 static enum emul_arm_result
396 emul_arm_insn(struct trapframe *tf)
397 {
398 uint32_t insn;
399 int insn_size;
400
401 insn_size = fetch_arm_insn(tf, &insn);
402
403 switch (insn_size) {
404 case 2:
405 /* T32-16bit instruction */
406
407 /* XXX: some T32 IT instruction deprecated should be emulated */
408 break;
409 case 4:
410 /* T32-32bit instruction, or A32 instruction */
411
412 /*
413 * Emulate ARMv6 instructions with cache operations
414 * register (c7), that can be used in user mode.
415 */
416 switch (insn & 0x0fff0fff) {
417 case 0x0e070f95:
418 /*
419 * mcr p15, 0, <Rd>, c7, c5, 4
420 * (flush prefetch buffer)
421 */
422 __asm __volatile("isb sy" ::: "memory");
423 goto emulated;
424 case 0x0e070f9a:
425 /*
426 * mcr p15, 0, <Rd>, c7, c10, 4
427 * (data synchronization barrier)
428 */
429 __asm __volatile("dsb sy" ::: "memory");
430 goto emulated;
431 case 0x0e070fba:
432 /*
433 * mcr p15, 0, <Rd>, c7, c10, 5
434 * (data memory barrier)
435 */
436 __asm __volatile("dmb sy" ::: "memory");
437 goto emulated;
438 default:
439 break;
440 }
441 break;
442 default:
443 return EMUL_ARM_FAULT;
444 }
445
446 /* unknown, or unsupported instruction */
447 return EMUL_ARM_UNKNOWN;
448
449 emulated:
450 tf->tf_pc += insn_size;
451 return EMUL_ARM_SUCCESS;
452 }
453 #endif /* COMPAT_NETBSD32 */
454
455 void
456 trap_el0_32sync(struct trapframe *tf)
457 {
458 struct lwp * const l = curlwp;
459 const uint32_t esr = tf->tf_esr;
460 const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
461
462 /* disable trace */
463 reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
464 /* enable traps and interrupts */
465 daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
466
467 switch (eclass) {
468 #ifdef COMPAT_NETBSD32
469 case ESR_EC_INSN_ABT_EL0:
470 case ESR_EC_DATA_ABT_EL0:
471 data_abort_handler(tf, eclass);
472 userret(l);
473 break;
474
475 case ESR_EC_SVC_A32:
476 (*l->l_proc->p_md.md_syscall)(tf);
477 break;
478
479 case ESR_EC_FP_ACCESS:
480 fpu_load(l);
481 userret(l);
482 break;
483
484 case ESR_EC_FP_TRAP_A32:
485 do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */
486 userret(l);
487 break;
488
489 case ESR_EC_PC_ALIGNMENT:
490 do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr);
491 userret(l);
492 break;
493
494 case ESR_EC_SP_ALIGNMENT:
495 do_trapsignal(l, SIGBUS, BUS_ADRALN,
496 (void *)tf->tf_reg[13], esr); /* sp is r13 on AArch32 */
497 userret(l);
498 break;
499
500 case ESR_EC_BKPT_INSN_A32:
501 do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr);
502 userret(l);
503 break;
504
505 case ESR_EC_UNKNOWN:
506 switch (emul_arm_insn(tf)) {
507 case EMUL_ARM_SUCCESS:
508 break;
509 case EMUL_ARM_UNKNOWN:
510 goto unknown;
511 case EMUL_ARM_FAULT:
512 do_trapsignal(l, SIGSEGV, SEGV_MAPERR,
513 (void *)tf->tf_pc, esr);
514 break;
515 }
516 userret(l);
517 break;
518
519 case ESR_EC_CP15_RT:
520 case ESR_EC_CP15_RRT:
521 case ESR_EC_CP14_RT:
522 case ESR_EC_CP14_DT:
523 case ESR_EC_CP14_RRT:
524 unknown:
525 #endif /* COMPAT_NETBSD32 */
526 default:
527 #ifdef DDB
528 if (sigill_debug) {
529 /* show illegal instruction */
530 printf("TRAP: pid %d (%s), uid %d: %s:"
531 " esr=0x%lx: pc=0x%lx: %s\n",
532 curlwp->l_proc->p_pid, curlwp->l_proc->p_comm,
533 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1,
534 eclass_trapname(eclass), tf->tf_esr, tf->tf_pc,
535 strdisasm_aarch32(tf->tf_pc));
536 }
537 #endif
538 /* illegal or not implemented instruction */
539 do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr);
540 userret(l);
541 break;
542 }
543 }
544
545 #define bad_trap_panic(trapfunc) \
546 void \
547 trapfunc(struct trapframe *tf) \
548 { \
549 panic("%s", __func__); \
550 }
551 bad_trap_panic(trap_el1t_sync)
552 bad_trap_panic(trap_el1t_irq)
553 bad_trap_panic(trap_el1t_fiq)
554 bad_trap_panic(trap_el1t_error)
555 bad_trap_panic(trap_el1h_fiq)
556 bad_trap_panic(trap_el1h_error)
557 bad_trap_panic(trap_el0_fiq)
558 bad_trap_panic(trap_el0_error)
559 bad_trap_panic(trap_el0_32fiq)
560 bad_trap_panic(trap_el0_32error)
561
562 void
563 cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb, int val)
564 {
565 tf->tf_reg[19] = fb->fb_reg[FB_X19];
566 tf->tf_reg[20] = fb->fb_reg[FB_X20];
567 tf->tf_reg[21] = fb->fb_reg[FB_X21];
568 tf->tf_reg[22] = fb->fb_reg[FB_X22];
569 tf->tf_reg[23] = fb->fb_reg[FB_X23];
570 tf->tf_reg[24] = fb->fb_reg[FB_X24];
571 tf->tf_reg[25] = fb->fb_reg[FB_X25];
572 tf->tf_reg[26] = fb->fb_reg[FB_X26];
573 tf->tf_reg[27] = fb->fb_reg[FB_X27];
574 tf->tf_reg[28] = fb->fb_reg[FB_X28];
575 tf->tf_reg[29] = fb->fb_reg[FB_X29];
576 tf->tf_sp = fb->fb_reg[FB_SP];
577 tf->tf_pc = fb->fb_reg[FB_LR];
578 tf->tf_reg[0] = val;
579 }
580
581 #ifdef TRAP_SIGDEBUG
582 static void
583 frame_dump(const struct trapframe *tf)
584 {
585 const struct reg *r = &tf->tf_regs;
586
587 printf("trapframe %p\n", tf);
588 for (size_t i = 0; i < __arraycount(r->r_reg); i++) {
589 printf(" r%.2zu %#018" PRIx64 "%c", i, r->r_reg[i],
590 " \n"[i && (i & 1) == 0]);
591 }
592
593 printf("\n");
594 printf(" sp %#018" PRIx64 " pc %#018" PRIx64 "\n",
595 r->r_sp, r->r_pc);
596 printf(" spsr %#018" PRIx64 " tpidr %#018" PRIx64 "\n",
597 r->r_spsr, r->r_tpidr);
598 printf(" esr %#018" PRIx64 " far %#018" PRIx64 "\n",
599 tf->tf_esr, tf->tf_far);
600
601 printf("\n");
602 hexdump(printf, "Stack dump", tf, 256);
603 }
604
605 static void
606 sigdebug(const struct trapframe *tf, const ksiginfo_t *ksi)
607 {
608 struct lwp *l = curlwp;
609 struct proc *p = l->l_proc;
610 const uint32_t eclass = __SHIFTOUT(ksi->ksi_trap, ESR_EC);
611
612 printf("pid %d.%d (%s): signal %d (trap %#x) "
613 "@pc %#" PRIx64 ", addr %p, error=%s\n",
614 p->p_pid, l->l_lid, p->p_comm, ksi->ksi_signo, ksi->ksi_trap,
615 tf->tf_regs.r_pc, ksi->ksi_addr, eclass_trapname(eclass));
616 frame_dump(tf);
617 }
618 #endif
619
620 void do_trapsignal1(
621 #ifdef TRAP_SIGDEBUG
622 const char *func,
623 size_t line,
624 struct trapframe *tf,
625 #endif
626 struct lwp *l, int signo, int code, void *addr, int trap)
627 {
628 ksiginfo_t ksi;
629
630 KSI_INIT_TRAP(&ksi);
631 ksi.ksi_signo = signo;
632 ksi.ksi_code = code;
633 ksi.ksi_addr = addr;
634 ksi.ksi_trap = trap;
635 #ifdef TRAP_SIGDEBUG
636 printf("%s, %zu: ", func, line);
637 sigdebug(tf, &ksi);
638 #endif
639 (*l->l_proc->p_emul->e_trapsignal)(l, &ksi);
640 }
641
642 bool
643 cpu_intr_p(void)
644 {
645 uint64_t ncsw;
646 int idepth;
647 lwp_t *l;
648
649 #ifdef __HAVE_PIC_FAST_SOFTINTS
650 /* XXX Copied from cpu.h. Looks incomplete - needs fixing. */
651 if (ci->ci_cpl < IPL_VM)
652 return false;
653 #endif
654
655 l = curlwp;
656 if (__predict_false(l->l_cpu == NULL)) {
657 KASSERT(l == &lwp0);
658 return false;
659 }
660 do {
661 ncsw = l->l_ncsw;
662 __insn_barrier();
663 idepth = l->l_cpu->ci_intr_depth;
664 __insn_barrier();
665 } while (__predict_false(ncsw != l->l_ncsw));
666
667 return idepth > 0;
668 }
669