aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-07-20 15:56:46 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-08-02 13:19:35 +0100
commit7a1ef343a1808d36dc9f8cc415511a954bc6ce7e (patch)
treec49abeb84e969a6f3b46f6dcd1bc37295504fb85
parent43bda01e00d2e30d048762c07e8985e5af535207 (diff)
target/arm: Restore M-profile CONTROL.SPSEL before any tailchaining
On exception return for M-profile, we must restore the CONTROL.SPSEL bit from the EXCRET value before we do any kind of tailchaining, including for the derived exceptions on integrity check failures. Otherwise we will give the guest an incorrect EXCRET.SPSEL value on exception entry for the tailchained exception. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20180720145647.8810-4-peter.maydell@linaro.org
-rw-r--r--target/arm/helper.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 9d908f1c66..559065131a 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7131,6 +7131,16 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
}
}
+ /*
+ * Set CONTROL.SPSEL from excret.SPSEL. Since we're still in
+ * Handler mode (and will be until we write the new XPSR.Interrupt
+ * field) this does not switch around the current stack pointer.
+ * We must do this before we do any kind of tailchaining, including
+ * for the derived exceptions on integrity check failures, or we will
+ * give the guest an incorrect EXCRET.SPSEL value on exception entry.
+ */
+ write_v7m_control_spsel_for_secstate(env, return_to_sp_process, exc_secure);
+
if (sfault) {
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
@@ -7152,12 +7162,6 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
return;
}
- /* Set CONTROL.SPSEL from excret.SPSEL. Since we're still in
- * Handler mode (and will be until we write the new XPSR.Interrupt
- * field) this does not switch around the current stack pointer.
- */
- write_v7m_control_spsel_for_secstate(env, return_to_sp_process, exc_secure);
-
switch_v7m_security_state(env, return_to_secure);
{