From 4b24f6d87b7500dd767a810fbb289f132d645081 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Sun, 4 Mar 2018 21:09:32 -0500 Subject: [PATCH] target/arm: Make CCR register banked for v8M Make the CCR register banked if v8M security extensions are enabled. This is slightly more complicated than the other "add banking" patches because there is one bit in the register which is not banked. We keep the live data in the NS copy of the register, and adjust it on register reads and writes. (Since we don't currently implement the behaviour that the bit controls, there is nowhere else that needs to care.) This patch includes the enforcement of the bits which are newly RES1 in ARMv8M. Backports commit 9d40cd8a68cfc7606f4548cc9e812bab15c6dc28 from qemu --- qemu/target/arm/cpu.c | 12 +++++++++--- qemu/target/arm/cpu.h | 2 +- qemu/target/arm/helper.c | 5 +++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/qemu/target/arm/cpu.c b/qemu/target/arm/cpu.c index 8b5e7b3e..6714eff1 100644 --- a/qemu/target/arm/cpu.c +++ b/qemu/target/arm/cpu.c @@ -182,11 +182,17 @@ static void arm_cpu_reset(CPUState *s) env->v7m.secure = true; } - /* The reset value of this bit is IMPDEF, but ARM recommends + /* In v7M the reset value of this bit is IMPDEF, but ARM recommends * that it resets to 1, so QEMU always does that rather than making - * it dependent on CPU model. + * it dependent on CPU model. In v8M it is RES1. */ - env->v7m.ccr = R_V7M_CCR_STKALIGN_MASK; + env->v7m.ccr[M_REG_NS] = R_V7M_CCR_STKALIGN_MASK; + env->v7m.ccr[M_REG_S] = R_V7M_CCR_STKALIGN_MASK; + if (arm_feature(env, ARM_FEATURE_V8)) { + /* in v8M the NONBASETHRDENA bit [0] is RES1 */ + env->v7m.ccr[M_REG_NS] |= R_V7M_CCR_NONBASETHRDENA_MASK; + env->v7m.ccr[M_REG_S] |= R_V7M_CCR_NONBASETHRDENA_MASK; + } /* Unlike A/R profile, M profile defines the reset LR value */ env->regs[14] = 0xffffffff; diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index c20f5123..f371e28a 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -428,7 +428,7 @@ typedef struct CPUARMState { uint32_t vecbase[2]; uint32_t basepri[2]; uint32_t control[2]; - uint32_t ccr; /* Configuration and Control */ + uint32_t ccr[2]; /* Configuration and Control */ uint32_t cfsr; /* Configurable Fault Status */ uint32_t hfsr; /* HardFault Status */ uint32_t dfsr; /* Debug Fault Status Register */ diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index 3678344f..0bc1d78c 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -5372,7 +5372,8 @@ static void v7m_push_stack(ARMCPU *cpu) uint32_t xpsr = xpsr_read(env); /* Align stack pointer if the guest wants that */ - if ((env->regs[13] & 4) && (env->v7m.ccr & R_V7M_CCR_STKALIGN_MASK)) { + if ((env->regs[13] & 4) && + (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_STKALIGN_MASK)) { env->regs[13] -= 4; xpsr |= XPSR_SPREALIGN; } @@ -5475,7 +5476,7 @@ static void do_v7m_exception_exit(ARMCPU *cpu) /* fall through */ case 9: /* Return to Thread using Main stack */ if (!rettobase && - !(env->v7m.ccr & R_V7M_CCR_NONBASETHRDENA_MASK)) { + !(env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_NONBASETHRDENA_MASK)) { ufault = true; } break;