aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-09-07 13:54:54 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-09-07 13:54:54 +0100
commit9d40cd8a68cfc7606f4548cc9e812bab15c6dc28 (patch)
tree5ea2b0c184445a132503a6ae8b8710be0e709fac /hw
parentecf5e8eae8b0b5fa41f00b53d67747b42fd1b8b9 (diff)
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. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1503414539-28762-17-git-send-email-peter.maydell@linaro.org
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/armv7m_nvic.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index a4c298f9c9..a8893973f4 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -448,7 +448,12 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
/* TODO: Implement SLEEPONEXIT. */
return 0;
case 0xd14: /* Configuration Control. */
- return cpu->env.v7m.ccr;
+ /* The BFHFNMIGN bit is the only non-banked bit; we
+ * keep it in the non-secure copy of the register.
+ */
+ val = cpu->env.v7m.ccr[attrs.secure];
+ val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
+ return val;
case 0xd24: /* System Handler Status. */
val = 0;
if (s->vectors[ARMV7M_EXCP_MEM].active) {
@@ -673,7 +678,20 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
R_V7M_CCR_USERSETMPEND_MASK |
R_V7M_CCR_NONBASETHRDENA_MASK);
- cpu->env.v7m.ccr = value;
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
+ /* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
+ value |= R_V7M_CCR_NONBASETHRDENA_MASK
+ | R_V7M_CCR_STKALIGN_MASK;
+ }
+ if (attrs.secure) {
+ /* the BFHFNMIGN bit is not banked; keep that in the NS copy */
+ cpu->env.v7m.ccr[M_REG_NS] =
+ (cpu->env.v7m.ccr[M_REG_NS] & ~R_V7M_CCR_BFHFNMIGN_MASK)
+ | (value & R_V7M_CCR_BFHFNMIGN_MASK);
+ value &= ~R_V7M_CCR_BFHFNMIGN_MASK;
+ }
+
+ cpu->env.v7m.ccr[attrs.secure] = value;
break;
case 0xd24: /* System Handler Control. */
s->vectors[ARMV7M_EXCP_MEM].active = (value & (1 << 0)) != 0;
@@ -860,12 +878,15 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
}
}
-static bool nvic_user_access_ok(NVICState *s, hwaddr offset)
+static bool nvic_user_access_ok(NVICState *s, hwaddr offset, MemTxAttrs attrs)
{
/* Return true if unprivileged access to this register is permitted. */
switch (offset) {
case 0xf00: /* STIR: accessible only if CCR.USERSETMPEND permits */
- return s->cpu->env.v7m.ccr & R_V7M_CCR_USERSETMPEND_MASK;
+ /* For access via STIR_NS it is the NS CCR.USERSETMPEND that
+ * controls access even though the CPU is in Secure state (I_QDKX).
+ */
+ return s->cpu->env.v7m.ccr[attrs.secure] & R_V7M_CCR_USERSETMPEND_MASK;
default:
/* All other user accesses cause a BusFault unconditionally */
return false;
@@ -881,7 +902,7 @@ static MemTxResult nvic_sysreg_read(void *opaque, hwaddr addr,
unsigned i, startvec, end;
uint32_t val;
- if (attrs.user && !nvic_user_access_ok(s, addr)) {
+ if (attrs.user && !nvic_user_access_ok(s, addr, attrs)) {
/* Generate BusFault for unprivileged accesses */
return MEMTX_ERROR;
}
@@ -971,7 +992,7 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
trace_nvic_sysreg_write(addr, value, size);
- if (attrs.user && !nvic_user_access_ok(s, addr)) {
+ if (attrs.user && !nvic_user_access_ok(s, addr, attrs)) {
/* Generate BusFault for unprivileged accesses */
return MEMTX_ERROR;
}