From 8ff26a3344b6e6d1eeb00b4043232a5bdbc0ebf9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 6 Oct 2017 16:46:47 +0100 Subject: nvic: Clear the vector arrays and prigroup on reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reset for devices does not include an automatic clear of the device state (unlike CPU state, where most of the state structure is cleared to zero). Add some missing initialization of NVIC state that meant that the device was left in the wrong state if the guest did a warm reset. (In particular, since we were resetting the computed state like s->exception_prio but not all the state it was computed from like s->vectors[x].active, the NVIC wound up in an inconsistent state that could later trigger assertion failures.) Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-id: 1506092407-26985-2-git-send-email-peter.maydell@linaro.org --- hw/intc/armv7m_nvic.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'hw/intc') diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index d90d8d0..bc7b66d 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -1782,6 +1782,11 @@ static void armv7m_nvic_reset(DeviceState *dev) int resetprio; NVICState *s = NVIC(dev); + memset(s->vectors, 0, sizeof(s->vectors)); + memset(s->sec_vectors, 0, sizeof(s->sec_vectors)); + s->prigroup[M_REG_NS] = 0; + s->prigroup[M_REG_S] = 0; + s->vectors[ARMV7M_EXCP_NMI].enabled = 1; /* MEM, BUS, and USAGE are enabled through * the System Handler Control register -- cgit v1.1 From de2db7ec894f11931932ca78cd14a8d2b1389d5b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 6 Oct 2017 16:46:47 +0100 Subject: target/arm: Prepare for CONTROL.SPSEL being nonzero in Handler mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the v7M architecture, there is an invariant that if the CPU is in Handler mode then the CONTROL.SPSEL bit cannot be nonzero. This in turn means that the current stack pointer is always indicated by CONTROL.SPSEL, even though Handler mode always uses the Main stack pointer. In v8M, this invariant is removed, and CONTROL.SPSEL may now be nonzero in Handler mode (though Handler mode still always uses the Main stack pointer). In preparation for this change, change how we handle this bit: rename switch_v7m_sp() to the now more accurate write_v7m_control_spsel(), and make it check both the handler mode state and the SPSEL bit. Note that this implicitly changes the point at which we switch active SP on exception exit from before we pop the exception frame to after it. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 1506092407-26985-4-git-send-email-peter.maydell@linaro.org --- hw/intc/armv7m_nvic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/intc') diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index bc7b66d..a1041c2 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -616,7 +616,7 @@ bool armv7m_nvic_acknowledge_irq(void *opaque) vec->active = 1; vec->pending = 0; - env->v7m.exception = s->vectpending; + write_v7m_exception(env, s->vectpending); nvic_irq_update(s); -- cgit v1.1 From bed079da04dd9e0e249b9bc22bca8dce58b67f40 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 6 Oct 2017 16:46:48 +0100 Subject: target/arm: Add new-in-v8M SFSR and SFAR Add the new M profile Secure Fault Status Register and Secure Fault Address Register. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 1506092407-26985-10-git-send-email-peter.maydell@linaro.org --- hw/intc/armv7m_nvic.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'hw/intc') diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index a1041c2..deea637 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -1017,6 +1017,22 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) goto bad_offset; } return cpu->env.pmsav8.mair1[attrs.secure]; + case 0xde4: /* SFSR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return 0; + } + return cpu->env.v7m.sfsr; + case 0xde8: /* SFAR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return 0; + } + return cpu->env.v7m.sfar; default: bad_offset: qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset); @@ -1368,6 +1384,24 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value, * only affect cacheability, and we don't implement caching. */ break; + case 0xde4: /* SFSR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return; + } + cpu->env.v7m.sfsr &= ~value; /* W1C */ + break; + case 0xde8: /* SFAR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return; + } + cpu->env.v7m.sfsr = value; + break; case 0xf00: /* Software Triggered Interrupt Register */ { int excnum = (value & 0x1ff) + NVIC_FIRST_IRQ; -- cgit v1.1 From 9901c576f6c02d43206e5faaf6e362ab7ea83246 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 6 Oct 2017 16:46:49 +0100 Subject: nvic: Implement Security Attribution Unit registers Implement the register interface for the SAU: SAU_CTRL, SAU_TYPE, SAU_RNR, SAU_RBAR and SAU_RLAR. None of the actual behaviour is implemented here; registers just read back as written. When the CPU definition for Cortex-M33 is eventually added, its initfn will set cpu->sau_sregion, in the same way that we currently set cpu->pmsav7_dregion for the M3 and M4. Number of SAU regions is typically a configurable CPU parameter, but this patch doesn't provide a QEMU CPU property for it. We can easily add one when we have a board that requires it. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 1506092407-26985-14-git-send-email-peter.maydell@linaro.org --- hw/intc/armv7m_nvic.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) (limited to 'hw/intc') diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index deea637..bd1d5d3 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -1017,6 +1017,60 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) goto bad_offset; } return cpu->env.pmsav8.mair1[attrs.secure]; + case 0xdd0: /* SAU_CTRL */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return 0; + } + return cpu->env.sau.ctrl; + case 0xdd4: /* SAU_TYPE */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return 0; + } + return cpu->sau_sregion; + case 0xdd8: /* SAU_RNR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return 0; + } + return cpu->env.sau.rnr; + case 0xddc: /* SAU_RBAR */ + { + int region = cpu->env.sau.rnr; + + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return 0; + } + if (region >= cpu->sau_sregion) { + return 0; + } + return cpu->env.sau.rbar[region]; + } + case 0xde0: /* SAU_RLAR */ + { + int region = cpu->env.sau.rnr; + + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return 0; + } + if (region >= cpu->sau_sregion) { + return 0; + } + return cpu->env.sau.rlar[region]; + } case 0xde4: /* SFSR */ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { goto bad_offset; @@ -1384,6 +1438,68 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value, * only affect cacheability, and we don't implement caching. */ break; + case 0xdd0: /* SAU_CTRL */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return; + } + cpu->env.sau.ctrl = value & 3; + case 0xdd4: /* SAU_TYPE */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + break; + case 0xdd8: /* SAU_RNR */ + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return; + } + if (value >= cpu->sau_sregion) { + qemu_log_mask(LOG_GUEST_ERROR, "SAU region out of range %" + PRIu32 "/%" PRIu32 "\n", + value, cpu->sau_sregion); + } else { + cpu->env.sau.rnr = value; + } + break; + case 0xddc: /* SAU_RBAR */ + { + int region = cpu->env.sau.rnr; + + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return; + } + if (region >= cpu->sau_sregion) { + return; + } + cpu->env.sau.rbar[region] = value & ~0x1f; + tlb_flush(CPU(cpu)); + break; + } + case 0xde0: /* SAU_RLAR */ + { + int region = cpu->env.sau.rnr; + + if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { + goto bad_offset; + } + if (!attrs.secure) { + return; + } + if (region >= cpu->sau_sregion) { + return; + } + cpu->env.sau.rlar[region] = value & ~0x1c; + tlb_flush(CPU(cpu)); + break; + } case 0xde4: /* SFSR */ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) { goto bad_offset; -- cgit v1.1 From 04829ce334bece78d4fa1d0fdbc8bc27dae9b242 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 6 Oct 2017 16:46:49 +0100 Subject: nvic: Add missing code for writing SHCSR.HARDFAULTPENDED bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we added support for the new SHCSR bits in v8M in commit 437d59c17e9 the code to support writing to the new HARDFAULTPENDED bit was accidentally only added for non-secure writes; the secure banked version of the bit should also be writable. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 1506092407-26985-21-git-send-email-peter.maydell@linaro.org --- hw/intc/armv7m_nvic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'hw/intc') diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index bd1d5d3..22d5e6e 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -1230,6 +1230,7 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value, s->sec_vectors[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0; s->sec_vectors[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0; + s->sec_vectors[ARMV7M_EXCP_HARD].pending = (value & (1 << 21)) != 0; /* SecureFault not banked, but RAZ/WI to NS */ s->vectors[ARMV7M_EXCP_SECURE].active = (value & (1 << 4)) != 0; s->vectors[ARMV7M_EXCP_SECURE].enabled = (value & (1 << 19)) != 0; -- cgit v1.1