Home | History | Annotate | Line # | Download | only in aarch64
      1 /* $NetBSD: trap.c,v 1.53 2025/07/21 08:46:17 skrll Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2014, 2023 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.53 2025/07/21 08:46:17 skrll 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/types.h>
     42 
     43 #include <sys/atomic.h>
     44 #include <sys/cpu.h>
     45 #include <sys/evcnt.h>
     46 #include <sys/kauth.h>
     47 #ifdef KGDB
     48 #include <sys/kgdb.h>
     49 #endif
     50 #include <sys/proc.h>
     51 #include <sys/siginfo.h>
     52 #include <sys/signal.h>
     53 #include <sys/signalvar.h>
     54 #include <sys/systm.h>
     55 #include <sys/xcall.h>
     56 
     57 #ifdef ARM_INTR_IMPL
     58 #include ARM_INTR_IMPL
     59 #else
     60 #error ARM_INTR_IMPL not defined
     61 #endif
     62 
     63 #ifndef ARM_IRQ_HANDLER
     64 #error ARM_IRQ_HANDLER not defined
     65 #endif
     66 
     67 #include <arm/cpufunc.h>
     68 
     69 #include <aarch64/userret.h>
     70 #include <aarch64/frame.h>
     71 #include <aarch64/machdep.h>
     72 #include <aarch64/armreg.h>
     73 #include <aarch64/locore.h>
     74 
     75 #ifdef KGDB
     76 #include <machine/db_machdep.h>
     77 #endif
     78 #ifdef DDB
     79 #include <ddb/db_output.h>
     80 #include <machine/db_machdep.h>
     81 #endif
     82 
     83 #ifdef KDTRACE_HOOKS
     84 #include <sys/dtrace_bsd.h>
     85 #endif
     86 
     87 #ifdef DDB
     88 int sigill_debug = 0;
     89 #endif
     90 
     91 #ifdef KDTRACE_HOOKS
     92 dtrace_doubletrap_func_t	dtrace_doubletrap_func = NULL;
     93 dtrace_trap_func_t		dtrace_trap_func = NULL;
     94 int (*dtrace_invop_jump_addr)(struct trapframe *);
     95 #endif
     96 
     97 enum emul_arm_result {
     98 	EMUL_ARM_SUCCESS = 0,
     99 	EMUL_ARM_UNKNOWN,
    100 	EMUL_ARM_FAULT,
    101 };
    102 
    103 const char * const trap_names[] = {
    104 	[ESR_EC_UNKNOWN]	= "Unknown Reason (Illegal Instruction)",
    105 	[ESR_EC_SERROR]		= "SError Interrupt",
    106 	[ESR_EC_WFX]		= "WFI or WFE instruction execution",
    107 	[ESR_EC_ILL_STATE]	= "Illegal Execution State",
    108 
    109 	[ESR_EC_BTE_A64]	= "Branch Target Exception",
    110 
    111 	[ESR_EC_SYS_REG]	= "MSR/MRS/SYS instruction",
    112 	[ESR_EC_SVC_A64]	= "SVC Instruction Execution",
    113 	[ESR_EC_HVC_A64]	= "HVC Instruction Execution",
    114 	[ESR_EC_SMC_A64]	= "SMC Instruction Execution",
    115 
    116 	[ESR_EC_INSN_ABT_EL0]	= "Instruction Abort (EL0)",
    117 	[ESR_EC_INSN_ABT_EL1]	= "Instruction Abort (EL1)",
    118 	[ESR_EC_DATA_ABT_EL0]	= "Data Abort (EL0)",
    119 	[ESR_EC_DATA_ABT_EL1]	= "Data Abort (EL1)",
    120 
    121 	[ESR_EC_PC_ALIGNMENT]	= "Misaligned PC",
    122 	[ESR_EC_SP_ALIGNMENT]	= "Misaligned SP",
    123 
    124 	[ESR_EC_FP_ACCESS]	= "Access to SIMD/FP Registers",
    125 	[ESR_EC_FP_TRAP_A64]	= "FP Exception",
    126 
    127 	[ESR_EC_BRKPNT_EL0]	= "Breakpoint Exception (EL0)",
    128 	[ESR_EC_BRKPNT_EL1]	= "Breakpoint Exception (EL1)",
    129 	[ESR_EC_SW_STEP_EL0]	= "Software Step (EL0)",
    130 	[ESR_EC_SW_STEP_EL1]	= "Software Step (EL1)",
    131 	[ESR_EC_WTCHPNT_EL0]	= "Watchpoint (EL0)",
    132 	[ESR_EC_WTCHPNT_EL1]	= "Watchpoint (EL1)",
    133 	[ESR_EC_BKPT_INSN_A64]	= "BKPT Instruction Execution",
    134 
    135 	[ESR_EC_CP15_RT]	= "A32: MCR/MRC access to CP15",
    136 	[ESR_EC_CP15_RRT]	= "A32: MCRR/MRRC access to CP15",
    137 	[ESR_EC_CP14_RT]	= "A32: MCR/MRC access to CP14",
    138 	[ESR_EC_CP14_DT]	= "A32: LDC/STC access to CP14",
    139 	[ESR_EC_CP14_RRT]	= "A32: MRRC access to CP14",
    140 	[ESR_EC_SVC_A32]	= "A32: SVC Instruction Execution",
    141 	[ESR_EC_HVC_A32]	= "A32: HVC Instruction Execution",
    142 	[ESR_EC_SMC_A32]	= "A32: SMC Instruction Execution",
    143 	[ESR_EC_FPID]		= "A32: MCR/MRC access to CP10",
    144 	[ESR_EC_FP_TRAP_A32]	= "A32: FP Exception",
    145 	[ESR_EC_BKPT_INSN_A32]	= "A32: BKPT Instruction Execution",
    146 	[ESR_EC_VECTOR_CATCH]	= "A32: Vector Catch Exception"
    147 };
    148 
    149 const char *
    150 eclass_trapname(uint32_t eclass)
    151 {
    152 	static char trapnamebuf[sizeof("Unknown trap 0x????????")];
    153 
    154 	if (eclass >= __arraycount(trap_names) || trap_names[eclass] == NULL) {
    155 		snprintf(trapnamebuf, sizeof(trapnamebuf),
    156 		    "Unknown trap %#02x", eclass);
    157 		return trapnamebuf;
    158 	}
    159 	return trap_names[eclass];
    160 }
    161 
    162 void
    163 userret(struct lwp *l)
    164 {
    165 	mi_userret(l);
    166 }
    167 
    168 void
    169 trap_doast(struct trapframe *tf)
    170 {
    171 	struct lwp * const l = curlwp;
    172 
    173 	/*
    174 	 * allow to have a chance of context switch just prior to user
    175 	 * exception return.
    176 	 */
    177 #ifdef __HAVE_PREEMPTION
    178 	kpreempt_disable();
    179 #endif
    180 	struct cpu_info * const ci = curcpu();
    181 
    182 	ci->ci_data.cpu_ntrap++;
    183 
    184 	KDASSERT(ci->ci_cpl == IPL_NONE);
    185 #ifdef __HAVE_PREEMPTION
    186 	kpreempt_enable();
    187 #endif
    188 
    189 	if (l->l_pflag & LP_OWEUPC) {
    190 		l->l_pflag &= ~LP_OWEUPC;
    191 		ADDUPROF(l);
    192 	}
    193 
    194 	userret(l);
    195 }
    196 
    197 void
    198 trap_el1h_sync(struct trapframe *tf)
    199 {
    200 	const uint32_t esr = tf->tf_esr;
    201 	const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
    202 
    203 	/* re-enable traps and interrupts */
    204 	if (!(tf->tf_spsr & SPSR_I))
    205 		daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
    206 	else
    207 		daif_enable(DAIF_D|DAIF_A);
    208 
    209 #ifdef KDTRACE_HOOKS
    210 	if (dtrace_trap_func != NULL && (*dtrace_trap_func)(tf, eclass))
    211 		return;
    212 #endif
    213 
    214 	switch (eclass) {
    215 	case ESR_EC_INSN_ABT_EL1:
    216 	case ESR_EC_DATA_ABT_EL1:
    217 		data_abort_handler(tf, eclass);
    218 		break;
    219 
    220 	case ESR_EC_BKPT_INSN_A64:
    221 #ifdef KDTRACE_HOOKS
    222 		if (__SHIFTOUT(esr, ESR_ISS) == 0x40d &&
    223 		    dtrace_invop_jump_addr != 0) {
    224 			(*dtrace_invop_jump_addr)(tf);
    225 			break;
    226 		}
    227 		/* FALLTHROUGH */
    228 #endif
    229 	case ESR_EC_BRKPNT_EL1:
    230 	case ESR_EC_SW_STEP_EL1:
    231 	case ESR_EC_WTCHPNT_EL1:
    232 #ifdef DDB
    233 		if (eclass == ESR_EC_BRKPNT_EL1)
    234 			kdb_trap(DB_TRAP_BREAKPOINT, tf);
    235 		else if (eclass == ESR_EC_BKPT_INSN_A64)
    236 			kdb_trap(DB_TRAP_BKPT_INSN, tf);
    237 		else if (eclass == ESR_EC_WTCHPNT_EL1)
    238 			kdb_trap(DB_TRAP_WATCHPOINT, tf);
    239 		else if (eclass == ESR_EC_SW_STEP_EL1)
    240 			kdb_trap(DB_TRAP_SW_STEP, tf);
    241 		else
    242 			kdb_trap(DB_TRAP_UNKNOWN, tf);
    243 #else
    244 		panic("No debugger in kernel");
    245 #endif
    246 		break;
    247 
    248 	case ESR_EC_FP_ACCESS:
    249 		if ((curlwp->l_flag & (LW_SYSTEM|LW_SYSTEM_FPU)) ==
    250 		    (LW_SYSTEM|LW_SYSTEM_FPU)) {
    251 			fpu_load(curlwp);
    252 			break;
    253 		}
    254 		/*FALLTHROUGH*/
    255 	case ESR_EC_FP_TRAP_A64:
    256 	case ESR_EC_PC_ALIGNMENT:
    257 	case ESR_EC_SP_ALIGNMENT:
    258 	case ESR_EC_ILL_STATE:
    259 	case ESR_EC_BTE_A64:
    260 	default:
    261 		panic("Trap: fatal %s: pc=%016" PRIx64 " sp=%016" PRIx64
    262 		    " esr=%08x", eclass_trapname(eclass), tf->tf_pc, tf->tf_sp,
    263 		    esr);
    264 		break;
    265 	}
    266 }
    267 
    268 /*
    269  * There are some systems with different cache line sizes for each cpu.
    270  * Userland programs can be preempted between CPUs at any time, so in such
    271  * a system, the minimum cache line size must be visible to userland.
    272  */
    273 #define CTR_EL0_USR_MASK	\
    274 	(CTR_EL0_DIC | CTR_EL0_IDC | CTR_EL0_DMIN_LINE | CTR_EL0_IMIN_LINE)
    275 uint64_t ctr_el0_usr __read_mostly;
    276 
    277 static void
    278 configure_cpu_traps0(void *arg1, void *arg2)
    279 {
    280 	struct cpu_info * const ci = curcpu();
    281 	uint64_t sctlr;
    282 	uint64_t ctr_el0_raw = reg_ctr_el0_read();
    283 
    284 #ifdef DEBUG_FORCE_TRAP_CTR_EL0
    285 	goto need_ctr_trap;
    286 #endif
    287 
    288 	if ((__SHIFTOUT(ctr_el0_raw, CTR_EL0_DMIN_LINE) >
    289 	     __SHIFTOUT(ctr_el0_usr, CTR_EL0_DMIN_LINE)) ||
    290 	    (__SHIFTOUT(ctr_el0_raw, CTR_EL0_IMIN_LINE) >
    291 	     __SHIFTOUT(ctr_el0_usr, CTR_EL0_IMIN_LINE)))
    292 		goto need_ctr_trap;
    293 
    294 	if ((__SHIFTOUT(ctr_el0_raw, CTR_EL0_DIC) == 1 &&
    295 	     __SHIFTOUT(ctr_el0_usr, CTR_EL0_DIC) == 0) ||
    296 	    (__SHIFTOUT(ctr_el0_raw, CTR_EL0_IDC) == 1 &&
    297 	     __SHIFTOUT(ctr_el0_usr, CTR_EL0_IDC) == 0))
    298 		goto need_ctr_trap;
    299 
    300 #if 0 /* XXX: To do or not to do */
    301 	/*
    302 	 * IDC==0, but (LoC==0 || LoUIS==LoUU==0)?
    303 	 * Would it be better to show IDC=1 to userland?
    304 	 */
    305 	if (__SHIFTOUT(ctr_el0_raw, CTR_EL0_IDC) == 0 &&
    306 	    __SHIFTOUT(ctr_el0_usr, CTR_EL0_IDC) == 1)
    307 		goto need_ctr_trap;
    308 #endif
    309 
    310 	return;
    311 
    312  need_ctr_trap:
    313 	evcnt_attach_dynamic(&ci->ci_uct_trap, EVCNT_TYPE_MISC, NULL,
    314 	    ci->ci_cpuname, "ctr_el0 trap");
    315 
    316 	/* trap CTR_EL0 access from EL0 on this cpu */
    317 	sctlr = reg_sctlr_el1_read();
    318 	sctlr &= ~SCTLR_UCT;
    319 	reg_sctlr_el1_write(sctlr);
    320 }
    321 
    322 void
    323 configure_cpu_traps(void)
    324 {
    325 	CPU_INFO_ITERATOR cii;
    326 	struct cpu_info *ci;
    327 	uint64_t where;
    328 
    329 	/* remember minimum cache line size out of all CPUs */
    330 	for (CPU_INFO_FOREACH(cii, ci)) {
    331 		uint64_t ctr_el0_cpu = ci->ci_id.ac_ctr;
    332 		uint64_t clidr = ci->ci_id.ac_clidr;
    333 
    334 		if (__SHIFTOUT(clidr, CLIDR_LOC) == 0 ||
    335 		    (__SHIFTOUT(clidr, CLIDR_LOUIS) == 0 &&
    336 		     __SHIFTOUT(clidr, CLIDR_LOUU) == 0)) {
    337 			/* this means the same as IDC=1 */
    338 			ctr_el0_cpu |= CTR_EL0_IDC;
    339 		}
    340 
    341 		/*
    342 		 * if DIC==1, there is no need to icache sync. however,
    343 		 * to calculate the minimum cacheline, in this case
    344 		 * ICacheLine is treated as the maximum.
    345 		 */
    346 		if (__SHIFTOUT(ctr_el0_cpu, CTR_EL0_DIC) == 1)
    347 			ctr_el0_cpu |= CTR_EL0_IMIN_LINE;
    348 
    349 		/* Neoverse N1 erratum 1542419 */
    350 		if (CPU_ID_NEOVERSEN1_P(ci->ci_id.ac_midr) &&
    351 		    __SHIFTOUT(ctr_el0_cpu, CTR_EL0_DIC) == 1)
    352 			ctr_el0_cpu &= ~CTR_EL0_DIC;
    353 
    354 		if (cii == 0) {
    355 			ctr_el0_usr = ctr_el0_cpu;
    356 			continue;
    357 		}
    358 
    359 		/* keep minimum cache line size, and worst DIC/IDC */
    360 		ctr_el0_usr &= (ctr_el0_cpu & CTR_EL0_DIC) | ~CTR_EL0_DIC;
    361 		ctr_el0_usr &= (ctr_el0_cpu & CTR_EL0_IDC) | ~CTR_EL0_IDC;
    362 		if (__SHIFTOUT(ctr_el0_cpu, CTR_EL0_DMIN_LINE) <
    363 		    __SHIFTOUT(ctr_el0_usr, CTR_EL0_DMIN_LINE)) {
    364 			ctr_el0_usr &= ~CTR_EL0_DMIN_LINE;
    365 			ctr_el0_usr |= ctr_el0_cpu & CTR_EL0_DMIN_LINE;
    366 		}
    367 		if ((ctr_el0_cpu & CTR_EL0_DIC) == 0 &&
    368 		    (__SHIFTOUT(ctr_el0_cpu, CTR_EL0_IMIN_LINE) <
    369 		    __SHIFTOUT(ctr_el0_usr, CTR_EL0_IMIN_LINE))) {
    370 			ctr_el0_usr &= ~CTR_EL0_IMIN_LINE;
    371 			ctr_el0_usr |= ctr_el0_cpu & CTR_EL0_IMIN_LINE;
    372 		}
    373 	}
    374 
    375 	where = xc_broadcast(0, configure_cpu_traps0, NULL, NULL);
    376 	xc_wait(where);
    377 }
    378 
    379 static enum emul_arm_result
    380 emul_aarch64_insn(struct trapframe *tf)
    381 {
    382 	uint32_t insn;
    383 
    384 	if (ufetch_32((uint32_t *)tf->tf_pc, &insn)) {
    385 		tf->tf_far = reg_far_el1_read();
    386 		return EMUL_ARM_FAULT;
    387 	}
    388 
    389 	LE32TOH(insn);
    390 	if ((insn & 0xffffffe0) == 0xd53b0020) {
    391 		/* mrs x?,ctr_el0 */
    392 		unsigned int Xt = insn & 31;
    393 		if (Xt != 31) {	/* !xzr */
    394 			uint64_t ctr_el0 = reg_ctr_el0_read();
    395 			ctr_el0 &= ~CTR_EL0_USR_MASK;
    396 			ctr_el0 |= (ctr_el0_usr & CTR_EL0_USR_MASK);
    397 			tf->tf_reg[Xt] = ctr_el0;
    398 		}
    399 		curcpu()->ci_uct_trap.ev_count++;
    400 
    401 	} else {
    402 		return EMUL_ARM_UNKNOWN;
    403 	}
    404 
    405 	tf->tf_pc += 4;
    406 	return EMUL_ARM_SUCCESS;
    407 }
    408 
    409 void
    410 trap_el0_sync(struct trapframe *tf)
    411 {
    412 	struct lwp * const l = curlwp;
    413 	const uint32_t esr = tf->tf_esr;
    414 	const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
    415 
    416 #ifdef DDB
    417 	/* disable trace, and enable hardware breakpoint/watchpoint */
    418 	reg_mdscr_el1_write(
    419 	    (reg_mdscr_el1_read() & ~MDSCR_SS) | MDSCR_KDE);
    420 #else
    421 	/* disable trace */
    422 	reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
    423 #endif
    424 	/* enable traps and interrupts */
    425 	daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
    426 
    427 	switch (eclass) {
    428 	case ESR_EC_INSN_ABT_EL0:
    429 	case ESR_EC_DATA_ABT_EL0:
    430 		data_abort_handler(tf, eclass);
    431 		userret(l);
    432 		break;
    433 
    434 	case ESR_EC_SVC_A64:
    435 		(*l->l_proc->p_md.md_syscall)(tf);
    436 		break;
    437 	case ESR_EC_FP_ACCESS:
    438 		fpu_load(l);
    439 		userret(l);
    440 		break;
    441 	case ESR_EC_FP_TRAP_A64:
    442 		do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */
    443 		userret(l);
    444 		break;
    445 
    446 	case ESR_EC_PC_ALIGNMENT:
    447 		do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr);
    448 		userret(l);
    449 		break;
    450 	case ESR_EC_SP_ALIGNMENT:
    451 		do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_sp, esr);
    452 		userret(l);
    453 		break;
    454 
    455 	case ESR_EC_BKPT_INSN_A64:
    456 	case ESR_EC_BRKPNT_EL0:
    457 	case ESR_EC_WTCHPNT_EL0:
    458 		do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr);
    459 		userret(l);
    460 		break;
    461 	case ESR_EC_SW_STEP_EL0:
    462 		/* disable trace, and send trace trap */
    463 		tf->tf_spsr &= ~SPSR_SS;
    464 		do_trapsignal(l, SIGTRAP, TRAP_TRACE, (void *)tf->tf_pc, esr);
    465 		userret(l);
    466 		break;
    467 
    468 	case ESR_EC_SYS_REG:
    469 		switch (emul_aarch64_insn(tf)) {
    470 		case EMUL_ARM_SUCCESS:
    471 			break;
    472 		case EMUL_ARM_UNKNOWN:
    473 			goto unknown;
    474 		case EMUL_ARM_FAULT:
    475 			do_trapsignal(l, SIGSEGV, SEGV_MAPERR,
    476 			    (void *)tf->tf_far, esr);
    477 			break;
    478 		}
    479 		userret(l);
    480 		break;
    481 
    482 	default:
    483 	case ESR_EC_UNKNOWN:
    484  unknown:
    485 #ifdef DDB
    486 		if (sigill_debug) {
    487 			/* show illegal instruction */
    488 			printf("TRAP: pid %d (%s), uid %d: %s:"
    489 			    " esr=0x%lx: pc=0x%lx: %s\n",
    490 			    curlwp->l_proc->p_pid, curlwp->l_proc->p_comm,
    491 			    l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1,
    492 			    eclass_trapname(eclass), tf->tf_esr, tf->tf_pc,
    493 			    strdisasm(tf->tf_pc, tf->tf_spsr));
    494 		}
    495 #endif
    496 		/* illegal or not implemented instruction */
    497 		do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr);
    498 		userret(l);
    499 		break;
    500 	}
    501 }
    502 
    503 void
    504 cpu_irq(struct trapframe *tf)
    505 {
    506 	struct cpu_info * const ci = curcpu();
    507 
    508 #ifdef STACKCHECKS
    509 	struct lwp *l = curlwp;
    510 	void *sp = (void *)reg_sp_read();
    511 	if (l->l_addr >= sp) {
    512 		panic("lwp/interrupt stack overflow detected."
    513 		    " lwp=%p, sp=%p, l_addr=%p", l, sp, l->l_addr);
    514 	}
    515 #endif
    516 
    517 #ifdef DDB
    518 	/* disable trace, and enable hardware breakpoint/watchpoint */
    519 	reg_mdscr_el1_write(
    520 	    (reg_mdscr_el1_read() & ~MDSCR_SS) | MDSCR_KDE);
    521 #else
    522 	/* disable trace */
    523 	reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
    524 #endif
    525 
    526 	/*
    527 	 * Prevent preemption once we enable traps, until we have
    528 	 * finished running hard and soft interrupt handlers.  This
    529 	 * guarantees ci = curcpu() remains stable and we don't
    530 	 * accidentally try to run its pending soft interrupts on
    531 	 * another CPU.
    532 	 */
    533 	kpreempt_disable();
    534 
    535 	/* enable traps */
    536 	daif_enable(DAIF_D|DAIF_A);
    537 
    538 	/* run hard interrupt handlers */
    539 	ci->ci_intr_depth++;
    540 	ARM_IRQ_HANDLER(tf);
    541 	ci->ci_intr_depth--;
    542 
    543 	/* run soft interrupt handlers */
    544 	cpu_dosoftints();
    545 
    546 	/* all done, preempt as you please */
    547 	kpreempt_enable();
    548 }
    549 
    550 void
    551 cpu_fiq(struct trapframe *tf)
    552 {
    553 	struct cpu_info * const ci = curcpu();
    554 
    555 #ifdef STACKCHECKS
    556 	struct lwp *l = curlwp;
    557 	void *sp = (void *)reg_sp_read();
    558 	if (l->l_addr >= sp) {
    559 		panic("lwp/interrupt stack overflow detected."
    560 		    " lwp=%p, sp=%p, l_addr=%p", l, sp, l->l_addr);
    561 	}
    562 #endif
    563 
    564 	/* disable trace */
    565 	reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
    566 
    567 	/*
    568 	 * Prevent preemption once we enable traps, until we have
    569 	 * finished running hard and soft interrupt handlers.  This
    570 	 * guarantees ci = curcpu() remains stable and we don't
    571 	 * accidentally try to run its pending soft interrupts on
    572 	 * another CPU.
    573 	 */
    574 	kpreempt_disable();
    575 
    576 	/* enable traps */
    577 	daif_enable(DAIF_D|DAIF_A);
    578 
    579 	/* run hard interrupt handlers */
    580 	ci->ci_intr_depth++;
    581 	ARM_FIQ_HANDLER(tf);
    582 	ci->ci_intr_depth--;
    583 
    584 	/* run soft interrupt handlers */
    585 	cpu_dosoftints();
    586 
    587 	/* all done, preempt as you please */
    588 	kpreempt_enable();
    589 }
    590 
    591 #ifdef COMPAT_NETBSD32
    592 
    593 /*
    594  * 32-bit length Thumb instruction. See ARMv7 DDI0406A A6.3.
    595  */
    596 #define THUMB_32BIT(hi) (((hi) & 0xe000) == 0xe000 && ((hi) & 0x1800))
    597 
    598 int
    599 fetch_arm_insn(uint64_t pc, uint64_t spsr, uint32_t *insn)
    600 {
    601 
    602 	/*
    603 	 * Instructions are stored in little endian for BE8,
    604 	 * only a valid binary format for ILP32EB. Therefore,
    605 	 * we need byte-swapping before decoding on aarch64eb.
    606 	 */
    607 
    608 	/* THUMB? */
    609 	if (spsr & SPSR_A32_T) {
    610 		uint16_t *p = (uint16_t *)(pc & ~1UL); /* XXX */
    611 		uint16_t hi, lo;
    612 
    613 		if (ufetch_16(p, &hi))
    614 			return -1;
    615 		LE16TOH(hi);
    616 
    617 		if (!THUMB_32BIT(hi)) {
    618 			/* 16-bit Thumb instruction */
    619 			*insn = hi;
    620 			return 2;
    621 		}
    622 
    623 		/* 32-bit Thumb instruction */
    624 		if (ufetch_16(p + 1, &lo))
    625 			return -1;
    626 		LE16TOH(lo);
    627 
    628 		*insn = ((uint32_t)hi << 16) | lo;
    629 		return 4;
    630 	}
    631 
    632 	if (ufetch_32((uint32_t *)pc, insn))
    633 		return -1;
    634 	LE32TOH(*insn);
    635 
    636 	return 4;
    637 }
    638 
    639 static bool
    640 arm_cond_match(uint32_t insn, uint64_t spsr)
    641 {
    642 	bool invert = (insn >> 28) & 1;
    643 	bool match;
    644 
    645 	switch (insn >> 29) {
    646 	case 0:	/* EQ or NE */
    647 		match = spsr & SPSR_Z;
    648 		break;
    649 	case 1:	/* CS/HI or CC/LO */
    650 		match = spsr & SPSR_C;
    651 		break;
    652 	case 2:	/* MI or PL */
    653 		match = spsr & SPSR_N;
    654 		break;
    655 	case 3:	/* VS or VC */
    656 		match = spsr & SPSR_V;
    657 		break;
    658 	case 4:	/* HI or LS */
    659 		match = ((spsr & (SPSR_C | SPSR_Z)) == SPSR_C);
    660 		break;
    661 	case 5:	/* GE or LT */
    662 		match = (!(spsr & SPSR_N) == !(spsr & SPSR_V));
    663 		break;
    664 	case 6:	/* GT or LE */
    665 		match = !(spsr & SPSR_Z) &&
    666 		    (!(spsr & SPSR_N) == !(spsr & SPSR_V));
    667 		break;
    668 	case 7:	/* AL */
    669 		match = true;
    670 		break;
    671 	}
    672 	return (!match != !invert);
    673 }
    674 
    675 uint8_t atomic_swap_8(volatile uint8_t *, uint8_t);
    676 
    677 static int
    678 emul_arm_swp(uint32_t insn, struct trapframe *tf)
    679 {
    680 	struct faultbuf fb;
    681 	vaddr_t vaddr;
    682 	uint32_t val;
    683 	int Rn, Rd, Rm, error;
    684 
    685 	Rn = __SHIFTOUT(insn, 0x000f0000);
    686 	Rd = __SHIFTOUT(insn, 0x0000f000);
    687 	Rm = __SHIFTOUT(insn, 0x0000000f);
    688 
    689 	vaddr = tf->tf_reg[Rn] & 0xffffffff;
    690 	val = tf->tf_reg[Rm];
    691 
    692 	/* fault if insn is swp, and unaligned access */
    693 	if ((insn & 0x00400000) == 0 && (vaddr & 3) != 0) {
    694 		tf->tf_far = vaddr;
    695 		return EFAULT;
    696 	}
    697 
    698 	/* vaddr will always point to userspace, since it has only 32bit */
    699 	if ((error = cpu_set_onfault(&fb)) == 0) {
    700 		if (aarch64_pan_enabled)
    701 			reg_pan_write(0); /* disable PAN */
    702 		if (insn & 0x00400000) {
    703 			/* swpb */
    704 			val = atomic_swap_8((uint8_t *)vaddr, val);
    705 		} else {
    706 			/* swp */
    707 			val = atomic_swap_32((uint32_t *)vaddr, val);
    708 		}
    709 		cpu_unset_onfault();
    710 		tf->tf_reg[Rd] = val;
    711 	} else {
    712 		tf->tf_far = reg_far_el1_read();
    713 	}
    714 	if (aarch64_pan_enabled)
    715 		reg_pan_write(1); /* enable PAN */
    716 	return error;
    717 }
    718 
    719 static enum emul_arm_result
    720 emul_thumb_insn(struct trapframe *tf, uint32_t insn, int insn_size)
    721 {
    722 	/* T32-16bit or 32bit instructions */
    723 	switch (insn_size) {
    724 	case 2:
    725 		/* Breakpoint used by GDB */
    726 		if (insn == 0xdefe) {
    727 			do_trapsignal(curlwp, SIGTRAP, TRAP_BRKPT,
    728 			    (void *)tf->tf_pc, 0);
    729 			return EMUL_ARM_SUCCESS;
    730 		}
    731 		/* XXX: some T32 IT instruction deprecated should be emulated */
    732 		break;
    733 	case 4:
    734 		break;
    735 	default:
    736 		return EMUL_ARM_FAULT;
    737 	}
    738 	return EMUL_ARM_UNKNOWN;
    739 }
    740 
    741 static enum emul_arm_result
    742 emul_arm_insn(struct trapframe *tf)
    743 {
    744 	uint32_t insn;
    745 	int insn_size;
    746 
    747 	insn_size = fetch_arm_insn(tf->tf_pc, tf->tf_spsr, &insn);
    748 	tf->tf_far = reg_far_el1_read();
    749 
    750 	if (tf->tf_spsr & SPSR_A32_T)
    751 		return emul_thumb_insn(tf, insn, insn_size);
    752 	if (insn_size != 4)
    753 		return EMUL_ARM_FAULT;
    754 
    755 	/* Breakpoint used by GDB */
    756 	if (insn == 0xe6000011 || insn == 0xe7ffdefe) {
    757 		do_trapsignal(curlwp, SIGTRAP, TRAP_BRKPT,
    758 		    (void *)tf->tf_pc, 0);
    759 		return EMUL_ARM_SUCCESS;
    760 	}
    761 
    762 	/* Unconditional instruction extension space? */
    763 	if ((insn & 0xf0000000) == 0xf0000000)
    764 		goto unknown_insn;
    765 
    766 	/* swp,swpb */
    767 	if ((insn & 0x0fb00ff0) == 0x01000090) {
    768 		if (arm_cond_match(insn, tf->tf_spsr)) {
    769 			if (emul_arm_swp(insn, tf) != 0)
    770 				return EMUL_ARM_FAULT;
    771 		}
    772 		goto emulated;
    773 	}
    774 
    775 	/*
    776 	 * Emulate ARMv6 instructions with cache operations
    777 	 * register (c7), that can be used in user mode.
    778 	 */
    779 	switch (insn & 0x0fff0fff) {
    780 	case 0x0e070f95:
    781 		if (arm_cond_match(insn, tf->tf_spsr)) {
    782 			/*
    783 			 * mcr p15, 0, <Rd>, c7, c5, 4
    784 			 * (flush prefetch buffer)
    785 			 */
    786 			isb();
    787 		}
    788 		goto emulated;
    789 	case 0x0e070f9a:
    790 		if (arm_cond_match(insn, tf->tf_spsr)) {
    791 			/*
    792 			 * mcr p15, 0, <Rd>, c7, c10, 4
    793 			 * (data synchronization barrier)
    794 			 */
    795 			dsb(sy);
    796 		}
    797 		goto emulated;
    798 	case 0x0e070fba:
    799 		if (arm_cond_match(insn, tf->tf_spsr)) {
    800 			/*
    801 			 * mcr p15, 0, <Rd>, c7, c10, 5
    802 			 * (data memory barrier)
    803 			 */
    804 			dmb(sy);
    805 		}
    806 		goto emulated;
    807 	default:
    808 		break;
    809 	}
    810 
    811  unknown_insn:
    812 	/* unknown, or unsupported instruction */
    813 	return EMUL_ARM_UNKNOWN;
    814 
    815  emulated:
    816 	tf->tf_pc += insn_size;
    817 	return EMUL_ARM_SUCCESS;
    818 }
    819 #endif /* COMPAT_NETBSD32 */
    820 
    821 void
    822 trap_el0_32sync(struct trapframe *tf)
    823 {
    824 	struct lwp * const l = curlwp;
    825 	const uint32_t esr = tf->tf_esr;
    826 	const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */
    827 
    828 #ifdef DDB
    829 	/* disable trace, and enable hardware breakpoint/watchpoint */
    830 	reg_mdscr_el1_write(
    831 	    (reg_mdscr_el1_read() & ~MDSCR_SS) | MDSCR_KDE);
    832 #else
    833 	/* disable trace */
    834 	reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS);
    835 #endif
    836 	/* enable traps and interrupts */
    837 	daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F);
    838 
    839 	switch (eclass) {
    840 #ifdef COMPAT_NETBSD32
    841 	case ESR_EC_INSN_ABT_EL0:
    842 	case ESR_EC_DATA_ABT_EL0:
    843 		data_abort_handler(tf, eclass);
    844 		userret(l);
    845 		break;
    846 
    847 	case ESR_EC_SVC_A32:
    848 		(*l->l_proc->p_md.md_syscall)(tf);
    849 		break;
    850 
    851 	case ESR_EC_FP_ACCESS:
    852 		fpu_load(l);
    853 		userret(l);
    854 		break;
    855 
    856 	case ESR_EC_FP_TRAP_A32:
    857 		do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */
    858 		userret(l);
    859 		break;
    860 
    861 	case ESR_EC_PC_ALIGNMENT:
    862 		do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr);
    863 		userret(l);
    864 		break;
    865 
    866 	case ESR_EC_SP_ALIGNMENT:
    867 		do_trapsignal(l, SIGBUS, BUS_ADRALN,
    868 		    (void *)tf->tf_reg[13], esr); /* sp is r13 on AArch32 */
    869 		userret(l);
    870 		break;
    871 
    872 	case ESR_EC_BKPT_INSN_A32:
    873 		do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr);
    874 		userret(l);
    875 		break;
    876 
    877 	case ESR_EC_UNKNOWN:
    878 		switch (emul_arm_insn(tf)) {
    879 		case EMUL_ARM_SUCCESS:
    880 			break;
    881 		case EMUL_ARM_UNKNOWN:
    882 			goto unknown;
    883 		case EMUL_ARM_FAULT:
    884 			do_trapsignal(l, SIGSEGV, SEGV_MAPERR,
    885 			    (void *)tf->tf_far, esr);
    886 			break;
    887 		}
    888 		userret(l);
    889 		break;
    890 
    891 	case ESR_EC_CP15_RT:
    892 	case ESR_EC_CP15_RRT:
    893 	case ESR_EC_CP14_RT:
    894 	case ESR_EC_CP14_DT:
    895 	case ESR_EC_CP14_RRT:
    896 unknown:
    897 #endif /* COMPAT_NETBSD32 */
    898 	default:
    899 #ifdef DDB
    900 		if (sigill_debug) {
    901 			/* show illegal instruction */
    902 			printf("TRAP: pid %d (%s), uid %d: %s:"
    903 			    " esr=0x%lx: pc=0x%lx: %s\n",
    904 			    curlwp->l_proc->p_pid, curlwp->l_proc->p_comm,
    905 			    l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1,
    906 			    eclass_trapname(eclass), tf->tf_esr, tf->tf_pc,
    907 			    strdisasm(tf->tf_pc, tf->tf_spsr));
    908 		}
    909 #endif
    910 		/* illegal or not implemented instruction */
    911 		do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr);
    912 		userret(l);
    913 		break;
    914 	}
    915 }
    916 
    917 void
    918 trap_el1h_error(struct trapframe *tf)
    919 {
    920 	/*
    921 	 * Normally, we should panic unconditionally,
    922 	 * but SError interrupt may occur when accessing to unmapped(?) I/O
    923 	 * spaces. bus_space_{peek,poke}_{1,2,4,8}() should trap these case.
    924 	 */
    925 	struct faultbuf *fb;
    926 
    927 	if (curcpu()->ci_intr_depth == 0) {
    928 		fb = cpu_disable_onfault();
    929 		if (fb != NULL) {
    930 			cpu_jump_onfault(tf, fb, EFAULT);
    931 			return;
    932 		}
    933 	}
    934 	panic("%s", __func__);
    935 }
    936 
    937 #define bad_trap_panic(trapfunc)	\
    938 void					\
    939 trapfunc(struct trapframe *tf)		\
    940 {					\
    941 	panic("%s", __func__);		\
    942 }
    943 bad_trap_panic(trap_el1t_sync)
    944 bad_trap_panic(trap_el1t_irq)
    945 bad_trap_panic(trap_el1t_fiq)
    946 bad_trap_panic(trap_el1t_error)
    947 bad_trap_panic(trap_el1h_fiq)
    948 bad_trap_panic(trap_el0_fiq)
    949 bad_trap_panic(trap_el0_error)
    950 bad_trap_panic(trap_el0_32fiq)
    951 bad_trap_panic(trap_el0_32error)
    952 
    953 void
    954 cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb, int val)
    955 {
    956 	tf->tf_reg[19] = fb->fb_reg[FB_X19];
    957 	tf->tf_reg[20] = fb->fb_reg[FB_X20];
    958 	tf->tf_reg[21] = fb->fb_reg[FB_X21];
    959 	tf->tf_reg[22] = fb->fb_reg[FB_X22];
    960 	tf->tf_reg[23] = fb->fb_reg[FB_X23];
    961 	tf->tf_reg[24] = fb->fb_reg[FB_X24];
    962 	tf->tf_reg[25] = fb->fb_reg[FB_X25];
    963 	tf->tf_reg[26] = fb->fb_reg[FB_X26];
    964 	tf->tf_reg[27] = fb->fb_reg[FB_X27];
    965 	tf->tf_reg[28] = fb->fb_reg[FB_X28];
    966 	tf->tf_reg[29] = fb->fb_reg[FB_X29];
    967 	tf->tf_sp = fb->fb_reg[FB_SP];
    968 	tf->tf_pc = fb->fb_reg[FB_LR];
    969 	tf->tf_reg[0] = val;
    970 }
    971 
    972 #ifdef TRAP_SIGDEBUG
    973 static void
    974 frame_dump(const struct trapframe *tf)
    975 {
    976 	const struct reg *r = &tf->tf_regs;
    977 
    978 	printf("trapframe %p\n", tf);
    979 	for (size_t i = 0; i < __arraycount(r->r_reg); i++) {
    980 		printf(" r%.2zu %#018" PRIx64 "%c", i, r->r_reg[i],
    981 		    " \n"[i && (i & 1) == 0]);
    982 	}
    983 
    984 	printf("\n");
    985 	printf("   sp %#018" PRIx64 "    pc %#018" PRIx64 "\n",
    986 	    r->r_sp, r->r_pc);
    987 	printf(" spsr %#018" PRIx64 " tpidr %#018" PRIx64 "\n",
    988 	    r->r_spsr, r->r_tpidr);
    989 	printf("  esr %#018" PRIx64 "   far %#018" PRIx64 "\n",
    990 	    tf->tf_esr, tf->tf_far);
    991 
    992 	printf("\n");
    993 	hexdump(printf, "Stack dump", tf, 256);
    994 }
    995 
    996 static void
    997 sigdebug(const struct trapframe *tf, const ksiginfo_t *ksi)
    998 {
    999 	struct lwp *l = curlwp;
   1000 	struct proc *p = l->l_proc;
   1001 	const uint32_t eclass = __SHIFTOUT(ksi->ksi_trap, ESR_EC);
   1002 
   1003 	printf("pid %d.%d (%s): signal %d (trap %#x) "
   1004 	    "@pc %#" PRIx64 ", addr %p, error=%s\n",
   1005 	    p->p_pid, l->l_lid, p->p_comm, ksi->ksi_signo, ksi->ksi_trap,
   1006 	    tf->tf_regs.r_pc, ksi->ksi_addr, eclass_trapname(eclass));
   1007 	frame_dump(tf);
   1008 }
   1009 #endif
   1010 
   1011 void
   1012 do_trapsignal1(
   1013 #ifdef TRAP_SIGDEBUG
   1014     const char *func,
   1015     size_t line,
   1016     struct trapframe *tf,
   1017 #endif
   1018     struct lwp *l, int signo, int code, void *addr, int trap)
   1019 {
   1020 	ksiginfo_t ksi;
   1021 
   1022 	KSI_INIT_TRAP(&ksi);
   1023 	ksi.ksi_signo = signo;
   1024 	ksi.ksi_code = code;
   1025 	ksi.ksi_addr = addr;
   1026 	ksi.ksi_trap = trap;
   1027 #ifdef TRAP_SIGDEBUG
   1028 	printf("%s, %zu: ", func, line);
   1029 	sigdebug(tf, &ksi);
   1030 #endif
   1031 	(*l->l_proc->p_emul->e_trapsignal)(l, &ksi);
   1032 }
   1033 
   1034 bool
   1035 cpu_intr_p(void)
   1036 {
   1037 	int idepth;
   1038 	long pctr;
   1039 	lwp_t *l;
   1040 
   1041 #ifdef __HAVE_PIC_FAST_SOFTINTS
   1042 	/* XXX Copied from cpu.h.  Looks incomplete - needs fixing. */
   1043 	if (ci->ci_cpl < IPL_VM)
   1044 		return false;
   1045 #endif
   1046 
   1047 	l = curlwp;
   1048 	if (__predict_false(l->l_cpu == NULL)) {
   1049 		KASSERT(l == &lwp0);
   1050 		return false;
   1051 	}
   1052 	do {
   1053 		pctr = lwp_pctr();
   1054 		idepth = l->l_cpu->ci_intr_depth;
   1055 	} while (__predict_false(pctr != lwp_pctr()));
   1056 
   1057 	return idepth > 0;
   1058 }
   1059