1e5acd89cSAndrew Turner /*- 2e5acd89cSAndrew Turner * Copyright (c) 2014 Andrew Turner 3e5acd89cSAndrew Turner * All rights reserved. 4e5acd89cSAndrew Turner * 5e5acd89cSAndrew Turner * Redistribution and use in source and binary forms, with or without 6e5acd89cSAndrew Turner * modification, are permitted provided that the following conditions 7e5acd89cSAndrew Turner * are met: 8e5acd89cSAndrew Turner * 1. Redistributions of source code must retain the above copyright 9e5acd89cSAndrew Turner * notice, this list of conditions and the following disclaimer. 10e5acd89cSAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright 11e5acd89cSAndrew Turner * notice, this list of conditions and the following disclaimer in the 12e5acd89cSAndrew Turner * documentation and/or other materials provided with the distribution. 13e5acd89cSAndrew Turner * 14e5acd89cSAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15e5acd89cSAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16e5acd89cSAndrew Turner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17e5acd89cSAndrew Turner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18e5acd89cSAndrew Turner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19e5acd89cSAndrew Turner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20e5acd89cSAndrew Turner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21e5acd89cSAndrew Turner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22e5acd89cSAndrew Turner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23e5acd89cSAndrew Turner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24e5acd89cSAndrew Turner * SUCH DAMAGE. 25e5acd89cSAndrew Turner * 26e5acd89cSAndrew Turner */ 27e5acd89cSAndrew Turner 28e5acd89cSAndrew Turner #include <sys/cdefs.h> 29e5acd89cSAndrew Turner __FBSDID("$FreeBSD$"); 30e5acd89cSAndrew Turner 31e5acd89cSAndrew Turner #include <sys/param.h> 32e5acd89cSAndrew Turner #include <sys/systm.h> 33e5acd89cSAndrew Turner #include <sys/kernel.h> 34e5acd89cSAndrew Turner #include <sys/lock.h> 35e5acd89cSAndrew Turner #include <sys/mutex.h> 36e5acd89cSAndrew Turner #include <sys/pioctl.h> 37e5acd89cSAndrew Turner #include <sys/proc.h> 38e5acd89cSAndrew Turner #include <sys/ptrace.h> 39e5acd89cSAndrew Turner #include <sys/syscall.h> 40e5acd89cSAndrew Turner #include <sys/sysent.h> 41e5acd89cSAndrew Turner #ifdef KDB 42e5acd89cSAndrew Turner #include <sys/kdb.h> 43e5acd89cSAndrew Turner #endif 44e5acd89cSAndrew Turner 45e5acd89cSAndrew Turner #include <vm/vm.h> 46e5acd89cSAndrew Turner #include <vm/pmap.h> 47e5acd89cSAndrew Turner #include <vm/vm_kern.h> 48e5acd89cSAndrew Turner #include <vm/vm_map.h> 49cb02f6b9SAndrew Turner #include <vm/vm_param.h> 50e5acd89cSAndrew Turner #include <vm/vm_extern.h> 51e5acd89cSAndrew Turner 52e5acd89cSAndrew Turner #include <machine/frame.h> 53e5acd89cSAndrew Turner #include <machine/pcb.h> 54e5acd89cSAndrew Turner #include <machine/pcpu.h> 55e5acd89cSAndrew Turner 56b78ee15eSRuslan Bukin #ifdef KDTRACE_HOOKS 57b78ee15eSRuslan Bukin #include <sys/dtrace_bsd.h> 58b78ee15eSRuslan Bukin #endif 59b78ee15eSRuslan Bukin 60e5acd89cSAndrew Turner #ifdef VFP 61e5acd89cSAndrew Turner #include <machine/vfp.h> 62e5acd89cSAndrew Turner #endif 63e5acd89cSAndrew Turner 64e5acd89cSAndrew Turner #ifdef KDB 65e5acd89cSAndrew Turner #include <machine/db_machdep.h> 66e5acd89cSAndrew Turner #endif 67e5acd89cSAndrew Turner 68e5acd89cSAndrew Turner #ifdef DDB 69e5acd89cSAndrew Turner #include <ddb/db_output.h> 70e5acd89cSAndrew Turner #endif 71e5acd89cSAndrew Turner 729d77aa2aSAndrew Turner extern register_t fsu_intr_fault; 73e5acd89cSAndrew Turner 74e5acd89cSAndrew Turner /* Called from exception.S */ 75d7635c7aSAndrew Turner void do_el1h_sync(struct thread *, struct trapframe *); 76d7635c7aSAndrew Turner void do_el0_sync(struct thread *, struct trapframe *); 77e5acd89cSAndrew Turner void do_el0_error(struct trapframe *); 780510aedcSKonstantin Belousov static void print_registers(struct trapframe *frame); 79e5acd89cSAndrew Turner 80b78ee15eSRuslan Bukin int (*dtrace_invop_jump_addr)(struct trapframe *); 81b78ee15eSRuslan Bukin 82e5acd89cSAndrew Turner static __inline void 83cb02f6b9SAndrew Turner call_trapsignal(struct thread *td, int sig, int code, void *addr) 84e5acd89cSAndrew Turner { 85e5acd89cSAndrew Turner ksiginfo_t ksi; 86e5acd89cSAndrew Turner 87e5acd89cSAndrew Turner ksiginfo_init_trap(&ksi); 88e5acd89cSAndrew Turner ksi.ksi_signo = sig; 89cb02f6b9SAndrew Turner ksi.ksi_code = code; 90cb02f6b9SAndrew Turner ksi.ksi_addr = addr; 91e5acd89cSAndrew Turner trapsignal(td, &ksi); 92e5acd89cSAndrew Turner } 93e5acd89cSAndrew Turner 94e5acd89cSAndrew Turner int 952d88da2fSKonstantin Belousov cpu_fetch_syscall_args(struct thread *td) 96e5acd89cSAndrew Turner { 97e5acd89cSAndrew Turner struct proc *p; 98e5acd89cSAndrew Turner register_t *ap; 992d88da2fSKonstantin Belousov struct syscall_args *sa; 100e5acd89cSAndrew Turner int nap; 101e5acd89cSAndrew Turner 102e5acd89cSAndrew Turner nap = 8; 103e5acd89cSAndrew Turner p = td->td_proc; 104e5acd89cSAndrew Turner ap = td->td_frame->tf_x; 1052d88da2fSKonstantin Belousov sa = &td->td_sa; 106e5acd89cSAndrew Turner 107e5acd89cSAndrew Turner sa->code = td->td_frame->tf_x[8]; 108e5acd89cSAndrew Turner 109e5acd89cSAndrew Turner if (sa->code == SYS_syscall || sa->code == SYS___syscall) { 110e5acd89cSAndrew Turner sa->code = *ap++; 111e5acd89cSAndrew Turner nap--; 112e5acd89cSAndrew Turner } 113e5acd89cSAndrew Turner 114e5acd89cSAndrew Turner if (p->p_sysent->sv_mask) 115e5acd89cSAndrew Turner sa->code &= p->p_sysent->sv_mask; 116e5acd89cSAndrew Turner if (sa->code >= p->p_sysent->sv_size) 117e5acd89cSAndrew Turner sa->callp = &p->p_sysent->sv_table[0]; 118e5acd89cSAndrew Turner else 119e5acd89cSAndrew Turner sa->callp = &p->p_sysent->sv_table[sa->code]; 120e5acd89cSAndrew Turner 121e5acd89cSAndrew Turner sa->narg = sa->callp->sy_narg; 122e5acd89cSAndrew Turner memcpy(sa->args, ap, nap * sizeof(register_t)); 123e5acd89cSAndrew Turner if (sa->narg > nap) 1246bc3fe5fSPedro F. Giffuni panic("ARM64TODO: Could we have more than 8 args?"); 125e5acd89cSAndrew Turner 126e5acd89cSAndrew Turner td->td_retval[0] = 0; 127e5acd89cSAndrew Turner td->td_retval[1] = 0; 128e5acd89cSAndrew Turner 129e5acd89cSAndrew Turner return (0); 130e5acd89cSAndrew Turner } 131e5acd89cSAndrew Turner 132e5acd89cSAndrew Turner #include "../../kern/subr_syscall.c" 133e5acd89cSAndrew Turner 134e5acd89cSAndrew Turner static void 135d7635c7aSAndrew Turner svc_handler(struct thread *td, struct trapframe *frame) 136e5acd89cSAndrew Turner { 137e5acd89cSAndrew Turner int error; 138e5acd89cSAndrew Turner 13952a680fbSAndrew Turner if ((frame->tf_esr & ESR_ELx_ISS_MASK) == 0) { 1402d88da2fSKonstantin Belousov error = syscallenter(td); 1412d88da2fSKonstantin Belousov syscallret(td, error); 14252a680fbSAndrew Turner } else { 14352a680fbSAndrew Turner call_trapsignal(td, SIGILL, ILL_ILLOPN, (void *)frame->tf_elr); 14452a680fbSAndrew Turner userret(td, frame); 14552a680fbSAndrew Turner } 146e5acd89cSAndrew Turner } 147e5acd89cSAndrew Turner 148e5acd89cSAndrew Turner static void 149d7635c7aSAndrew Turner data_abort(struct thread *td, struct trapframe *frame, uint64_t esr, 150d7635c7aSAndrew Turner uint64_t far, int lower) 151e5acd89cSAndrew Turner { 152e5acd89cSAndrew Turner struct vm_map *map; 153e5acd89cSAndrew Turner struct proc *p; 154e5acd89cSAndrew Turner struct pcb *pcb; 155e5acd89cSAndrew Turner vm_prot_t ftype; 156e5acd89cSAndrew Turner vm_offset_t va; 157cb02f6b9SAndrew Turner int error, sig, ucode; 158e5acd89cSAndrew Turner 1596ced3789SKonstantin Belousov /* 1606ced3789SKonstantin Belousov * According to the ARMv8-A rev. A.g, B2.10.5 "Load-Exclusive 1616ced3789SKonstantin Belousov * and Store-Exclusive instruction usage restrictions", state 1626ced3789SKonstantin Belousov * of the exclusive monitors after data abort exception is unknown. 1636ced3789SKonstantin Belousov */ 1646ced3789SKonstantin Belousov clrex(); 1656ced3789SKonstantin Belousov 1668f746773SAndrew Turner #ifdef KDB 1678f746773SAndrew Turner if (kdb_active) { 1688f746773SAndrew Turner kdb_reenter(); 1698f746773SAndrew Turner return; 1708f746773SAndrew Turner } 1718f746773SAndrew Turner #endif 1728f746773SAndrew Turner 173e5acd89cSAndrew Turner pcb = td->td_pcb; 174e5acd89cSAndrew Turner 175e5acd89cSAndrew Turner /* 176e5acd89cSAndrew Turner * Special case for fuswintr and suswintr. These can't sleep so 177e5acd89cSAndrew Turner * handle them early on in the trap handler. 178e5acd89cSAndrew Turner */ 1799d77aa2aSAndrew Turner if (__predict_false(pcb->pcb_onfault == (vm_offset_t)&fsu_intr_fault)) { 180e5acd89cSAndrew Turner frame->tf_elr = pcb->pcb_onfault; 181e5acd89cSAndrew Turner return; 182e5acd89cSAndrew Turner } 183e5acd89cSAndrew Turner 1840510aedcSKonstantin Belousov p = td->td_proc; 185e5acd89cSAndrew Turner if (lower) 1860510aedcSKonstantin Belousov map = &p->p_vmspace->vm_map; 187e5acd89cSAndrew Turner else { 188e5acd89cSAndrew Turner /* The top bit tells us which range to use */ 18971cb533eSAndrew Turner if (far >= VM_MAXUSER_ADDRESS) { 190e5acd89cSAndrew Turner map = kernel_map; 1911d479540SAndrew Turner } else { 1920510aedcSKonstantin Belousov map = &p->p_vmspace->vm_map; 1931d479540SAndrew Turner if (map == NULL) 1941d479540SAndrew Turner map = kernel_map; 1951d479540SAndrew Turner } 196e5acd89cSAndrew Turner } 197e5acd89cSAndrew Turner 198510a3f1bSAndrew Turner if (pmap_fault(map->pmap, esr, far) == KERN_SUCCESS) 199510a3f1bSAndrew Turner return; 200510a3f1bSAndrew Turner 201510a3f1bSAndrew Turner KASSERT(td->td_md.md_spinlock_count == 0, 202510a3f1bSAndrew Turner ("data abort with spinlock held")); 203510a3f1bSAndrew Turner if (td->td_critnest != 0 || WITNESS_CHECK(WARN_SLEEPOK | 204510a3f1bSAndrew Turner WARN_GIANTOK, NULL, "Kernel page fault") != 0) { 205510a3f1bSAndrew Turner print_registers(frame); 206510a3f1bSAndrew Turner printf(" far: %16lx\n", far); 207510a3f1bSAndrew Turner printf(" esr: %.8lx\n", esr); 208510a3f1bSAndrew Turner panic("data abort in critical section or under mutex"); 209510a3f1bSAndrew Turner } 210510a3f1bSAndrew Turner 211e5acd89cSAndrew Turner va = trunc_page(far); 212e5acd89cSAndrew Turner ftype = ((esr >> 6) & 1) ? VM_PROT_READ | VM_PROT_WRITE : VM_PROT_READ; 213e5acd89cSAndrew Turner 2141fa67124SKonstantin Belousov /* Fault in the page. */ 215e5acd89cSAndrew Turner error = vm_fault(map, va, ftype, VM_FAULT_NORMAL); 216cb02f6b9SAndrew Turner if (error != KERN_SUCCESS) { 217e5acd89cSAndrew Turner if (lower) { 218e5acd89cSAndrew Turner sig = SIGSEGV; 219cb02f6b9SAndrew Turner if (error == KERN_PROTECTION_FAILURE) 220cb02f6b9SAndrew Turner ucode = SEGV_ACCERR; 221cb02f6b9SAndrew Turner else 222cb02f6b9SAndrew Turner ucode = SEGV_MAPERR; 223cb02f6b9SAndrew Turner call_trapsignal(td, sig, ucode, (void *)far); 224e5acd89cSAndrew Turner } else { 225e5acd89cSAndrew Turner if (td->td_intr_nesting_level == 0 && 226e5acd89cSAndrew Turner pcb->pcb_onfault != 0) { 227e5acd89cSAndrew Turner frame->tf_x[0] = error; 228e5acd89cSAndrew Turner frame->tf_elr = pcb->pcb_onfault; 229e5acd89cSAndrew Turner return; 230e5acd89cSAndrew Turner } 2311e888d78SAndrew Turner 2321e888d78SAndrew Turner printf("Fatal data abort:\n"); 2331e888d78SAndrew Turner print_registers(frame); 2341e888d78SAndrew Turner printf(" far: %16lx\n", far); 2351e888d78SAndrew Turner printf(" esr: %.8lx\n", esr); 2361e888d78SAndrew Turner 2378f746773SAndrew Turner #ifdef KDB 2388f746773SAndrew Turner if (debugger_on_panic || kdb_active) 2398f746773SAndrew Turner if (kdb_trap(ESR_ELx_EXCEPTION(esr), 0, frame)) 2408f746773SAndrew Turner return; 2418f746773SAndrew Turner #endif 242e5acd89cSAndrew Turner panic("vm_fault failed: %lx", frame->tf_elr); 243e5acd89cSAndrew Turner } 244e5acd89cSAndrew Turner } 245e5acd89cSAndrew Turner 246e5acd89cSAndrew Turner if (lower) 247e5acd89cSAndrew Turner userret(td, frame); 248e5acd89cSAndrew Turner } 249e5acd89cSAndrew Turner 250ccd285e7SEd Maste static void 251ccd285e7SEd Maste print_registers(struct trapframe *frame) 252ccd285e7SEd Maste { 253ccd285e7SEd Maste u_int reg; 254ccd285e7SEd Maste 2552e620e70SAndrew Turner for (reg = 0; reg < nitems(frame->tf_x); reg++) { 256ccd285e7SEd Maste printf(" %sx%d: %16lx\n", (reg < 10) ? " " : "", reg, 257ccd285e7SEd Maste frame->tf_x[reg]); 258ccd285e7SEd Maste } 259ccd285e7SEd Maste printf(" sp: %16lx\n", frame->tf_sp); 260ccd285e7SEd Maste printf(" lr: %16lx\n", frame->tf_lr); 261ccd285e7SEd Maste printf(" elr: %16lx\n", frame->tf_elr); 262f17e4f07SAndrew Turner printf("spsr: %8x\n", frame->tf_spsr); 263ccd285e7SEd Maste } 264ccd285e7SEd Maste 265e5acd89cSAndrew Turner void 266d7635c7aSAndrew Turner do_el1h_sync(struct thread *td, struct trapframe *frame) 267e5acd89cSAndrew Turner { 268e5acd89cSAndrew Turner uint32_t exception; 2690510aedcSKonstantin Belousov uint64_t esr, far; 270e5acd89cSAndrew Turner 271e5acd89cSAndrew Turner /* Read the esr register to get the exception details */ 272f17e4f07SAndrew Turner esr = frame->tf_esr; 273e5acd89cSAndrew Turner exception = ESR_ELx_EXCEPTION(esr); 274e5acd89cSAndrew Turner 275b78ee15eSRuslan Bukin #ifdef KDTRACE_HOOKS 276b78ee15eSRuslan Bukin if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, exception)) 277b78ee15eSRuslan Bukin return; 278b78ee15eSRuslan Bukin #endif 279b78ee15eSRuslan Bukin 2803ad7e84eSAndrew Turner CTR4(KTR_TRAP, 281d7635c7aSAndrew Turner "do_el1_sync: curthread: %p, esr %lx, elr: %lx, frame: %p", td, 282d7635c7aSAndrew Turner esr, frame->tf_elr, frame); 2833ad7e84eSAndrew Turner 284e5acd89cSAndrew Turner switch(exception) { 285e5acd89cSAndrew Turner case EXCP_FP_SIMD: 286e5acd89cSAndrew Turner case EXCP_TRAP_FP: 2876ed982a2SAndrew Turner #ifdef VFP 288d7635c7aSAndrew Turner if ((td->td_pcb->pcb_fpflags & PCB_FP_KERN) != 0) { 2896ed982a2SAndrew Turner vfp_restore_state(); 2906ed982a2SAndrew Turner } else 2916ed982a2SAndrew Turner #endif 2926ed982a2SAndrew Turner { 293ccd285e7SEd Maste print_registers(frame); 2941e888d78SAndrew Turner printf(" esr: %.8lx\n", esr); 295e5acd89cSAndrew Turner panic("VFP exception in the kernel"); 2966ed982a2SAndrew Turner } 2976ed982a2SAndrew Turner break; 298d953ec32SAndrew Turner case EXCP_INSN_ABORT: 299e5acd89cSAndrew Turner case EXCP_DATA_ABORT: 3000510aedcSKonstantin Belousov far = READ_SPECIALREG(far_el1); 3010510aedcSKonstantin Belousov intr_enable(); 302d7635c7aSAndrew Turner data_abort(td, frame, esr, far, 0); 303e5acd89cSAndrew Turner break; 304e5acd89cSAndrew Turner case EXCP_BRK: 305b78ee15eSRuslan Bukin #ifdef KDTRACE_HOOKS 306b78ee15eSRuslan Bukin if ((esr & ESR_ELx_ISS_MASK) == 0x40d && \ 307b78ee15eSRuslan Bukin dtrace_invop_jump_addr != 0) { 308b78ee15eSRuslan Bukin dtrace_invop_jump_addr(frame); 309b78ee15eSRuslan Bukin break; 310b78ee15eSRuslan Bukin } 311b78ee15eSRuslan Bukin #endif 3128f746773SAndrew Turner /* FALLTHROUGH */ 313e5acd89cSAndrew Turner case EXCP_WATCHPT_EL1: 314e5acd89cSAndrew Turner case EXCP_SOFTSTP_EL1: 315e5acd89cSAndrew Turner #ifdef KDB 316e5acd89cSAndrew Turner kdb_trap(exception, 0, frame); 317e5acd89cSAndrew Turner #else 318e5acd89cSAndrew Turner panic("No debugger in kernel.\n"); 319e5acd89cSAndrew Turner #endif 320e5acd89cSAndrew Turner break; 321e5acd89cSAndrew Turner default: 322ccd285e7SEd Maste print_registers(frame); 323e5acd89cSAndrew Turner panic("Unknown kernel exception %x esr_el1 %lx\n", exception, 324e5acd89cSAndrew Turner esr); 325e5acd89cSAndrew Turner } 326e5acd89cSAndrew Turner } 327e5acd89cSAndrew Turner 328ccd285e7SEd Maste /* 3295a060174SEd Maste * The attempted execution of an instruction bit pattern that has no allocated 3308d5bb774SEd Maste * instruction results in an exception with an unknown reason. 331ccd285e7SEd Maste */ 332ccd285e7SEd Maste static void 333add8a9c2SAndrew Turner el0_excp_unknown(struct trapframe *frame, uint64_t far) 334ccd285e7SEd Maste { 335ccd285e7SEd Maste struct thread *td; 336ccd285e7SEd Maste 337ccd285e7SEd Maste td = curthread; 338ccd285e7SEd Maste call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)far); 339ccd285e7SEd Maste userret(td, frame); 340ccd285e7SEd Maste } 341ccd285e7SEd Maste 342e5acd89cSAndrew Turner void 343d7635c7aSAndrew Turner do_el0_sync(struct thread *td, struct trapframe *frame) 344e5acd89cSAndrew Turner { 345e5acd89cSAndrew Turner uint32_t exception; 3460510aedcSKonstantin Belousov uint64_t esr, far; 347e5acd89cSAndrew Turner 348e5acd89cSAndrew Turner /* Check we have a sane environment when entering from userland */ 349e5acd89cSAndrew Turner KASSERT((uintptr_t)get_pcpu() >= VM_MIN_KERNEL_ADDRESS, 350e5acd89cSAndrew Turner ("Invalid pcpu address from userland: %p (tpidr %lx)", 351e5acd89cSAndrew Turner get_pcpu(), READ_SPECIALREG(tpidr_el1))); 352e5acd89cSAndrew Turner 353f17e4f07SAndrew Turner esr = frame->tf_esr; 354e5acd89cSAndrew Turner exception = ESR_ELx_EXCEPTION(esr); 3550510aedcSKonstantin Belousov switch (exception) { 356add8a9c2SAndrew Turner case EXCP_UNKNOWN: 3570510aedcSKonstantin Belousov case EXCP_INSN_ABORT_L: 3580510aedcSKonstantin Belousov case EXCP_DATA_ABORT_L: 3590510aedcSKonstantin Belousov case EXCP_DATA_ABORT: 3600510aedcSKonstantin Belousov far = READ_SPECIALREG(far_el1); 3610510aedcSKonstantin Belousov } 3620510aedcSKonstantin Belousov intr_enable(); 363e5acd89cSAndrew Turner 3643ad7e84eSAndrew Turner CTR4(KTR_TRAP, 365d7635c7aSAndrew Turner "do_el0_sync: curthread: %p, esr %lx, elr: %lx, frame: %p", td, esr, 366d7635c7aSAndrew Turner frame->tf_elr, frame); 3673ad7e84eSAndrew Turner 368e5acd89cSAndrew Turner switch(exception) { 369e5acd89cSAndrew Turner case EXCP_FP_SIMD: 370e5acd89cSAndrew Turner case EXCP_TRAP_FP: 371e5acd89cSAndrew Turner #ifdef VFP 372e5acd89cSAndrew Turner vfp_restore_state(); 373e5acd89cSAndrew Turner #else 374e5acd89cSAndrew Turner panic("VFP exception in userland"); 375e5acd89cSAndrew Turner #endif 376e5acd89cSAndrew Turner break; 377e5acd89cSAndrew Turner case EXCP_SVC: 378d7635c7aSAndrew Turner svc_handler(td, frame); 379e5acd89cSAndrew Turner break; 380e5acd89cSAndrew Turner case EXCP_INSN_ABORT_L: 381e5acd89cSAndrew Turner case EXCP_DATA_ABORT_L: 3824cbca608SZbigniew Bodek case EXCP_DATA_ABORT: 383d7635c7aSAndrew Turner data_abort(td, frame, esr, far, 1); 384e5acd89cSAndrew Turner break; 385ccd285e7SEd Maste case EXCP_UNKNOWN: 386add8a9c2SAndrew Turner el0_excp_unknown(frame, far); 387ccd285e7SEd Maste break; 388729ac0eeSAndrew Turner case EXCP_SP_ALIGN: 389729ac0eeSAndrew Turner call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_sp); 390729ac0eeSAndrew Turner userret(td, frame); 391729ac0eeSAndrew Turner break; 3928bdcc096SAndrew Turner case EXCP_PC_ALIGN: 3938bdcc096SAndrew Turner call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr); 3948bdcc096SAndrew Turner userret(td, frame); 3958bdcc096SAndrew Turner break; 3960987c184SAndrew Turner case EXCP_BRK: 3970987c184SAndrew Turner call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_elr); 3980987c184SAndrew Turner userret(td, frame); 3990987c184SAndrew Turner break; 40013db6962SAndrew Turner case EXCP_MSR: 40113db6962SAndrew Turner call_trapsignal(td, SIGILL, ILL_PRVOPC, (void *)frame->tf_elr); 40213db6962SAndrew Turner userret(td, frame); 40313db6962SAndrew Turner break; 40487e19994SAndrew Turner case EXCP_SOFTSTP_EL0: 40587e19994SAndrew Turner td->td_frame->tf_spsr &= ~PSR_SS; 40687e19994SAndrew Turner td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; 40787e19994SAndrew Turner WRITE_SPECIALREG(MDSCR_EL1, 40887e19994SAndrew Turner READ_SPECIALREG(MDSCR_EL1) & ~DBG_MDSCR_SS); 40987e19994SAndrew Turner call_trapsignal(td, SIGTRAP, TRAP_TRACE, 41087e19994SAndrew Turner (void *)frame->tf_elr); 41187e19994SAndrew Turner userret(td, frame); 41287e19994SAndrew Turner break; 413e5acd89cSAndrew Turner default: 414e0c6c1d1SAndrew Turner call_trapsignal(td, SIGBUS, BUS_OBJERR, (void *)frame->tf_elr); 415e0c6c1d1SAndrew Turner userret(td, frame); 416e0c6c1d1SAndrew Turner break; 417e5acd89cSAndrew Turner } 4184c247b97SAndrew Turner 419d7635c7aSAndrew Turner KASSERT((td->td_pcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0, 4204c247b97SAndrew Turner ("Kernel VFP flags set while entering userspace")); 4216ed982a2SAndrew Turner KASSERT( 422d7635c7aSAndrew Turner td->td_pcb->pcb_fpusaved == &td->td_pcb->pcb_fpustate, 4236ed982a2SAndrew Turner ("Kernel VFP state in use when entering userspace")); 424e5acd89cSAndrew Turner } 425e5acd89cSAndrew Turner 426e5acd89cSAndrew Turner void 427e5acd89cSAndrew Turner do_el0_error(struct trapframe *frame) 428e5acd89cSAndrew Turner { 429e5acd89cSAndrew Turner 430c547d650SEd Maste panic("ARM64TODO: do_el0_error"); 431e5acd89cSAndrew Turner } 432e5acd89cSAndrew Turner 433