summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandrew <andrew@FreeBSD.org>2016-06-22 12:05:08 +0000
committerandrew <andrew@FreeBSD.org>2016-06-22 12:05:08 +0000
commit4c327142ba2577ba04fa3df00bb2c992d4420495 (patch)
tree29f80a72041b2159d50eb800ca8a6778a4f85e2b
parent2b26f1f44b746e4ccfd50c9d1e2cd3f7ac1e3ad5 (diff)
downloadFreeBSD-src-4c327142ba2577ba04fa3df00bb2c992d4420495.zip
FreeBSD-src-4c327142ba2577ba04fa3df00bb2c992d4420495.tar.gz
Fix a race when the hardware has raised an exception with an unknown or
uncategorised reason. We need to read the fault address register before enabling interrupts as the interrupt handler may cause this register to change. Approved by: re (marius, kib) Obtained from: ABT Systems Ltd Sponsored by: The FreeBSD Foundation
-rw-r--r--sys/arm64/arm64/trap.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
index 1db5742..ea932ed 100644
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -313,13 +313,11 @@ do_el1h_sync(struct trapframe *frame)
* instruction results in an exception with an unknown reason.
*/
static void
-el0_excp_unknown(struct trapframe *frame)
+el0_excp_unknown(struct trapframe *frame, uint64_t far)
{
struct thread *td;
- uint64_t far;
td = curthread;
- far = READ_SPECIALREG(far_el1);
call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)far);
userret(td, frame);
}
@@ -342,6 +340,7 @@ do_el0_sync(struct trapframe *frame)
esr = READ_SPECIALREG(esr_el1);
exception = ESR_ELx_EXCEPTION(esr);
switch (exception) {
+ case EXCP_UNKNOWN:
case EXCP_INSN_ABORT_L:
case EXCP_DATA_ABORT_L:
case EXCP_DATA_ABORT:
@@ -371,7 +370,7 @@ do_el0_sync(struct trapframe *frame)
data_abort(frame, esr, far, 1);
break;
case EXCP_UNKNOWN:
- el0_excp_unknown(frame);
+ el0_excp_unknown(frame, far);
break;
case EXCP_SP_ALIGN:
call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_sp);
OpenPOWER on IntegriCloud