aboutsummaryrefslogtreecommitdiff
path: root/hw/intc/armv7m_nvic.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-07-23 17:21:46 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-07-27 10:57:39 +0100
commit845d27a91315bc1e3a0000339c5ee46ef63598a5 (patch)
treec1be3d17724288dbb02d179b580ba9ebfadaa62f /hw/intc/armv7m_nvic.c
parent7caad65756c0afaf4b238b068ab61481eb68a1dc (diff)
hw/intc/armv7m_nvic: for v8.1M VECTPENDING hides S exceptions from NS
In Arm v8.1M the VECTPENDING field in the ICSR has new behaviour: if the register is accessed NonSecure and the highest priority pending enabled exception (that would be returned in the VECTPENDING field) targets Secure, then the VECTPENDING field must read 1 rather than the exception number of the pending exception. Implement this. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210723162146.5167-7-peter.maydell@linaro.org
Diffstat (limited to 'hw/intc/armv7m_nvic.c')
-rw-r--r--hw/intc/armv7m_nvic.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index c9149a3b22..1e7ddcb94c 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -804,6 +804,16 @@ void armv7m_nvic_acknowledge_irq(void *opaque)
nvic_irq_update(s);
}
+static bool vectpending_targets_secure(NVICState *s)
+{
+ /* Return true if s->vectpending targets Secure state */
+ if (s->vectpending_is_s_banked) {
+ return true;
+ }
+ return !exc_is_banked(s->vectpending) &&
+ exc_targets_secure(s, s->vectpending);
+}
+
void armv7m_nvic_get_pending_irq_info(void *opaque,
int *pirq, bool *ptargets_secure)
{
@@ -813,12 +823,7 @@ void armv7m_nvic_get_pending_irq_info(void *opaque,
assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
- if (s->vectpending_is_s_banked) {
- targets_secure = true;
- } else {
- targets_secure = !exc_is_banked(pending) &&
- exc_targets_secure(s, pending);
- }
+ targets_secure = vectpending_targets_secure(s);
trace_nvic_get_pending_irq_info(pending, targets_secure);
@@ -1039,7 +1044,19 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
/* VECTACTIVE */
val = cpu->env.v7m.exception;
/* VECTPENDING */
- val |= (s->vectpending & 0x1ff) << 12;
+ if (s->vectpending) {
+ /*
+ * From v8.1M VECTPENDING must read as 1 if accessed as
+ * NonSecure and the highest priority pending and enabled
+ * exception targets Secure.
+ */
+ int vp = s->vectpending;
+ if (!attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_V8_1M) &&
+ vectpending_targets_secure(s)) {
+ vp = 1;
+ }
+ val |= (vp & 0x1ff) << 12;
+ }
/* ISRPENDING - set if any external IRQ is pending */
if (nvic_isrpending(s)) {
val |= (1 << 22);