svn commit: r354174 - head/sys/arm64/arm64
Andrew Turner
andrew at FreeBSD.org
Wed Oct 30 10:42:53 UTC 2019
Author: andrew
Date: Wed Oct 30 10:42:52 2019
New Revision: 354174
URL: https://svnweb.freebsd.org/changeset/base/354174
Log:
Use an array of handlers in the data and instruction aborts
Previously we would call data_abort on all data and instruction aborts
however this is incorrect for most abort types. Move to use an array
of function pointers to allow for more handlers to be easily added.
Reviewed by: jhibbits
Sponsored by: DARPA, AFRL
Differential Revision: https://reviews.freebsd.org/D22170
Modified:
head/sys/arm64/arm64/trap.c
Modified: head/sys/arm64/arm64/trap.c
==============================================================================
--- head/sys/arm64/arm64/trap.c Wed Oct 30 10:41:10 2019 (r354173)
+++ head/sys/arm64/arm64/trap.c Wed Oct 30 10:42:52 2019 (r354174)
@@ -84,6 +84,24 @@ static void print_registers(struct trapframe *frame);
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 @@ svc_handler(struct thread *td, struct trapframe *frame
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 @@ data_abort(struct thread *td, struct trapframe *frame,
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 @@ do_el1h_sync(struct thread *td, struct trapframe *fram
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 @@ do_el1h_sync(struct thread *td, struct trapframe *fram
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 @@ do_el0_sync(struct thread *td, struct trapframe *frame
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 @@ do_el0_sync(struct thread *td, struct trapframe *frame
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))
More information about the svn-src-all
mailing list