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