Home | History | Annotate | Line # | Download | only in aarch64
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