diff mbox series

[PULL,41/45] target/arm: Implement tailchaining for M profile cores

Message ID 20180814181815.23348-42-peter.maydell@linaro.org
State Accepted
Commit 5f62d3b9e67bfc3deb970e3c7fb7df7e57d46fc3
Headers show
Series target-arm queue | expand

Commit Message

Peter Maydell Aug. 14, 2018, 6:18 p.m. UTC
Tailchaining is an optimization in handling of exception return
for M-profile cores: if we are about to pop the exception stack
for an exception return, but there is a pending exception which
is higher priority than the priority we are returning to, then
instead of unstacking and then immediately taking the exception
and stacking registers again, we can chain to the pending
exception without unstacking and stacking.

For v6M and v7M it is IMPDEF whether tailchaining happens for pending
exceptions; for v8M this is architecturally required.  Implement it
in QEMU for all M-profile cores, since in practice v6M and v7M
hardware implementations generally do have it.

(We were already doing tailchaining for derived exceptions which
happened during exception return, like the validity checks and
stack access failures; these have always been required to be
tailchained for all versions of the architecture.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

Message-id: 20180720145647.8810-5-peter.maydell@linaro.org
---
 target/arm/helper.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

-- 
2.18.0
diff mbox series

Patch

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 559065131a4..8b07bf214ec 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7162,6 +7162,22 @@  static void do_v7m_exception_exit(ARMCPU *cpu)
         return;
     }
 
+    /*
+     * Tailchaining: if there is currently a pending exception that
+     * is high enough priority to preempt execution at the level we're
+     * about to return to, then just directly take that exception now,
+     * avoiding an unstack-and-then-stack. Note that now we have
+     * deactivated the previous exception by calling armv7m_nvic_complete_irq()
+     * our current execution priority is already the execution priority we are
+     * returning to -- none of the state we would unstack or set based on
+     * the EXCRET value affects it.
+     */
+    if (armv7m_nvic_can_take_pending_exception(env->nvic)) {
+        qemu_log_mask(CPU_LOG_INT, "...tailchaining to pending exception\n");
+        v7m_exception_taken(cpu, excret, true, false);
+        return;
+    }
+
     switch_v7m_security_state(env, return_to_secure);
 
     {