diff options
author | andrew <andrew@FreeBSD.org> | 2016-06-22 12:05:08 +0000 |
---|---|---|
committer | andrew <andrew@FreeBSD.org> | 2016-06-22 12:05:08 +0000 |
commit | 4c327142ba2577ba04fa3df00bb2c992d4420495 (patch) | |
tree | 29f80a72041b2159d50eb800ca8a6778a4f85e2b | |
parent | 2b26f1f44b746e4ccfd50c9d1e2cd3f7ac1e3ad5 (diff) | |
download | FreeBSD-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.c | 7 |
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); |