Index: head/sys/arm64/arm64/trap.c =================================================================== --- head/sys/arm64/arm64/trap.c +++ head/sys/arm64/arm64/trap.c @@ -84,6 +84,24 @@ int (*dtrace_invop_jump_addr)(struct trapframe *); +typedef void (abort_handler)(struct thread *, struct trapframe *, uint64_t, + uint64_t, int); + +static abort_handler data_abort; + +static abort_handler *abort_handlers[] = { + [ISS_DATA_DFSC_TF_L0] = data_abort, + [ISS_DATA_DFSC_TF_L1] = data_abort, + [ISS_DATA_DFSC_TF_L2] = data_abort, + [ISS_DATA_DFSC_TF_L3] = data_abort, + [ISS_DATA_DFSC_AFF_L1] = data_abort, + [ISS_DATA_DFSC_AFF_L2] = data_abort, + [ISS_DATA_DFSC_AFF_L3] = data_abort, + [ISS_DATA_DFSC_PF_L1] = data_abort, + [ISS_DATA_DFSC_PF_L2] = data_abort, + [ISS_DATA_DFSC_PF_L3] = data_abort, +}; + static __inline void call_trapsignal(struct thread *td, int sig, int code, void *addr) { @@ -149,7 +167,7 @@ static void data_abort(struct thread *td, struct trapframe *frame, uint64_t esr, - uint64_t far, int lower, int exec) + uint64_t far, int lower) { struct vm_map *map; struct proc *p; @@ -212,11 +230,16 @@ panic("data abort in critical section or under mutex"); } - if (exec) + switch (ESR_ELx_EXCEPTION(esr)) { + case EXCP_INSN_ABORT: + case EXCP_INSN_ABORT_L: ftype = VM_PROT_EXECUTE; - else + break; + default: ftype = (esr & ISS_DATA_WnR) == 0 ? VM_PROT_READ : VM_PROT_READ | VM_PROT_WRITE; + break; + } /* Fault in the page. */ error = vm_fault_trap(map, far, ftype, VM_FAULT_NORMAL, &sig, &ucode); @@ -275,6 +298,7 @@ struct trapframe *oframe; uint32_t exception; uint64_t esr, far; + int dfsc; /* Read the esr register to get the exception details */ esr = frame->tf_esr; @@ -318,8 +342,14 @@ case EXCP_INSN_ABORT: case EXCP_DATA_ABORT: far = READ_SPECIALREG(far_el1); - data_abort(td, frame, esr, far, 0, - exception == EXCP_INSN_ABORT); + dfsc = esr & ISS_DATA_DFSC_MASK; + if (dfsc < nitems(abort_handlers) && + abort_handlers[dfsc] != NULL) + abort_handlers[dfsc](td, frame, esr, far, 0); + else + panic("Unhandled EL1 %s abort: %x", + exception == EXCP_INSN_ABORT ? "instruction" : + "data", dfsc); break; case EXCP_BRK: #ifdef KDTRACE_HOOKS @@ -365,6 +395,7 @@ pcpu_bp_harden bp_harden; uint32_t exception; uint64_t esr, far; + int dfsc; /* Check we have a sane environment when entering from userland */ KASSERT((uintptr_t)get_pcpu() >= VM_MIN_KERNEL_ADDRESS, @@ -416,8 +447,14 @@ case EXCP_INSN_ABORT_L: case EXCP_DATA_ABORT_L: case EXCP_DATA_ABORT: - data_abort(td, frame, esr, far, 1, - exception == EXCP_INSN_ABORT_L); + dfsc = esr & ISS_DATA_DFSC_MASK; + if (dfsc < nitems(abort_handlers) && + abort_handlers[dfsc] != NULL) + abort_handlers[dfsc](td, frame, esr, far, 1); + else + panic("Unhandled EL0 %s abort: %x", + exception == EXCP_INSN_ABORT_L ? "instruction" : + "data", dfsc); break; case EXCP_UNKNOWN: if (!undef_insn(0, frame))