17e55f8c1SIan Lepore /*-
27e55f8c1SIan Lepore * Copyright 2014 Olivier Houchard <cognet@FreeBSD.org>
37e55f8c1SIan Lepore * Copyright 2014 Svatopluk Kraus <onwahe@gmail.com>
47e55f8c1SIan Lepore * Copyright 2014 Michal Meloun <meloun@miracle.cz>
57e55f8c1SIan Lepore * Copyright 2014 Andrew Turner <andrew@FreeBSD.org>
67e55f8c1SIan Lepore * All rights reserved.
77e55f8c1SIan Lepore *
87e55f8c1SIan Lepore * Redistribution and use in source and binary forms, with or without
97e55f8c1SIan Lepore * modification, are permitted provided that the following conditions
107e55f8c1SIan Lepore * are met:
117e55f8c1SIan Lepore * 1. Redistributions of source code must retain the above copyright
127e55f8c1SIan Lepore * notice, this list of conditions and the following disclaimer.
137e55f8c1SIan Lepore * 2. Redistributions in binary form must reproduce the above copyright
147e55f8c1SIan Lepore * notice, this list of conditions and the following disclaimer in the
157e55f8c1SIan Lepore * documentation and/or other materials provided with the distribution.
167e55f8c1SIan Lepore *
177e55f8c1SIan Lepore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
187e55f8c1SIan Lepore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
197e55f8c1SIan Lepore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
207e55f8c1SIan Lepore * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
217e55f8c1SIan Lepore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
227e55f8c1SIan Lepore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
237e55f8c1SIan Lepore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
247e55f8c1SIan Lepore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
257e55f8c1SIan Lepore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
267e55f8c1SIan Lepore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
277e55f8c1SIan Lepore * SUCH DAMAGE.
287e55f8c1SIan Lepore */
297e55f8c1SIan Lepore
307e55f8c1SIan Lepore #include "opt_ktrace.h"
317e55f8c1SIan Lepore
327e55f8c1SIan Lepore #include <sys/param.h>
337e55f8c1SIan Lepore #include <sys/bus.h>
347e55f8c1SIan Lepore #include <sys/systm.h>
357e55f8c1SIan Lepore #include <sys/proc.h>
367e55f8c1SIan Lepore #include <sys/kernel.h>
377e55f8c1SIan Lepore #include <sys/lock.h>
387e55f8c1SIan Lepore #include <sys/mutex.h>
397e55f8c1SIan Lepore #include <sys/signalvar.h>
407e55f8c1SIan Lepore #include <sys/ktr.h>
419ed01c32SGleb Smirnoff #include <sys/vmmeter.h>
427e55f8c1SIan Lepore #ifdef KTRACE
437e55f8c1SIan Lepore #include <sys/uio.h>
447e55f8c1SIan Lepore #include <sys/ktrace.h>
457e55f8c1SIan Lepore #endif
467e55f8c1SIan Lepore
477e55f8c1SIan Lepore #include <vm/vm.h>
487e55f8c1SIan Lepore #include <vm/pmap.h>
497e55f8c1SIan Lepore #include <vm/vm_kern.h>
507e55f8c1SIan Lepore #include <vm/vm_map.h>
517e55f8c1SIan Lepore #include <vm/vm_extern.h>
527e55f8c1SIan Lepore #include <vm/vm_param.h>
537e55f8c1SIan Lepore
547e55f8c1SIan Lepore #include <machine/cpu.h>
557e55f8c1SIan Lepore #include <machine/frame.h>
567e55f8c1SIan Lepore #include <machine/machdep.h>
577e55f8c1SIan Lepore #include <machine/pcb.h>
587e55f8c1SIan Lepore
597e55f8c1SIan Lepore #ifdef KDB
607e55f8c1SIan Lepore #include <sys/kdb.h>
617e55f8c1SIan Lepore #include <machine/db_machdep.h>
627e55f8c1SIan Lepore #endif
637e55f8c1SIan Lepore
64c2188153SAndrew Turner #ifdef KDTRACE_HOOKS
65c2188153SAndrew Turner #include <sys/dtrace_bsd.h>
66c2188153SAndrew Turner #endif
67c2188153SAndrew Turner
688826d904SIan Lepore extern char cachebailout[];
697e55f8c1SIan Lepore
707e55f8c1SIan Lepore struct ksig {
717e55f8c1SIan Lepore int sig;
727e55f8c1SIan Lepore u_long code;
737e55f8c1SIan Lepore vm_offset_t addr;
747e55f8c1SIan Lepore };
757e55f8c1SIan Lepore
767e55f8c1SIan Lepore typedef int abort_func_t(struct trapframe *, u_int, u_int, u_int, u_int,
777e55f8c1SIan Lepore struct thread *, struct ksig *);
787e55f8c1SIan Lepore
797e55f8c1SIan Lepore static abort_func_t abort_fatal;
807e55f8c1SIan Lepore static abort_func_t abort_align;
817e55f8c1SIan Lepore static abort_func_t abort_icache;
827e55f8c1SIan Lepore
837e55f8c1SIan Lepore struct abort {
847e55f8c1SIan Lepore abort_func_t *func;
857e55f8c1SIan Lepore const char *desc;
867e55f8c1SIan Lepore };
877e55f8c1SIan Lepore
887e55f8c1SIan Lepore /*
897e55f8c1SIan Lepore * How are the aborts handled?
907e55f8c1SIan Lepore *
917e55f8c1SIan Lepore * Undefined Code:
927e55f8c1SIan Lepore * - Always fatal as we do not know what does it mean.
937e55f8c1SIan Lepore * Imprecise External Abort:
947e55f8c1SIan Lepore * - Always fatal, but can be handled somehow in the future.
9536fb9d5fSSvatopluk Kraus * Now, due to PCIe buggy hardware, ignored.
967e55f8c1SIan Lepore * Precise External Abort:
977e55f8c1SIan Lepore * - Always fatal, but who knows in the future???
987e55f8c1SIan Lepore * Debug Event:
997e55f8c1SIan Lepore * - Special handling.
1007e55f8c1SIan Lepore * External Translation Abort (L1 & L2)
10136fb9d5fSSvatopluk Kraus * - Always fatal as something is screwed up in page tables or hardware.
1027e55f8c1SIan Lepore * Domain Fault (L1 & L2):
1037e55f8c1SIan Lepore * - Always fatal as we do not play game with domains.
1047e55f8c1SIan Lepore * Alignment Fault:
10536fb9d5fSSvatopluk Kraus * - Everything should be aligned in kernel with exception of user to kernel
10636fb9d5fSSvatopluk Kraus * and vice versa data copying, so if pcb_onfault is not set, it's fatal.
1077e55f8c1SIan Lepore * We generate signal in case of abort from user mode.
1087e55f8c1SIan Lepore * Instruction cache maintenance:
1097e55f8c1SIan Lepore * - According to manual, this is translation fault during cache maintenance
1107e55f8c1SIan Lepore * operation. So, it could be really complex in SMP case and fuzzy too
1117e55f8c1SIan Lepore * for cache operations working on virtual addresses. For now, we will
1127e55f8c1SIan Lepore * consider this abort as fatal. In fact, no cache maintenance on
1137e55f8c1SIan Lepore * not mapped virtual addresses should be called. As cache maintenance
1145bdf58e1SGordon Bergling * operation (except DMB, DSB, and Flush Prefetch Buffer) are privileged,
1157e55f8c1SIan Lepore * the abort is fatal for user mode as well for now. (This is good place to
1167e55f8c1SIan Lepore * note that cache maintenance on virtual address fill TLB.)
1177e55f8c1SIan Lepore * Acces Bit (L1 & L2):
1187e55f8c1SIan Lepore * - Fast hardware emulation for kernel and user mode.
1197e55f8c1SIan Lepore * Translation Fault (L1 & L2):
1207e55f8c1SIan Lepore * - Standard fault mechanism is held including vm_fault().
1217e55f8c1SIan Lepore * Permission Fault (L1 & L2):
12236fb9d5fSSvatopluk Kraus * - Fast hardware emulation of modify bits and in other cases, standard
1237e55f8c1SIan Lepore * fault mechanism is held including vm_fault().
1247e55f8c1SIan Lepore */
1257e55f8c1SIan Lepore
1267e55f8c1SIan Lepore static const struct abort aborts[] = {
1277e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x000)"},
1287e55f8c1SIan Lepore {abort_align, "Alignment Fault"},
1297e55f8c1SIan Lepore {abort_fatal, "Debug Event"},
1307e55f8c1SIan Lepore {NULL, "Access Bit (L1)"},
1318826d904SIan Lepore {NULL, "Instruction cache maintenance"},
1327e55f8c1SIan Lepore {NULL, "Translation Fault (L1)"},
1337e55f8c1SIan Lepore {NULL, "Access Bit (L2)"},
1347e55f8c1SIan Lepore {NULL, "Translation Fault (L2)"},
1357e55f8c1SIan Lepore
1367e55f8c1SIan Lepore {abort_fatal, "External Abort"},
1377e55f8c1SIan Lepore {abort_fatal, "Domain Fault (L1)"},
1387e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x00A)"},
1397e55f8c1SIan Lepore {abort_fatal, "Domain Fault (L2)"},
1407e55f8c1SIan Lepore {abort_fatal, "External Translation Abort (L1)"},
1417e55f8c1SIan Lepore {NULL, "Permission Fault (L1)"},
1427e55f8c1SIan Lepore {abort_fatal, "External Translation Abort (L2)"},
1437e55f8c1SIan Lepore {NULL, "Permission Fault (L2)"},
1447e55f8c1SIan Lepore
1457e55f8c1SIan Lepore {abort_fatal, "TLB Conflict Abort"},
1467e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x401)"},
1477e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x402)"},
1487e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x403)"},
1497e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x404)"},
1507e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x405)"},
1517e55f8c1SIan Lepore {abort_fatal, "Asynchronous External Abort"},
1527e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x407)"},
1537e55f8c1SIan Lepore
1547e55f8c1SIan Lepore {abort_fatal, "Asynchronous Parity Error on Memory Access"},
1557e55f8c1SIan Lepore {abort_fatal, "Parity Error on Memory Access"},
1567e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x40A)"},
1577e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x40B)"},
1587e55f8c1SIan Lepore {abort_fatal, "Parity Error on Translation (L1)"},
1597e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x40D)"},
1607e55f8c1SIan Lepore {abort_fatal, "Parity Error on Translation (L2)"},
1617e55f8c1SIan Lepore {abort_fatal, "Undefined Code (0x40F)"}
1627e55f8c1SIan Lepore };
1637e55f8c1SIan Lepore
1647e55f8c1SIan Lepore static __inline void
call_trapsignal(struct thread * td,int sig,int code,vm_offset_t addr,int trapno)16591371fbcSJohn Baldwin call_trapsignal(struct thread *td, int sig, int code, vm_offset_t addr,
16691371fbcSJohn Baldwin int trapno)
1677e55f8c1SIan Lepore {
1687e55f8c1SIan Lepore ksiginfo_t ksi;
1697e55f8c1SIan Lepore
1707e55f8c1SIan Lepore CTR4(KTR_TRAP, "%s: addr: %#x, sig: %d, code: %d",
1717e55f8c1SIan Lepore __func__, addr, sig, code);
1727e55f8c1SIan Lepore
1737e55f8c1SIan Lepore /*
1747e55f8c1SIan Lepore * TODO: some info would be nice to know
1757e55f8c1SIan Lepore * if we are serving data or prefetch abort.
1767e55f8c1SIan Lepore */
1777e55f8c1SIan Lepore
1787e55f8c1SIan Lepore ksiginfo_init_trap(&ksi);
1797e55f8c1SIan Lepore ksi.ksi_signo = sig;
1807e55f8c1SIan Lepore ksi.ksi_code = code;
1817e55f8c1SIan Lepore ksi.ksi_addr = (void *)addr;
18291371fbcSJohn Baldwin ksi.ksi_trapno = trapno;
1837e55f8c1SIan Lepore trapsignal(td, &ksi);
1847e55f8c1SIan Lepore }
1857e55f8c1SIan Lepore
1867e55f8c1SIan Lepore /*
1877e55f8c1SIan Lepore * abort_imprecise() handles the following abort:
1887e55f8c1SIan Lepore *
1897e55f8c1SIan Lepore * FAULT_EA_IMPREC - Imprecise External Abort
1907e55f8c1SIan Lepore *
1917e55f8c1SIan Lepore * The imprecise means that we don't know where the abort happened,
1927e55f8c1SIan Lepore * thus FAR is undefined. The abort should not never fire, but hot
19336fb9d5fSSvatopluk Kraus * plugging or accidental hardware failure can be the cause of it.
1947e55f8c1SIan Lepore * If the abort happens, it can even be on different (thread) context.
1957e55f8c1SIan Lepore * Without any additional support, the abort is fatal, as we do not
1967e55f8c1SIan Lepore * know what really happened.
1977e55f8c1SIan Lepore *
1987e55f8c1SIan Lepore * QQQ: Some additional functionality, like pcb_onfault but global,
1997e55f8c1SIan Lepore * can be implemented. Imprecise handlers could be registered
2007e55f8c1SIan Lepore * which tell us if the abort is caused by something they know
2017e55f8c1SIan Lepore * about. They should return one of three codes like:
2027e55f8c1SIan Lepore * FAULT_IS_MINE,
2037e55f8c1SIan Lepore * FAULT_CAN_BE_MINE,
2047e55f8c1SIan Lepore * FAULT_IS_NOT_MINE.
2057e55f8c1SIan Lepore * The handlers should be called until some of them returns
2067e55f8c1SIan Lepore * FAULT_IS_MINE value or all was called. If all handlers return
2077e55f8c1SIan Lepore * FAULT_IS_NOT_MINE value, then the abort is fatal.
2087e55f8c1SIan Lepore */
2097e55f8c1SIan Lepore static __inline void
abort_imprecise(struct trapframe * tf,u_int fsr,u_int prefetch,bool usermode)210bee75f52SSvatopluk Kraus abort_imprecise(struct trapframe *tf, u_int fsr, u_int prefetch, bool usermode)
2117e55f8c1SIan Lepore {
21236fb9d5fSSvatopluk Kraus
21336fb9d5fSSvatopluk Kraus /*
21436fb9d5fSSvatopluk Kraus * XXX - We can got imprecise abort as result of access
2157e55f8c1SIan Lepore * to not-present PCI/PCIe configuration space.
2167e55f8c1SIan Lepore */
2177e55f8c1SIan Lepore #if 0
2187e55f8c1SIan Lepore goto out;
2197e55f8c1SIan Lepore #endif
2207e55f8c1SIan Lepore abort_fatal(tf, FAULT_EA_IMPREC, fsr, 0, prefetch, curthread, NULL);
2217e55f8c1SIan Lepore
2227e55f8c1SIan Lepore /*
2237e55f8c1SIan Lepore * Returning from this function means that we ignore
2247e55f8c1SIan Lepore * the abort for good reason. Note that imprecise abort
2257e55f8c1SIan Lepore * could fire any time even in user mode.
2267e55f8c1SIan Lepore */
2277e55f8c1SIan Lepore
2287e55f8c1SIan Lepore #if 0
2297e55f8c1SIan Lepore out:
2307e55f8c1SIan Lepore if (usermode)
2317e55f8c1SIan Lepore userret(curthread, tf);
2327e55f8c1SIan Lepore #endif
2337e55f8c1SIan Lepore }
2347e55f8c1SIan Lepore
2357e55f8c1SIan Lepore /*
2367e55f8c1SIan Lepore * abort_debug() handles the following abort:
2377e55f8c1SIan Lepore *
2387e55f8c1SIan Lepore * FAULT_DEBUG - Debug Event
2397e55f8c1SIan Lepore *
2407e55f8c1SIan Lepore */
2417e55f8c1SIan Lepore static __inline void
abort_debug(struct trapframe * tf,u_int fsr,u_int prefetch,bool usermode,u_int far)242bee75f52SSvatopluk Kraus abort_debug(struct trapframe *tf, u_int fsr, u_int prefetch, bool usermode,
2437e55f8c1SIan Lepore u_int far)
2447e55f8c1SIan Lepore {
24536fb9d5fSSvatopluk Kraus
2467e55f8c1SIan Lepore if (usermode) {
2477e55f8c1SIan Lepore struct thread *td;
2487e55f8c1SIan Lepore
2497e55f8c1SIan Lepore td = curthread;
25091371fbcSJohn Baldwin call_trapsignal(td, SIGTRAP, TRAP_BRKPT, far, FAULT_DEBUG);
2517e55f8c1SIan Lepore userret(td, tf);
2527e55f8c1SIan Lepore } else {
2537e55f8c1SIan Lepore #ifdef KDB
254595f8a59SZbigniew Bodek kdb_trap((prefetch) ? T_BREAKPOINT : T_WATCHPOINT, 0, tf);
2557e55f8c1SIan Lepore #else
2567e55f8c1SIan Lepore printf("No debugger in kernel.\n");
2577e55f8c1SIan Lepore #endif
2587e55f8c1SIan Lepore }
2597e55f8c1SIan Lepore }
2607e55f8c1SIan Lepore
2617e55f8c1SIan Lepore /*
2627e55f8c1SIan Lepore * Abort handler.
2637e55f8c1SIan Lepore *
2647e55f8c1SIan Lepore * FAR, FSR, and everything what can be lost after enabling
2657e55f8c1SIan Lepore * interrupts must be grabbed before the interrupts will be
2667e55f8c1SIan Lepore * enabled. Note that when interrupts will be enabled, we
2677e55f8c1SIan Lepore * could even migrate to another CPU ...
2687e55f8c1SIan Lepore *
2697e55f8c1SIan Lepore * TODO: move quick cases to ASM
2707e55f8c1SIan Lepore */
2717e55f8c1SIan Lepore void
abort_handler(struct trapframe * tf,int prefetch)2727e55f8c1SIan Lepore abort_handler(struct trapframe *tf, int prefetch)
2737e55f8c1SIan Lepore {
2747e55f8c1SIan Lepore struct thread *td;
2757e55f8c1SIan Lepore vm_offset_t far, va;
276bee75f52SSvatopluk Kraus int idx, rv;
2777e55f8c1SIan Lepore uint32_t fsr;
2787e55f8c1SIan Lepore struct ksig ksig;
2797e55f8c1SIan Lepore struct proc *p;
2807e55f8c1SIan Lepore struct pcb *pcb;
2817e55f8c1SIan Lepore struct vm_map *map;
2827e55f8c1SIan Lepore struct vmspace *vm;
2837e55f8c1SIan Lepore vm_prot_t ftype;
284bee75f52SSvatopluk Kraus bool usermode;
285df08823dSKonstantin Belousov int bp_harden, ucode;
2867e55f8c1SIan Lepore #ifdef INVARIANTS
2877e55f8c1SIan Lepore void *onfault;
2887e55f8c1SIan Lepore #endif
289f196c104SSvatopluk Kraus
29083c9dea1SGleb Smirnoff VM_CNT_INC(v_trap);
2917e55f8c1SIan Lepore td = curthread;
292f196c104SSvatopluk Kraus
2937e55f8c1SIan Lepore fsr = (prefetch) ? cp15_ifsr_get(): cp15_dfsr_get();
294d5b05f19SAndrew Turner #if __ARM_ARCH >= 7
295d5b05f19SAndrew Turner far = (prefetch) ? cp15_ifar_get() : cp15_dfar_get();
296d5b05f19SAndrew Turner #else
2977e55f8c1SIan Lepore far = (prefetch) ? TRAPF_PC(tf) : cp15_dfar_get();
298d5b05f19SAndrew Turner #endif
2997e55f8c1SIan Lepore
3007e55f8c1SIan Lepore idx = FSR_TO_FAULT(fsr);
3017e55f8c1SIan Lepore usermode = TRAPF_USERMODE(tf); /* Abort came from user mode? */
302a36b6ec0SMichal Meloun
303a36b6ec0SMichal Meloun /*
304a36b6ec0SMichal Meloun * Apply BP hardening by flushing the branch prediction cache
305a36b6ec0SMichal Meloun * for prefaults on kernel addresses.
306a36b6ec0SMichal Meloun */
307a36b6ec0SMichal Meloun if (__predict_false(prefetch && far > VM_MAXUSER_ADDRESS &&
308a36b6ec0SMichal Meloun (idx == FAULT_TRAN_L2 || idx == FAULT_PERM_L2))) {
309a36b6ec0SMichal Meloun bp_harden = PCPU_GET(bp_harden_kind);
310a36b6ec0SMichal Meloun if (bp_harden == PCPU_BP_HARDEN_KIND_BPIALL)
311a36b6ec0SMichal Meloun _CP15_BPIALL();
312a36b6ec0SMichal Meloun else if (bp_harden == PCPU_BP_HARDEN_KIND_ICIALLU)
313a36b6ec0SMichal Meloun _CP15_ICIALLU();
314a36b6ec0SMichal Meloun }
315a36b6ec0SMichal Meloun
3167e55f8c1SIan Lepore if (usermode)
3177e55f8c1SIan Lepore td->td_frame = tf;
3187e55f8c1SIan Lepore
3193ee1f8b1SSvatopluk Kraus CTR6(KTR_TRAP, "%s: fsr %#x (idx %u) far %#x prefetch %u usermode %d",
3203ee1f8b1SSvatopluk Kraus __func__, fsr, idx, far, prefetch, usermode);
3217e55f8c1SIan Lepore
3227e55f8c1SIan Lepore /*
3237e55f8c1SIan Lepore * Firstly, handle aborts that are not directly related to mapping.
3247e55f8c1SIan Lepore */
3257e55f8c1SIan Lepore if (__predict_false(idx == FAULT_EA_IMPREC)) {
3267e55f8c1SIan Lepore abort_imprecise(tf, fsr, prefetch, usermode);
3277e55f8c1SIan Lepore return;
3287e55f8c1SIan Lepore }
3297e55f8c1SIan Lepore
3307e55f8c1SIan Lepore if (__predict_false(idx == FAULT_DEBUG)) {
3317e55f8c1SIan Lepore abort_debug(tf, fsr, prefetch, usermode, far);
3327e55f8c1SIan Lepore return;
3337e55f8c1SIan Lepore }
3347e55f8c1SIan Lepore
33536fb9d5fSSvatopluk Kraus /*
33636fb9d5fSSvatopluk Kraus * ARM has a set of unprivileged load and store instructions
33736fb9d5fSSvatopluk Kraus * (LDRT/LDRBT/STRT/STRBT ...) which are supposed to be used in other
33836fb9d5fSSvatopluk Kraus * than user mode and OS should recognize their aborts and behave
33936fb9d5fSSvatopluk Kraus * appropriately. However, there is no way how to do that reasonably
34036fb9d5fSSvatopluk Kraus * in general unless we restrict the handling somehow.
34136fb9d5fSSvatopluk Kraus *
34236fb9d5fSSvatopluk Kraus * For now, these instructions are used only in copyin()/copyout()
34336fb9d5fSSvatopluk Kraus * like functions where usermode buffers are checked in advance that
34436fb9d5fSSvatopluk Kraus * they are not from KVA space. Thus, no action is needed here.
34536fb9d5fSSvatopluk Kraus */
34636fb9d5fSSvatopluk Kraus
347f196c104SSvatopluk Kraus /*
348f196c104SSvatopluk Kraus * (1) Handle access and R/W hardware emulation aborts.
349f196c104SSvatopluk Kraus * (2) Check that abort is not on pmap essential address ranges.
350f196c104SSvatopluk Kraus * There is no way how to fix it, so we don't even try.
351f196c104SSvatopluk Kraus */
3527e55f8c1SIan Lepore rv = pmap_fault(PCPU_GET(curpmap), far, fsr, idx, usermode);
353b78e1f8aSSvatopluk Kraus if (rv == KERN_SUCCESS)
3547e55f8c1SIan Lepore return;
3557e55f8c1SIan Lepore #ifdef KDB
3567e55f8c1SIan Lepore if (kdb_active) {
3577e55f8c1SIan Lepore kdb_reenter();
3587e55f8c1SIan Lepore goto out;
3597e55f8c1SIan Lepore }
3607e55f8c1SIan Lepore #endif
361f196c104SSvatopluk Kraus if (rv == KERN_INVALID_ADDRESS)
362f196c104SSvatopluk Kraus goto nogo;
363f196c104SSvatopluk Kraus
3647e55f8c1SIan Lepore if (__predict_false((td->td_pflags & TDP_NOFAULTING) != 0)) {
3657e55f8c1SIan Lepore /*
3667e55f8c1SIan Lepore * Due to both processor errata and lazy TLB invalidation when
3677e55f8c1SIan Lepore * access restrictions are removed from virtual pages, memory
3687e55f8c1SIan Lepore * accesses that are allowed by the physical mapping layer may
3697e55f8c1SIan Lepore * nonetheless cause one spurious page fault per virtual page.
3707e55f8c1SIan Lepore * When the thread is executing a "no faulting" section that
3717e55f8c1SIan Lepore * is bracketed by vm_fault_{disable,enable}_pagefaults(),
3727e55f8c1SIan Lepore * every page fault is treated as a spurious page fault,
3737e55f8c1SIan Lepore * unless it accesses the same virtual address as the most
3747e55f8c1SIan Lepore * recent page fault within the same "no faulting" section.
3757e55f8c1SIan Lepore */
3767e55f8c1SIan Lepore if (td->td_md.md_spurflt_addr != far ||
3777e55f8c1SIan Lepore (td->td_pflags & TDP_RESETSPUR) != 0) {
3787e55f8c1SIan Lepore td->td_md.md_spurflt_addr = far;
3797e55f8c1SIan Lepore td->td_pflags &= ~TDP_RESETSPUR;
3807e55f8c1SIan Lepore
3817e55f8c1SIan Lepore tlb_flush_local(far & ~PAGE_MASK);
3827e55f8c1SIan Lepore return;
3837e55f8c1SIan Lepore }
3847e55f8c1SIan Lepore } else {
3857e55f8c1SIan Lepore /*
3867e55f8c1SIan Lepore * If we get a page fault while in a critical section, then
3877e55f8c1SIan Lepore * it is most likely a fatal kernel page fault. The kernel
3887e55f8c1SIan Lepore * is already going to panic trying to get a sleep lock to
3897e55f8c1SIan Lepore * do the VM lookup, so just consider it a fatal trap so the
3907e55f8c1SIan Lepore * kernel can print out a useful trap message and even get
3917e55f8c1SIan Lepore * to the debugger.
3927e55f8c1SIan Lepore *
3937e55f8c1SIan Lepore * If we get a page fault while holding a non-sleepable
3947e55f8c1SIan Lepore * lock, then it is most likely a fatal kernel page fault.
3957e55f8c1SIan Lepore * If WITNESS is enabled, then it's going to whine about
3967e55f8c1SIan Lepore * bogus LORs with various VM locks, so just skip to the
3977e55f8c1SIan Lepore * fatal trap handling directly.
3987e55f8c1SIan Lepore */
3997e55f8c1SIan Lepore if (td->td_critnest != 0 ||
4007e55f8c1SIan Lepore WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL,
4017e55f8c1SIan Lepore "Kernel page fault") != 0) {
4027e55f8c1SIan Lepore abort_fatal(tf, idx, fsr, far, prefetch, td, &ksig);
4037e55f8c1SIan Lepore return;
4047e55f8c1SIan Lepore }
4057e55f8c1SIan Lepore }
4067e55f8c1SIan Lepore
4077e55f8c1SIan Lepore /* Re-enable interrupts if they were enabled previously. */
4087e55f8c1SIan Lepore if (td->td_md.md_spinlock_count == 0) {
4097e55f8c1SIan Lepore if (__predict_true(tf->tf_spsr & PSR_I) == 0)
4107e55f8c1SIan Lepore enable_interrupts(PSR_I);
4117e55f8c1SIan Lepore if (__predict_true(tf->tf_spsr & PSR_F) == 0)
4127e55f8c1SIan Lepore enable_interrupts(PSR_F);
4137e55f8c1SIan Lepore }
4147e55f8c1SIan Lepore
4157e55f8c1SIan Lepore p = td->td_proc;
4167e55f8c1SIan Lepore if (usermode) {
4177e55f8c1SIan Lepore td->td_pticks = 0;
418b53133a7SMateusz Guzik if (td->td_cowgen != atomic_load_int(&p->p_cowgen))
4194ea6a9a2SMateusz Guzik thread_cow_update(td);
4207e55f8c1SIan Lepore }
4217e55f8c1SIan Lepore
4227e55f8c1SIan Lepore /* Invoke the appropriate handler, if necessary. */
4237e55f8c1SIan Lepore if (__predict_false(aborts[idx].func != NULL)) {
4247e55f8c1SIan Lepore if ((aborts[idx].func)(tf, idx, fsr, far, prefetch, td, &ksig))
4257e55f8c1SIan Lepore goto do_trapsignal;
4267e55f8c1SIan Lepore goto out;
4277e55f8c1SIan Lepore }
4287e55f8c1SIan Lepore
4297e55f8c1SIan Lepore /*
430f196c104SSvatopluk Kraus * At this point, we're dealing with one of the following aborts:
431f196c104SSvatopluk Kraus *
432f196c104SSvatopluk Kraus * FAULT_ICACHE - I-cache maintenance
433f196c104SSvatopluk Kraus * FAULT_TRAN_xx - Translation
434f196c104SSvatopluk Kraus * FAULT_PERM_xx - Permission
435f196c104SSvatopluk Kraus */
436f196c104SSvatopluk Kraus
437f196c104SSvatopluk Kraus /*
4388826d904SIan Lepore * Don't pass faulting cache operation to vm_fault(). We don't want
4398826d904SIan Lepore * to handle all vm stuff at this moment.
4408826d904SIan Lepore */
4418826d904SIan Lepore pcb = td->td_pcb;
4428826d904SIan Lepore if (__predict_false(pcb->pcb_onfault == cachebailout)) {
4438826d904SIan Lepore tf->tf_r0 = far; /* return failing address */
4448826d904SIan Lepore tf->tf_pc = (register_t)pcb->pcb_onfault;
4458826d904SIan Lepore return;
4468826d904SIan Lepore }
4478826d904SIan Lepore
44836fb9d5fSSvatopluk Kraus /* Handle remaining I-cache aborts. */
4498826d904SIan Lepore if (idx == FAULT_ICACHE) {
4508826d904SIan Lepore if (abort_icache(tf, idx, fsr, far, prefetch, td, &ksig))
4518826d904SIan Lepore goto do_trapsignal;
4528826d904SIan Lepore goto out;
4538826d904SIan Lepore }
4548826d904SIan Lepore
4557e55f8c1SIan Lepore va = trunc_page(far);
4567e55f8c1SIan Lepore if (va >= KERNBASE) {
4577e55f8c1SIan Lepore /*
4587e55f8c1SIan Lepore * Don't allow user-mode faults in kernel address space.
4597e55f8c1SIan Lepore */
4602e3294cdSMichal Meloun if (usermode) {
4612e3294cdSMichal Meloun ksig.sig = SIGSEGV;
4622e3294cdSMichal Meloun ksig.code = SEGV_ACCERR;
4637e55f8c1SIan Lepore goto nogo;
4642e3294cdSMichal Meloun }
4657e55f8c1SIan Lepore
4667e55f8c1SIan Lepore map = kernel_map;
4677e55f8c1SIan Lepore } else {
4687e55f8c1SIan Lepore /*
4697e55f8c1SIan Lepore * This is a fault on non-kernel virtual memory. If curproc
4707e55f8c1SIan Lepore * is NULL or curproc->p_vmspace is NULL the fault is fatal.
4717e55f8c1SIan Lepore */
4727e55f8c1SIan Lepore vm = (p != NULL) ? p->p_vmspace : NULL;
4732e3294cdSMichal Meloun if (vm == NULL) {
4742e3294cdSMichal Meloun ksig.sig = SIGSEGV;
4752e3294cdSMichal Meloun ksig.code = 0;
4767e55f8c1SIan Lepore goto nogo;
4772e3294cdSMichal Meloun }
4787e55f8c1SIan Lepore
4797e55f8c1SIan Lepore map = &vm->vm_map;
4807e55f8c1SIan Lepore if (!usermode && (td->td_intr_nesting_level != 0 ||
4817e55f8c1SIan Lepore pcb->pcb_onfault == NULL)) {
4827e55f8c1SIan Lepore abort_fatal(tf, idx, fsr, far, prefetch, td, &ksig);
4837e55f8c1SIan Lepore return;
4847e55f8c1SIan Lepore }
4857e55f8c1SIan Lepore }
4867e55f8c1SIan Lepore
4877e55f8c1SIan Lepore ftype = (fsr & FSR_WNR) ? VM_PROT_WRITE : VM_PROT_READ;
4887e55f8c1SIan Lepore if (prefetch)
4897e55f8c1SIan Lepore ftype |= VM_PROT_EXECUTE;
4907e55f8c1SIan Lepore
4917e55f8c1SIan Lepore #ifdef INVARIANTS
4927e55f8c1SIan Lepore onfault = pcb->pcb_onfault;
4937e55f8c1SIan Lepore pcb->pcb_onfault = NULL;
4947e55f8c1SIan Lepore #endif
4957e55f8c1SIan Lepore
4961fa67124SKonstantin Belousov /* Fault in the page. */
497df08823dSKonstantin Belousov rv = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL, &ksig.sig,
498df08823dSKonstantin Belousov &ucode);
499df08823dSKonstantin Belousov ksig.code = ucode;
5007e55f8c1SIan Lepore
5017e55f8c1SIan Lepore #ifdef INVARIANTS
5027e55f8c1SIan Lepore pcb->pcb_onfault = onfault;
5037e55f8c1SIan Lepore #endif
5047e55f8c1SIan Lepore
5057e55f8c1SIan Lepore if (__predict_true(rv == KERN_SUCCESS))
5067e55f8c1SIan Lepore goto out;
5077e55f8c1SIan Lepore nogo:
5087e55f8c1SIan Lepore if (!usermode) {
5097e55f8c1SIan Lepore if (td->td_intr_nesting_level == 0 &&
5107e55f8c1SIan Lepore pcb->pcb_onfault != NULL) {
5117e55f8c1SIan Lepore tf->tf_r0 = rv;
5127e55f8c1SIan Lepore tf->tf_pc = (int)pcb->pcb_onfault;
5137e55f8c1SIan Lepore return;
5147e55f8c1SIan Lepore }
5157e55f8c1SIan Lepore CTR2(KTR_TRAP, "%s: vm_fault() failed with %d", __func__, rv);
5167e55f8c1SIan Lepore abort_fatal(tf, idx, fsr, far, prefetch, td, &ksig);
5177e55f8c1SIan Lepore return;
5187e55f8c1SIan Lepore }
5197e55f8c1SIan Lepore
5207e55f8c1SIan Lepore ksig.addr = far;
5217e55f8c1SIan Lepore
5227e55f8c1SIan Lepore do_trapsignal:
52391371fbcSJohn Baldwin call_trapsignal(td, ksig.sig, ksig.code, ksig.addr, idx);
5247e55f8c1SIan Lepore out:
5257e55f8c1SIan Lepore if (usermode)
5267e55f8c1SIan Lepore userret(td, tf);
5277e55f8c1SIan Lepore }
5287e55f8c1SIan Lepore
5297e55f8c1SIan Lepore /*
5307e55f8c1SIan Lepore * abort_fatal() handles the following data aborts:
53136fb9d5fSSvatopluk Kraus *
5327e55f8c1SIan Lepore * FAULT_DEBUG - Debug Event
5337e55f8c1SIan Lepore * FAULT_ACCESS_xx - Acces Bit
5347e55f8c1SIan Lepore * FAULT_EA_PREC - Precise External Abort
5357e55f8c1SIan Lepore * FAULT_DOMAIN_xx - Domain Fault
5367e55f8c1SIan Lepore * FAULT_EA_TRAN_xx - External Translation Abort
5377e55f8c1SIan Lepore * FAULT_EA_IMPREC - Imprecise External Abort
5387e55f8c1SIan Lepore * + all undefined codes for ABORT
5397e55f8c1SIan Lepore *
5407e55f8c1SIan Lepore * We should never see these on a properly functioning system.
5417e55f8c1SIan Lepore *
5427e55f8c1SIan Lepore * This function is also called by the other handlers if they
5437e55f8c1SIan Lepore * detect a fatal problem.
5447e55f8c1SIan Lepore *
5457e55f8c1SIan Lepore * Note: If 'l' is NULL, we assume we're dealing with a prefetch abort.
5467e55f8c1SIan Lepore */
5477e55f8c1SIan Lepore static int
abort_fatal(struct trapframe * tf,u_int idx,u_int fsr,u_int far,u_int prefetch,struct thread * td,struct ksig * ksig)54836fb9d5fSSvatopluk Kraus abort_fatal(struct trapframe *tf, u_int idx, u_int fsr, u_int far,
54936fb9d5fSSvatopluk Kraus u_int prefetch, struct thread *td, struct ksig *ksig)
5507e55f8c1SIan Lepore {
551bee75f52SSvatopluk Kraus bool usermode;
5527e55f8c1SIan Lepore const char *mode;
5537e55f8c1SIan Lepore const char *rw_mode;
55465d1a4cfSMitchell Horne #ifdef KDB
55565d1a4cfSMitchell Horne bool handled;
55665d1a4cfSMitchell Horne #endif
5577e55f8c1SIan Lepore
5587e55f8c1SIan Lepore usermode = TRAPF_USERMODE(tf);
559c2188153SAndrew Turner #ifdef KDTRACE_HOOKS
560c2188153SAndrew Turner if (!usermode) {
561c2188153SAndrew Turner if (dtrace_trap_func != NULL && (*dtrace_trap_func)(tf, far))
562c2188153SAndrew Turner return (0);
563c2188153SAndrew Turner }
564c2188153SAndrew Turner #endif
565c2188153SAndrew Turner
5667e55f8c1SIan Lepore mode = usermode ? "user" : "kernel";
5677e55f8c1SIan Lepore rw_mode = fsr & FSR_WNR ? "write" : "read";
5687e55f8c1SIan Lepore disable_interrupts(PSR_I|PSR_F);
5697e55f8c1SIan Lepore
5707e55f8c1SIan Lepore if (td != NULL) {
5717e55f8c1SIan Lepore printf("Fatal %s mode data abort: '%s' on %s\n", mode,
5727e55f8c1SIan Lepore aborts[idx].desc, rw_mode);
5737e55f8c1SIan Lepore printf("trapframe: %p\nFSR=%08x, FAR=", tf, fsr);
5747e55f8c1SIan Lepore if (idx != FAULT_EA_IMPREC)
5757e55f8c1SIan Lepore printf("%08x, ", far);
5767e55f8c1SIan Lepore else
5777e55f8c1SIan Lepore printf("Invalid, ");
5787e55f8c1SIan Lepore printf("spsr=%08x\n", tf->tf_spsr);
5797e55f8c1SIan Lepore } else {
5807e55f8c1SIan Lepore printf("Fatal %s mode prefetch abort at 0x%08x\n",
5817e55f8c1SIan Lepore mode, tf->tf_pc);
5827e55f8c1SIan Lepore printf("trapframe: %p, spsr=%08x\n", tf, tf->tf_spsr);
5837e55f8c1SIan Lepore }
5847e55f8c1SIan Lepore
5857e55f8c1SIan Lepore printf("r0 =%08x, r1 =%08x, r2 =%08x, r3 =%08x\n",
5867e55f8c1SIan Lepore tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3);
5877e55f8c1SIan Lepore printf("r4 =%08x, r5 =%08x, r6 =%08x, r7 =%08x\n",
5887e55f8c1SIan Lepore tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7);
5897e55f8c1SIan Lepore printf("r8 =%08x, r9 =%08x, r10=%08x, r11=%08x\n",
5907e55f8c1SIan Lepore tf->tf_r8, tf->tf_r9, tf->tf_r10, tf->tf_r11);
5917e55f8c1SIan Lepore printf("r12=%08x, ", tf->tf_r12);
5927e55f8c1SIan Lepore
5937e55f8c1SIan Lepore if (usermode)
5947e55f8c1SIan Lepore printf("usp=%08x, ulr=%08x",
5957e55f8c1SIan Lepore tf->tf_usr_sp, tf->tf_usr_lr);
5967e55f8c1SIan Lepore else
5977e55f8c1SIan Lepore printf("ssp=%08x, slr=%08x",
5987e55f8c1SIan Lepore tf->tf_svc_sp, tf->tf_svc_lr);
5997e55f8c1SIan Lepore printf(", pc =%08x\n\n", tf->tf_pc);
6007e55f8c1SIan Lepore
6017e55f8c1SIan Lepore #ifdef KDB
602b317cfd4SJohn Baldwin if (debugger_on_trap) {
603c9c4d38aSAndriy Gapon kdb_why = KDB_WHY_TRAP;
60465d1a4cfSMitchell Horne handled = kdb_trap(fsr, 0, tf);
605c9c4d38aSAndriy Gapon kdb_why = KDB_WHY_UNSET;
60665d1a4cfSMitchell Horne if (handled)
60765d1a4cfSMitchell Horne return (0);
608c9c4d38aSAndriy Gapon }
6097e55f8c1SIan Lepore #endif
6107e55f8c1SIan Lepore panic("Fatal abort");
6117e55f8c1SIan Lepore /*NOTREACHED*/
6127e55f8c1SIan Lepore }
6137e55f8c1SIan Lepore
6147e55f8c1SIan Lepore /*
6157e55f8c1SIan Lepore * abort_align() handles the following data abort:
6167e55f8c1SIan Lepore *
6177e55f8c1SIan Lepore * FAULT_ALIGN - Alignment fault
6187e55f8c1SIan Lepore *
61936fb9d5fSSvatopluk Kraus * Everything should be aligned in kernel with exception of user to kernel
62036fb9d5fSSvatopluk Kraus * and vice versa data copying, so if pcb_onfault is not set, it's fatal.
62136fb9d5fSSvatopluk Kraus * We generate signal in case of abort from user mode.
6227e55f8c1SIan Lepore */
6237e55f8c1SIan Lepore static int
abort_align(struct trapframe * tf,u_int idx,u_int fsr,u_int far,u_int prefetch,struct thread * td,struct ksig * ksig)62436fb9d5fSSvatopluk Kraus abort_align(struct trapframe *tf, u_int idx, u_int fsr, u_int far,
62536fb9d5fSSvatopluk Kraus u_int prefetch, struct thread *td, struct ksig *ksig)
6267e55f8c1SIan Lepore {
627bee75f52SSvatopluk Kraus bool usermode;
6287e55f8c1SIan Lepore
6297e55f8c1SIan Lepore usermode = TRAPF_USERMODE(tf);
6307e55f8c1SIan Lepore if (!usermode) {
6317e55f8c1SIan Lepore if (td->td_intr_nesting_level == 0 && td != NULL &&
6327e55f8c1SIan Lepore td->td_pcb->pcb_onfault != NULL) {
6339a54871fSSvatopluk Kraus tf->tf_r0 = EFAULT;
6347e55f8c1SIan Lepore tf->tf_pc = (int)td->td_pcb->pcb_onfault;
6357e55f8c1SIan Lepore return (0);
6367e55f8c1SIan Lepore }
6377e55f8c1SIan Lepore abort_fatal(tf, idx, fsr, far, prefetch, td, ksig);
6387e55f8c1SIan Lepore }
6397e55f8c1SIan Lepore /* Deliver a bus error signal to the process */
6409a54871fSSvatopluk Kraus ksig->code = BUS_ADRALN;
6417e55f8c1SIan Lepore ksig->sig = SIGBUS;
6427e55f8c1SIan Lepore ksig->addr = far;
6437e55f8c1SIan Lepore return (1);
6447e55f8c1SIan Lepore }
6457e55f8c1SIan Lepore
6467e55f8c1SIan Lepore /*
6477e55f8c1SIan Lepore * abort_icache() handles the following data abort:
6487e55f8c1SIan Lepore *
6497e55f8c1SIan Lepore * FAULT_ICACHE - Instruction cache maintenance
6507e55f8c1SIan Lepore *
6517e55f8c1SIan Lepore * According to manual, FAULT_ICACHE is translation fault during cache
6527e55f8c1SIan Lepore * maintenance operation. In fact, no cache maintenance operation on
6537e55f8c1SIan Lepore * not mapped virtual addresses should be called. As cache maintenance
6545bdf58e1SGordon Bergling * operation (except DMB, DSB, and Flush Prefetch Buffer) are privileged,
6557e55f8c1SIan Lepore * the abort is concider as fatal for now. However, all the matter with
6567e55f8c1SIan Lepore * cache maintenance operation on virtual addresses could be really complex
6577e55f8c1SIan Lepore * and fuzzy in SMP case, so maybe in future standard fault mechanism
6587e55f8c1SIan Lepore * should be held here including vm_fault() calling.
6597e55f8c1SIan Lepore */
6607e55f8c1SIan Lepore static int
abort_icache(struct trapframe * tf,u_int idx,u_int fsr,u_int far,u_int prefetch,struct thread * td,struct ksig * ksig)66136fb9d5fSSvatopluk Kraus abort_icache(struct trapframe *tf, u_int idx, u_int fsr, u_int far,
66236fb9d5fSSvatopluk Kraus u_int prefetch, struct thread *td, struct ksig *ksig)
6637e55f8c1SIan Lepore {
66436fb9d5fSSvatopluk Kraus
6657e55f8c1SIan Lepore abort_fatal(tf, idx, fsr, far, prefetch, td, ksig);
6667e55f8c1SIan Lepore return(0);
6677e55f8c1SIan Lepore }
668