nvic: Expose NMI line
On real v7M hardware, the NMI line is an externally visible signal that an SoC or board can toggle to assert an NMI. Expose it in our QEMU NVIC and armv7m container objects so that a board model can wire it up if it needs to. In particular, the MPS2 watchdog is wired to NMI. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
This commit is contained in:
parent
050c2ea07b
commit
514b4f361b
|
@ -202,6 +202,7 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
|
||||||
*/
|
*/
|
||||||
qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
|
qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL);
|
||||||
qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
|
qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
|
||||||
|
qdev_pass_gpios(DEVICE(&s->nvic), dev, "NMI");
|
||||||
|
|
||||||
/* Wire the NVIC up to the CPU */
|
/* Wire the NVIC up to the CPU */
|
||||||
sbd = SYS_BUS_DEVICE(&s->nvic);
|
sbd = SYS_BUS_DEVICE(&s->nvic);
|
||||||
|
|
|
@ -774,6 +774,24 @@ static void set_irq_level(void *opaque, int n, int level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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)
|
static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = s->cpu;
|
ARMCPU *cpu = s->cpu;
|
||||||
|
@ -2382,6 +2400,7 @@ static void armv7m_nvic_instance_init(Object *obj)
|
||||||
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
|
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
|
||||||
qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger",
|
qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger",
|
||||||
M_REG_NUM_BANKS);
|
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)
|
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
|
@ -192,6 +192,7 @@ nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (pr
|
||||||
nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
|
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_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_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_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"
|
nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue