Home | History | Annotate | Line # | Download | only in riscv
      1 /*	$NetBSD: trap.c,v 1.30 2024/11/25 22:04:14 skrll 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 #define	__PMAP_PRIVATE
     35 #define	__UFETCHSTORE_PRIVATE
     36 
     37 __RCSID("$NetBSD: trap.c,v 1.30 2024/11/25 22:04:14 skrll Exp $");
     38 
     39 #include <sys/param.h>
     40 
     41 #include <sys/atomic.h>
     42 #include <sys/cpu.h>
     43 #include <sys/kauth.h>
     44 #include <sys/signal.h>
     45 #include <sys/signalvar.h>
     46 #include <sys/siginfo.h>
     47 #include <sys/systm.h>
     48 
     49 #include <uvm/uvm.h>
     50 
     51 #include <machine/locore.h>
     52 #include <machine/machdep.h>
     53 #include <machine/db_machdep.h>
     54 #include <machine/userret.h>
     55 
     56 #define	MACHINE_ECALL_TRAP_MASK	(__BIT(CAUSE_MACHINE_ECALL))
     57 
     58 #define	SUPERVISOR_ECALL_TRAP_MASK					\
     59 				(__BIT(CAUSE_SUPERVISOR_ECALL))
     60 
     61 #define	USER_ECALL_TRAP_MASK	(__BIT(CAUSE_USER_ECALL))
     62 
     63 #define	SYSCALL_TRAP_MASK	(__BIT(CAUSE_SYSCALL))
     64 
     65 #define	BREAKPOINT_TRAP_MASK	(__BIT(CAUSE_BREAKPOINT))
     66 
     67 #define	INSTRUCTION_TRAP_MASK	(__BIT(CAUSE_ILLEGAL_INSTRUCTION))
     68 
     69 #define	FAULT_TRAP_MASK		(__BIT(CAUSE_FETCH_ACCESS) 		\
     70 				|__BIT(CAUSE_LOAD_ACCESS) 		\
     71 				|__BIT(CAUSE_STORE_ACCESS)		\
     72 				|__BIT(CAUSE_FETCH_PAGE_FAULT) 		\
     73 				|__BIT(CAUSE_LOAD_PAGE_FAULT) 		\
     74 				|__BIT(CAUSE_STORE_PAGE_FAULT))
     75 
     76 #define	MISALIGNED_TRAP_MASK	(__BIT(CAUSE_FETCH_MISALIGNED)		\
     77 				|__BIT(CAUSE_LOAD_MISALIGNED)		\
     78 				|__BIT(CAUSE_STORE_MISALIGNED))
     79 
     80 static const char * const causenames[] = {
     81 	[CAUSE_FETCH_MISALIGNED] = "misaligned fetch",
     82 	[CAUSE_LOAD_MISALIGNED] = "misaligned load",
     83 	[CAUSE_STORE_MISALIGNED] = "misaligned store",
     84 	[CAUSE_FETCH_ACCESS] = "fetch",
     85 	[CAUSE_LOAD_ACCESS] = "load",
     86 	[CAUSE_STORE_ACCESS] = "store",
     87 	[CAUSE_ILLEGAL_INSTRUCTION] = "illegal instruction",
     88 	[CAUSE_BREAKPOINT] = "breakpoint",
     89 	[CAUSE_SYSCALL] = "syscall",
     90 	[CAUSE_FETCH_PAGE_FAULT] = "instruction page fault",
     91 	[CAUSE_LOAD_PAGE_FAULT] = "load page fault",
     92 	[CAUSE_STORE_PAGE_FAULT] = "store page fault",
     93 };
     94 
     95 
     96 void
     97 cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb, int error)
     98 {
     99 	tf->tf_a0 = error;
    100 	tf->tf_ra = fb->fb_reg[FB_RA];
    101 	tf->tf_s0 = fb->fb_reg[FB_S0];
    102 	tf->tf_s1 = fb->fb_reg[FB_S1];
    103 	tf->tf_s2 = fb->fb_reg[FB_S2];
    104 	tf->tf_s3 = fb->fb_reg[FB_S3];
    105 	tf->tf_s4 = fb->fb_reg[FB_S4];
    106 	tf->tf_s5 = fb->fb_reg[FB_S5];
    107 	tf->tf_s6 = fb->fb_reg[FB_S6];
    108 	tf->tf_s7 = fb->fb_reg[FB_S7];
    109 	tf->tf_s8 = fb->fb_reg[FB_S8];
    110 	tf->tf_s9 = fb->fb_reg[FB_S9];
    111 	tf->tf_s10 = fb->fb_reg[FB_S10];
    112 	tf->tf_s11 = fb->fb_reg[FB_S11];
    113 	tf->tf_sp = fb->fb_reg[FB_SP];
    114 	tf->tf_pc = fb->fb_reg[FB_RA];
    115 }
    116 
    117 
    118 int
    119 copyin(const void *uaddr, void *kaddr, size_t len)
    120 {
    121 	struct faultbuf fb;
    122 	int error;
    123 
    124 	if (__predict_false(len == 0)) {
    125 		return 0;
    126 	}
    127 
    128 	// XXXNH cf. VM_MIN_ADDRESS and user_va0_disable
    129 	if (uaddr == NULL)
    130 		return EFAULT;
    131 
    132 	const vaddr_t uva = (vaddr_t)uaddr;
    133 	if (uva > VM_MAXUSER_ADDRESS - len)
    134 		return EFAULT;
    135 
    136 	csr_sstatus_set(SR_SUM);
    137 	if ((error = cpu_set_onfault(&fb)) == 0) {
    138 		memcpy(kaddr, uaddr, len);
    139 		cpu_unset_onfault();
    140 	}
    141 	csr_sstatus_clear(SR_SUM);
    142 
    143 	return error;
    144 }
    145 
    146 int
    147 copyout(const void *kaddr, void *uaddr, size_t len)
    148 {
    149 	struct faultbuf fb;
    150 	int error;
    151 
    152 	if (__predict_false(len == 0)) {
    153 		return 0;
    154 	}
    155 
    156 	// XXXNH cf. VM_MIN_ADDRESS and user_va0_disable
    157 	if (uaddr == NULL)
    158 		return EFAULT;
    159 
    160 	const vaddr_t uva = (vaddr_t)uaddr;
    161 	if (uva > VM_MAXUSER_ADDRESS - len)
    162 		return EFAULT;
    163 
    164 	csr_sstatus_set(SR_SUM);
    165 	if ((error = cpu_set_onfault(&fb)) == 0) {
    166 		memcpy(uaddr, kaddr, len);
    167 		cpu_unset_onfault();
    168 	}
    169 	csr_sstatus_clear(SR_SUM);
    170 
    171 	return error;
    172 }
    173 
    174 int
    175 kcopy(const void *kfaddr, void *kdaddr, size_t len)
    176 {
    177 	struct faultbuf fb;
    178 	int error;
    179 
    180 	if ((error = cpu_set_onfault(&fb)) == 0) {
    181 		memcpy(kdaddr, kfaddr, len);
    182 		cpu_unset_onfault();
    183 	}
    184 
    185 	return error;
    186 }
    187 
    188 int
    189 copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
    190 {
    191 	struct faultbuf fb;
    192 	size_t retlen;
    193 	int error;
    194 
    195 	if (__predict_false(len == 0)) {
    196 		return 0;
    197 	}
    198 
    199 	if (__predict_false(uaddr == NULL))
    200 		return EFAULT;
    201 	/*
    202 	 * Can only check if starting user address is out of range here.
    203 	 * The string may end before uva + len.
    204 	 */
    205 	const vaddr_t uva = (vaddr_t)uaddr;
    206 	if (uva > VM_MAXUSER_ADDRESS)
    207 		return EFAULT;
    208 
    209 	csr_sstatus_set(SR_SUM);
    210 	if ((error = cpu_set_onfault(&fb)) == 0) {
    211 		retlen = strlcpy(kaddr, uaddr, len);
    212 		cpu_unset_onfault();
    213 		if (retlen >= len) {
    214 			error = ENAMETOOLONG;
    215 		} else if (done != NULL) {
    216 			*done = retlen + 1;
    217 		}
    218 	}
    219 	csr_sstatus_clear(SR_SUM);
    220 
    221 	return error;
    222 }
    223 
    224 int
    225 copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done)
    226 {
    227 	struct faultbuf fb;
    228 	size_t retlen;
    229 	int error;
    230 
    231 	if (__predict_false(len == 0)) {
    232 		return 0;
    233 	}
    234 
    235 	if (__predict_false(uaddr == NULL))
    236 		return EFAULT;
    237 	/*
    238 	 * Can only check if starting user address is out of range here.
    239 	 * The string may end before uva + len.
    240 	 */
    241 	const vaddr_t uva = (vaddr_t)uaddr;
    242 	if (uva > VM_MAXUSER_ADDRESS)
    243 		return EFAULT;
    244 
    245 	csr_sstatus_set(SR_SUM);
    246 	if ((error = cpu_set_onfault(&fb)) == 0) {
    247 		retlen = strlcpy(uaddr, kaddr, len);
    248 		cpu_unset_onfault();
    249 		if (retlen >= len) {
    250 			error = ENAMETOOLONG;
    251 		} else if (done != NULL) {
    252 			*done = retlen + 1;
    253 		}
    254 	}
    255 	csr_sstatus_clear(SR_SUM);
    256 
    257 	return error;
    258 }
    259 
    260 static const char *
    261 cause_name(register_t cause)
    262 {
    263 	if (CAUSE_INTERRUPT_P(cause))
    264 		return "interrupt";
    265 	const char *name = "(unk)";
    266 	if (cause < __arraycount(causenames) && causenames[cause] != NULL)
    267 		name = causenames[cause];
    268 
    269 	return name;
    270 }
    271 
    272 void
    273 dump_trapframe(const struct trapframe *tf, void (*pr)(const char *, ...))
    274 {
    275 	const char *name = cause_name(tf->tf_cause);
    276 	static const char *regname[] = {
    277 		   "ra",  "sp",  "gp",	//  x0,  x1,  x2,  x3,
    278 	    "tp",  "t0",  "t1",  "t2",	//  x4,  x5,  x6,  x7,
    279 	    "s0",  "s1",  "a0",  "a1",	//  x8,  x9, x10, x11,
    280 	    "a2",  "a3",  "a4",  "a5",	// x12, x13, x14, x15,
    281 	    "a6",  "a7",  "s2",  "s3",	// x16, x17, x18, x19,
    282 	    "s4",  "s5",  "s6",  "s7",	// x20, x21, x22, x23,
    283 	    "s8",  "s9", "s10", "s11",	// x24, x25, x26, x27,
    284 	    "t3",  "t4",  "t5",  "t6",	// x28, x29, x30, x31,
    285 	};
    286 
    287 	(*pr)("Trapframe @ %p "
    288 	    "(cause=%d (%s), status=%#x, pc=%#18" PRIxREGISTER
    289 	    ", va=%#" PRIxREGISTER "):\n",
    290 	    tf, tf->tf_cause, name, tf->tf_sr, tf->tf_pc, tf->tf_tval);
    291 
    292 	(*pr)("                        ");
    293 	for (unsigned reg = 1; reg < 32; reg++) {
    294 		(*pr)("%-3s=%#18" PRIxREGISTER "  ",
    295 		    regname[reg - 1],
    296 		    tf->tf_regs.r_reg[reg - 1]);
    297 		if (reg % 4 == 3)
    298 			(*pr)("\n");
    299 	}
    300 }
    301 
    302 static inline void
    303 trap_ksi_init(ksiginfo_t *ksi, int signo, int code, vaddr_t addr,
    304      register_t cause)
    305 {
    306 	KSI_INIT_TRAP(ksi);
    307 	ksi->ksi_signo = signo;
    308 	ksi->ksi_code = code;
    309 	ksi->ksi_addr = (void *)addr;
    310 	ksi->ksi_trap = cause;
    311 }
    312 
    313 static void
    314 cpu_trapsignal(struct trapframe *tf, ksiginfo_t *ksi)
    315 {
    316 	if (cpu_printfataltraps) {
    317 		dump_trapframe(tf, printf);
    318 	}
    319 	(*curlwp->l_proc->p_emul->e_trapsignal)(curlwp, ksi);
    320 }
    321 
    322 static inline vm_prot_t
    323 get_faulttype(register_t cause)
    324 {
    325 	if (cause == CAUSE_LOAD_ACCESS || cause == CAUSE_LOAD_PAGE_FAULT)
    326 		return VM_PROT_READ;
    327 	if (cause == CAUSE_STORE_ACCESS || cause == CAUSE_STORE_PAGE_FAULT)
    328 		return VM_PROT_WRITE;
    329 	KASSERT(cause == CAUSE_FETCH_ACCESS || cause == CAUSE_FETCH_PAGE_FAULT);
    330 	return VM_PROT_EXECUTE;
    331 }
    332 
    333 static bool
    334 trap_pagefault_fixup(struct trapframe *tf, struct pmap *pmap, register_t cause,
    335     intptr_t addr)
    336 {
    337 	pt_entry_t * const ptep = pmap_pte_lookup(pmap, addr);
    338 	struct vm_page *pg;
    339 
    340 	if (ptep == NULL)
    341 		return false;
    342 
    343 	pt_entry_t opte = *ptep;
    344 	if (!pte_valid_p(opte))
    345 		return false;
    346 
    347 	pt_entry_t npte;
    348 	u_int attr;
    349 	do {
    350 		/* TODO: PTE_G is just the kernel PTE, but all pages
    351 		 * can fault for CAUSE_LOAD_PAGE_FAULT and
    352 		 * CAUSE_STORE_PAGE_FAULT...*/
    353 		/* if ((opte & ~PTE_G) == 0) */
    354 		/* 	return false; */
    355 
    356 		pg = PHYS_TO_VM_PAGE(pte_to_paddr(opte));
    357 		if (pg == NULL)
    358 			return false;
    359 
    360 		attr = 0;
    361 		npte = opte;
    362 
    363 		switch (cause) {
    364 		case CAUSE_LOAD_PAGE_FAULT:
    365 			if ((npte & PTE_R) == 0) {
    366 				npte |= PTE_A;
    367 				attr |= VM_PAGEMD_REFERENCED;
    368 			}
    369 			break;
    370 		case CAUSE_STORE_ACCESS:
    371 			if ((npte & PTE_W) != 0) {
    372 				npte |= PTE_A | PTE_D;
    373 				attr |= VM_PAGEMD_MODIFIED;
    374 			}
    375 			break;
    376 		case CAUSE_STORE_PAGE_FAULT:
    377 			if ((npte & PTE_D) == 0) {
    378 				npte |= PTE_A | PTE_D;
    379 				attr |= VM_PAGEMD_REFERENCED | VM_PAGEMD_MODIFIED;
    380 			}
    381 			break;
    382 		case CAUSE_FETCH_ACCESS:
    383 		case CAUSE_FETCH_PAGE_FAULT:
    384 #if 0
    385 			if ((npte & PTE_NX) != 0) {
    386 				npte &= ~PTE_NX;
    387 				attr |= VM_PAGEMD_EXECPAGE;
    388 			}
    389 #endif
    390 			break;
    391 		default:
    392 			panic("%s: Unhandled cause (%#" PRIxREGISTER
    393 			    ") for addr %lx", __func__, cause, addr);
    394 		}
    395 		if (attr == 0)
    396 			return false;
    397 	} while (opte != atomic_cas_pte(ptep, opte, npte));
    398 
    399 	pmap_page_set_attributes(VM_PAGE_TO_MD(pg), attr);
    400 	pmap_tlb_update_addr(pmap, addr, npte, 0);
    401 
    402 	if (attr & VM_PAGEMD_EXECPAGE)
    403 		pmap_md_page_syncicache(VM_PAGE_TO_MD(pg),
    404 		    curcpu()->ci_kcpuset);
    405 
    406 	return true;
    407 }
    408 
    409 static bool
    410 trap_pagefault(struct trapframe *tf, register_t epc, register_t status,
    411     register_t cause, register_t tval, bool usertrap_p, ksiginfo_t *ksi)
    412 {
    413 	struct proc * const p = curlwp->l_proc;
    414 	const intptr_t addr = trunc_page(tval);
    415 
    416 	if (__predict_false(usertrap_p
    417 	    && (false
    418 		// Make this address is not trying to access kernel space.
    419 		|| addr < 0
    420 #ifdef _LP64
    421 		// If this is a process using a 32-bit address space, make
    422 		// sure the address is a signed 32-bit number.
    423 		|| ((p->p_flag & PK_32) && (int32_t) addr != addr)
    424 #endif
    425 		|| false))) {
    426 		trap_ksi_init(ksi, SIGSEGV, SEGV_MAPERR, addr, cause);
    427 		return false;
    428 	}
    429 
    430 	struct vm_map * const map = (addr >= 0 ?
    431 	    &p->p_vmspace->vm_map : kernel_map);
    432 
    433 	// See if this fault is for reference/modified/execpage tracking
    434 	if (trap_pagefault_fixup(tf, map->pmap, cause, addr))
    435 		return true;
    436 
    437 #ifdef PMAP_FAULTINFO
    438 	struct pcb * const pcb = lwp_getpcb(curlwp);
    439 	struct pcb_faultinfo * const pfi = &pcb->pcb_faultinfo;
    440 
    441 	if (p->p_pid == pfi->pfi_lastpid && addr == pfi->pfi_faultaddr) {
    442 		if (++pfi->pfi_repeats > 4) {
    443 			tlb_asid_t asid = tlb_get_asid();
    444 			pt_entry_t *ptep = pfi->pfi_faultptep;
    445 			printf("%s: fault #%u (%s) for %#" PRIxVADDR
    446 			    "(%#"PRIxVADDR") at pc %#"PRIxVADDR" curpid=%u/%u "
    447 			    "ptep@%p=%#"PRIxPTE")\n", __func__,
    448 			    pfi->pfi_repeats, cause_name(tf->tf_cause),
    449 			    tval, addr, epc, map->pmap->pm_pai[0].pai_asid,
    450 			    asid, ptep, ptep ? pte_value(*ptep) : 0);
    451 			if (pfi->pfi_repeats >= 4) {
    452 				cpu_Debugger();
    453 			} else {
    454 				pfi->pfi_cause = cause;
    455 			}
    456 		}
    457 	} else {
    458 		pfi->pfi_lastpid = p->p_pid;
    459 		pfi->pfi_faultaddr = addr;
    460 		pfi->pfi_repeats = 0;
    461 		pfi->pfi_faultptep = NULL;
    462 		pfi->pfi_cause = cause;
    463 	}
    464 #endif /* PMAP_FAULTINFO */
    465 
    466 	const vm_prot_t ftype = get_faulttype(cause);
    467 
    468 	if (usertrap_p) {
    469 		int error = uvm_fault(&p->p_vmspace->vm_map, addr, ftype);
    470 		if (error) {
    471 			int signo = SIGSEGV;
    472 			int code = SEGV_MAPERR;
    473 
    474 			switch (error) {
    475 			case ENOMEM: {
    476 				struct lwp * const l = curlwp;
    477 				printf("UVM: pid %d (%s), uid %d killed: "
    478 				    "out of swap\n",
    479 				    l->l_proc->p_pid, l->l_proc->p_comm,
    480 				    l->l_cred ?
    481 					kauth_cred_geteuid(l->l_cred) : -1);
    482 				signo = SIGKILL;
    483 				code = 0;
    484 				break;
    485 			    }
    486 			case EACCES:
    487 				KASSERT(signo == SIGSEGV);
    488 				code = SEGV_ACCERR;
    489 				break;
    490 			case EINVAL:
    491 				signo = SIGBUS;
    492 				code = BUS_ADRERR;
    493 				break;
    494 			}
    495 
    496 			trap_ksi_init(ksi, signo, code, (intptr_t)tval, cause);
    497 			return false;
    498 		}
    499 		uvm_grow(p, addr);
    500 
    501 		return true;
    502 	}
    503 
    504 	// Page faults are not allowed while dealing with interrupts
    505 	if (cpu_intr_p())
    506 		return false;
    507 
    508 	struct faultbuf * const fb = cpu_disable_onfault();
    509 	int error = uvm_fault(map, addr, ftype);
    510 	cpu_enable_onfault(fb);
    511 
    512 	if (error == 0) {
    513 		if (map != kernel_map) {
    514 			uvm_grow(p, addr);
    515 		}
    516 		return true;
    517 	}
    518 
    519 	if (fb == NULL) {
    520 		return false;
    521 	}
    522 
    523 	cpu_jump_onfault(tf, fb, error);
    524 	return true;
    525 }
    526 
    527 static bool
    528 trap_instruction(struct trapframe *tf, register_t epc, register_t status,
    529     register_t cause, register_t tval, bool usertrap_p, ksiginfo_t *ksi)
    530 {
    531 	if (usertrap_p) {
    532 		if (__SHIFTOUT(tf->tf_sr, SR_FS) == SR_FS_OFF) {
    533 			fpu_load();
    534 			return true;
    535 		}
    536 
    537 		trap_ksi_init(ksi, SIGILL, ILL_ILLOPC,
    538 		    (intptr_t)tval, cause);
    539 	}
    540 	return false;
    541 }
    542 
    543 static bool
    544 trap_misalignment(struct trapframe *tf, register_t epc, register_t status,
    545     register_t cause, register_t tval, bool usertrap_p, ksiginfo_t *ksi)
    546 {
    547 	if (usertrap_p) {
    548 		trap_ksi_init(ksi, SIGBUS, BUS_ADRALN,
    549 		    (intptr_t)tval, cause);
    550 	}
    551 	return false;
    552 }
    553 
    554 static bool
    555 trap_breakpoint(struct trapframe *tf, register_t epc, register_t status,
    556     register_t cause, register_t tval, bool usertrap_p, ksiginfo_t *ksi)
    557 {
    558 	if (usertrap_p) {
    559 		trap_ksi_init(ksi, SIGTRAP, TRAP_BRKPT,
    560 		    (intptr_t)tval, cause);
    561 	} else {
    562 		dump_trapframe(tf, printf);
    563 #if defined(DDB)
    564 		kdb_trap(cause, tf);
    565 		PC_BREAK_ADVANCE(tf);
    566 #else
    567 		panic("%s: unknown kernel trap", __func__);
    568 #endif
    569 		return true;
    570 	}
    571 	return false;
    572 }
    573 
    574 void
    575 cpu_trap(struct trapframe *tf, register_t epc, register_t status,
    576     register_t cause, register_t tval)
    577 {
    578 	const register_t code = CAUSE_CODE(cause);
    579 	const register_t fault_mask = __BIT(code);
    580 	const intptr_t addr = tval;
    581 	const bool usertrap_p = (status & SR_SPP) == 0;
    582 	bool ok = true;
    583 	ksiginfo_t ksi;
    584 
    585 	KASSERT(!CAUSE_INTERRUPT_P(cause));
    586 	KASSERT(__SHIFTOUT(tf->tf_sr, SR_SIE) == 0);
    587 
    588 	/* We can allow interrupts now */
    589 	csr_sstatus_set(SR_SIE);
    590 
    591 	if (__predict_true(fault_mask & FAULT_TRAP_MASK)) {
    592 #ifndef _LP64
    593 #if 0
    594 		// This fault may be cause the kernel's page table got a new
    595 		// page table page and this pmap's page table doesn't know
    596 		// about it.  See
    597 		struct pmap * const pmap = curlwp->l_proc->p_vmspace->vm_map.pmap;
    598 		if ((intptr_t) addr < 0
    599 		    && pmap != pmap_kernel()
    600 		    && pmap_pdetab_fixup(pmap, addr)) {
    601 			return;
    602 		}
    603 #endif
    604 #endif
    605 		ok = trap_pagefault(tf, epc, status, cause, addr,
    606 		    usertrap_p, &ksi);
    607 	} else if (fault_mask & INSTRUCTION_TRAP_MASK) {
    608 		ok = trap_instruction(tf, epc, status, cause, addr,
    609 		    usertrap_p, &ksi);
    610 	} else if (fault_mask & SYSCALL_TRAP_MASK) {
    611 		panic("cpu_exception_handler failure");
    612 	} else if (fault_mask & MISALIGNED_TRAP_MASK) {
    613 		ok = trap_misalignment(tf, epc, status, cause, addr,
    614 		    usertrap_p, &ksi);
    615 	} else if (fault_mask & BREAKPOINT_TRAP_MASK) {
    616 		ok = trap_breakpoint(tf, epc, status, cause, addr,
    617 		    usertrap_p, &ksi);
    618 	}
    619 
    620 	if (usertrap_p) {
    621 		if (!ok)
    622 			cpu_trapsignal(tf, &ksi);
    623 
    624 		userret(curlwp);
    625 	} else if (!ok) {
    626 		dump_trapframe(tf, printf);
    627 		panic("%s: fatal kernel trap", __func__);
    628 	}
    629 	/*
    630 	 * Ensure interrupts are disabled in sstatus, and that interrupts
    631 	 * will get enabled on 'sret' for userland.
    632 	 */
    633 	KASSERT(__SHIFTOUT(tf->tf_sr, SR_SIE) == 0);
    634 	KASSERT(__SHIFTOUT(tf->tf_sr, SR_SPIE) != 0 ||
    635 	    __SHIFTOUT(tf->tf_sr, SR_SPP) != 0);
    636 }
    637 
    638 void
    639 cpu_ast(struct trapframe *tf)
    640 {
    641 	struct lwp * const l = curlwp;
    642 
    643 	/*
    644 	 * allow to have a chance of context switch just prior to user
    645 	 * exception return.
    646 	 */
    647 #ifdef __HAVE_PREEMPTION
    648 	kpreempt_disable();
    649 #endif
    650 	struct cpu_info * const ci = curcpu();
    651 
    652 	ci->ci_data.cpu_ntrap++;
    653 
    654 	KDASSERT(ci->ci_cpl == IPL_NONE);
    655 #ifdef __HAVE_PREEMPTION
    656 	kpreempt_enable();
    657 #endif
    658 
    659 	if (curlwp->l_pflag & LP_OWEUPC) {
    660 		curlwp->l_pflag &= ~LP_OWEUPC;
    661 		ADDUPROF(curlwp);
    662 	}
    663 
    664 	userret(l);
    665 }
    666 
    667 
    668 static int
    669 fetch_user_data(const void *uaddr, void *valp, size_t size)
    670 {
    671 	struct faultbuf fb;
    672 	int error;
    673 
    674 	const vaddr_t uva = (vaddr_t)uaddr;
    675 	if (__predict_false(uva > VM_MAXUSER_ADDRESS - size))
    676 		return EFAULT;
    677 
    678 	if ((error = cpu_set_onfault(&fb)) != 0)
    679 		return error;
    680 
    681 	csr_sstatus_set(SR_SUM);
    682 	switch (size) {
    683 	case 1:
    684 		*(uint8_t *)valp = *(volatile const uint8_t *)uaddr;
    685 		break;
    686 	case 2:
    687 		*(uint16_t *)valp = *(volatile const uint16_t *)uaddr;
    688 		break;
    689 	case 4:
    690 		*(uint32_t *)valp = *(volatile const uint32_t *)uaddr;
    691 		break;
    692 #ifdef _LP64
    693 	case 8:
    694 		*(uint64_t *)valp = *(volatile const uint64_t *)uaddr;
    695 		break;
    696 #endif /* _LP64 */
    697 	default:
    698 		error = EINVAL;
    699 	}
    700 	csr_sstatus_clear(SR_SUM);
    701 
    702 	cpu_unset_onfault();
    703 
    704 	return error;
    705 }
    706 
    707 int
    708 _ufetch_8(const uint8_t *uaddr, uint8_t *valp)
    709 {
    710 	return fetch_user_data(uaddr, valp, sizeof(*valp));
    711 }
    712 
    713 int
    714 _ufetch_16(const uint16_t *uaddr, uint16_t *valp)
    715 {
    716 	return fetch_user_data(uaddr, valp, sizeof(*valp));
    717 }
    718 
    719 int
    720 _ufetch_32(const uint32_t *uaddr, uint32_t *valp)
    721 {
    722 	return fetch_user_data(uaddr, valp, sizeof(*valp));
    723 }
    724 
    725 #ifdef _LP64
    726 int
    727 _ufetch_64(const uint64_t *uaddr, uint64_t *valp)
    728 {
    729 	return fetch_user_data(uaddr, valp, sizeof(*valp));
    730 }
    731 #endif /* _LP64 */
    732 
    733 static int
    734 store_user_data(void *uaddr, const void *valp, size_t size)
    735 {
    736 	struct faultbuf fb;
    737 	int error;
    738 
    739 	const vaddr_t uva = (vaddr_t)uaddr;
    740 	if (__predict_false(uva > VM_MAXUSER_ADDRESS - size))
    741 		return EFAULT;
    742 
    743 	if ((error = cpu_set_onfault(&fb)) != 0)
    744 		return error;
    745 
    746 	csr_sstatus_set(SR_SUM);
    747 	switch (size) {
    748 	case 1:
    749 		*(volatile uint8_t *)uaddr = *(const uint8_t *)valp;
    750 		break;
    751 	case 2:
    752 		*(volatile uint16_t *)uaddr = *(const uint8_t *)valp;
    753 		break;
    754 	case 4:
    755 		*(volatile uint32_t *)uaddr = *(const uint32_t *)valp;
    756 		break;
    757 #ifdef _LP64
    758 	case 8:
    759 		*(volatile uint64_t *)uaddr = *(const uint64_t *)valp;
    760 		break;
    761 #endif /* _LP64 */
    762 	default:
    763 		error = EINVAL;
    764 	}
    765 	csr_sstatus_clear(SR_SUM);
    766 
    767 	cpu_unset_onfault();
    768 
    769 	return error;
    770 }
    771 
    772 int
    773 _ustore_8(uint8_t *uaddr, uint8_t val)
    774 {
    775 	return store_user_data(uaddr, &val, sizeof(val));
    776 }
    777 
    778 int
    779 _ustore_16(uint16_t *uaddr, uint16_t val)
    780 {
    781 	return store_user_data(uaddr, &val, sizeof(val));
    782 }
    783 
    784 int
    785 _ustore_32(uint32_t *uaddr, uint32_t val)
    786 {
    787 	return store_user_data(uaddr, &val, sizeof(val));
    788 }
    789 
    790 #ifdef _LP64
    791 int
    792 _ustore_64(uint64_t *uaddr, uint64_t val)
    793 {
    794 	return store_user_data(uaddr, &val, sizeof(val));
    795 }
    796 #endif /* _LP64 */
    797