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-head mailing list