aboutsummaryrefslogtreecommitdiff
path: root/target/arm/m_helper.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-11-19 21:56:08 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-12-10 11:44:56 +0000
commit3423fbf10427db7680d3237d4f62d8370052fca0 (patch)
tree99621df5d4d2033875f5b2c509db270ba477f92c /target/arm/m_helper.c
parentcb45adb654bb34de9de6301b6981972dd107e342 (diff)
target/arm: Implement new v8.1M NOCP check for exception return
In v8.1M a new exception return check is added which may cause a NOCP UsageFault (see rule R_XLTP): before we clear s0..s15 and the FPSCR we must check whether access to CP10 from the Security state of the returning exception is disabled; if it is then we must take a fault. (Note that for our implementation CPPWR is always RAZ/WI and so can never cause CP10 accesses to fail.) The other v8.1M change to this register-clearing code is that if MVE is implemented VPR must also be cleared, so add a TODO comment to that effect. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
Diffstat (limited to 'target/arm/m_helper.c')
-rw-r--r--target/arm/m_helper.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 9cdc8a64c2..0bdd3cc10e 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -1515,7 +1515,27 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
v7m_exception_taken(cpu, excret, true, false);
return;
} else {
- /* Clear s0..s15 and FPSCR */
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
+ /* v8.1M adds this NOCP check */
+ bool nsacr_pass = exc_secure ||
+ extract32(env->v7m.nsacr, 10, 1);
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
+ if (!nsacr_pass) {
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
+ "stackframe: NSACR prevents clearing FPU registers\n");
+ v7m_exception_taken(cpu, excret, true, false);
+ } else if (!cpacr_pass) {
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
+ exc_secure);
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
+ "stackframe: CPACR prevents clearing FPU registers\n");
+ v7m_exception_taken(cpu, excret, true, false);
+ }
+ }
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
int i;
for (i = 0; i < 16; i += 2) {