*/
qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
+ qdev_pass_gpios(DEVICE(&s->nvic), dev, "NMI");
/* Wire the NVIC up to the CPU */
sbd = SYS_BUS_DEVICE(&s->nvic);
}
}
+/* callback when external NMI line is changed */
+static void nvic_nmi_trigger(void *opaque, int n, int level)
+{
+ NVICState *s = opaque;
+
+ trace_nvic_set_nmi_level(level);
+
+ /*
+ * The architecture doesn't specify whether NMI should share
+ * the normal-interrupt behaviour of being resampled on
+ * exception handler return. We choose not to, so just
+ * set NMI pending here and don't track the current level.
+ */
+ if (level) {
+ armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI, false);
+ }
+}
+
static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
{
ARMCPU *cpu = s->cpu;
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger",
M_REG_NUM_BANKS);
+ qdev_init_gpio_in_named(dev, nvic_nmi_trigger, "NMI", 1);
}
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
+nvic_set_nmi_level(int level) "NVIC external NMI level set to %d"
nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"