diff options
-rw-r--r-- | hw/intc/armv7m_nvic.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index c9149a3..1e7ddcb 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); |