aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Iles <jamie@nuviainc.com>2021-05-26 13:18:44 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-06-03 16:43:25 +0100
commit6e0c60a2be30c333b06d3558a62b0f177199cbfb (patch)
tree0a52ee7cfcc3e894bf53dfc58fcf7c965d09b98d
parent0711a634355a68cd83966872e387402a8b4b048a (diff)
target/arm: fix missing exception class
The DAIF and PAC checks used raise_exception_ra to raise an exception and unwind CPU state but raise_exception_ra is currently designed for handling data aborts as the syndrome is partially precomputed and encoded in the TB and then merged in merge_syn_data_abort when handling the data abort. Using raise_exception_ra for DAIF and PAC checks results in an empty syndrome being retrieved from data[2] in restore_state_to_opc and setting ESR to 0. This manifested as: kvm [571]: Unknown exception class: esr: 0x000000 – Unknown/Uncategorized when launching a KVM guest when the host qemu used a CPU supporting EL2+pointer authentication and enabling pointer authentication in the guest. Rework raise_exception_ra such that the state is restored before raising the exception so that the exception is not clobbered by restore_state_to_opc. Fixes: 0d43e1a2d29a ("target/arm: Add PAuth helpers") Cc: Richard Henderson <richard.henderson@linaro.org> Cc: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Jamie Iles <jamie@nuviainc.com> [PMM: added comment] Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--target/arm/op_helper.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index efcb600992..1a95972bcc 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -63,8 +63,15 @@ void raise_exception(CPUARMState *env, uint32_t excp,
void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome,
uint32_t target_el, uintptr_t ra)
{
- CPUState *cs = do_raise_exception(env, excp, syndrome, target_el);
- cpu_loop_exit_restore(cs, ra);
+ CPUState *cs = env_cpu(env);
+
+ /*
+ * restore_state_to_opc() will set env->exception.syndrome, so
+ * we must restore CPU state here before setting the syndrome
+ * the caller passed us, and cannot use cpu_loop_exit_restore().
+ */
+ cpu_restore_state(cs, ra, true);
+ raise_exception(env, excp, syndrome, target_el);
}
uint64_t HELPER(neon_tbl)(CPUARMState *env, uint32_t desc,