summaryrefslogtreecommitdiffstats
path: root/qemu/hw/intc/armv7m_nvic.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/intc/armv7m_nvic.c')
-rw-r--r--qemu/hw/intc/armv7m_nvic.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/qemu/hw/intc/armv7m_nvic.c b/qemu/hw/intc/armv7m_nvic.c
index e13b729e1..669e82adf 100644
--- a/qemu/hw/intc/armv7m_nvic.c
+++ b/qemu/hw/intc/armv7m_nvic.c
@@ -10,6 +10,9 @@
* NVIC. Much of that is also implemented here.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "hw/arm/arm.h"
@@ -28,6 +31,7 @@ typedef struct {
MemoryRegion gic_iomem_alias;
MemoryRegion container;
uint32_t num_irq;
+ qemu_irq sysresetreq;
} nvic_state;
#define TYPE_NVIC "armv7m_nvic"
@@ -185,26 +189,25 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
return cpu->midr;
case 0xd04: /* Interrupt Control State. */
/* VECTACTIVE */
- val = s->gic.running_irq[0];
+ cpu = ARM_CPU(current_cpu);
+ val = cpu->env.v7m.exception;
if (val == 1023) {
val = 0;
} else if (val >= 32) {
val -= 16;
}
- /* RETTOBASE */
- if (s->gic.running_irq[0] == 1023
- || s->gic.last_active[s->gic.running_irq[0]][0] == 1023) {
- val |= (1 << 11);
- }
/* VECTPENDING */
if (s->gic.current_pending[0] != 1023)
val |= (s->gic.current_pending[0] << 12);
- /* ISRPENDING */
+ /* ISRPENDING and RETTOBASE */
for (irq = 32; irq < s->num_irq; irq++) {
if (s->gic.irq_state[irq].pending) {
val |= (1 << 22);
break;
}
+ if (irq != cpu->env.v7m.exception && s->gic.irq_state[irq].active) {
+ val |= (1 << 11);
+ }
}
/* PENDSTSET */
if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
@@ -349,10 +352,13 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
break;
case 0xd0c: /* Application Interrupt/Reset Control. */
if ((value >> 16) == 0x05fa) {
+ if (value & 4) {
+ qemu_irq_pulse(s->sysresetreq);
+ }
if (value & 2) {
qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
}
- if (value & 5) {
+ if (value & 1) {
qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
}
if (value & 0x700) {
@@ -536,11 +542,14 @@ static void armv7m_nvic_instance_init(Object *obj)
* value in the GICState struct.
*/
GICState *s = ARM_GIC_COMMON(obj);
+ DeviceState *dev = DEVICE(obj);
+ nvic_state *nvic = NVIC(obj);
/* The ARM v7m may have anything from 0 to 496 external interrupt
* IRQ lines. We default to 64. Other boards may differ and should
* set the num-irq property appropriately.
*/
s->num_irq = 64;
+ qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
}
static void armv7m_nvic_class_init(ObjectClass *klass, void *data)