aboutsummaryrefslogtreecommitdiff
path: root/target/arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-04-29 17:35:59 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-04-29 17:35:59 +0100
commit3432c79a4e7345818d2defcf9e61a1bcb2907f9f (patch)
tree38d789bba131bec193895924427b822e3fb5dc9b /target/arm
parent2e1c5bcd32014c9ede1b604ae6c2c653de17fc53 (diff)
target/arm/helper: don't return early for STKOF faults during stacking
Currently the code in v7m_push_stack() which detects a violation of the v8M stack limit simply returns early if it does so. This is OK for the current integer-only code, but won't work for the floating point handling we're about to add. We need to continue executing the rest of the function so that we check for other exceptions like not having permission to use the FPU and so that we correctly set the FPCCR state if we are doing lazy stacking. Refactor to avoid the early return. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190416125744.27770-10-peter.maydell@linaro.org
Diffstat (limited to 'target/arm')
-rw-r--r--target/arm/helper.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e801744673..142d301b65 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8182,7 +8182,7 @@ static bool v7m_push_stack(ARMCPU *cpu)
* should ignore further stack faults trying to process
* that derived exception.)
*/
- bool stacked_ok;
+ bool stacked_ok = true, limitviol = false;
CPUARMState *env = &cpu->env;
uint32_t xpsr = xpsr_read(env);
uint32_t frameptr = env->regs[13];
@@ -8213,7 +8213,14 @@ static bool v7m_push_stack(ARMCPU *cpu)
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
env->v7m.secure);
env->regs[13] = limit;
- return true;
+ /*
+ * We won't try to perform any further memory accesses but
+ * we must continue through the following code to check for
+ * permission faults during FPU state preservation, and we
+ * must update FPCCR if lazy stacking is enabled.
+ */
+ limitviol = true;
+ stacked_ok = false;
}
}
@@ -8222,7 +8229,7 @@ static bool v7m_push_stack(ARMCPU *cpu)
* (which may be taken in preference to the one we started with
* if it has higher priority).
*/
- stacked_ok =
+ stacked_ok = stacked_ok &&
v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
@@ -8232,8 +8239,14 @@ static bool v7m_push_stack(ARMCPU *cpu)
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
- /* Update SP regardless of whether any of the stack accesses failed. */
- env->regs[13] = frameptr;
+ /*
+ * If we broke a stack limit then SP was already updated earlier;
+ * otherwise we update SP regardless of whether any of the stack
+ * accesses failed or we took some other kind of fault.
+ */
+ if (!limitviol) {
+ env->regs[13] = frameptr;
+ }
return !stacked_ok;
}