aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/intc/arm_gic.c22
-rw-r--r--hw/intc/armv7m_nvic.c2
-rw-r--r--hw/intc/gic_internal.h2
3 files changed, 18 insertions, 8 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 4ad80e77bb..6abdb14379 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -213,14 +213,24 @@ static void gic_set_running_irq(GICState *s, int cpu, int irq)
gic_update(s);
}
-uint32_t gic_acknowledge_irq(GICState *s, int cpu)
+uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs)
{
int ret, irq, src;
int cm = 1 << cpu;
- irq = s->current_pending[cpu];
- if (irq == 1023
- || GIC_GET_PRIORITY(irq, cpu) >= s->running_priority[cpu]) {
- DPRINTF("ACK no pending IRQ\n");
+
+ /* gic_get_current_pending_irq() will return 1022 or 1023 appropriately
+ * for the case where this GIC supports grouping and the pending interrupt
+ * is in the wrong group.
+ */
+ irq = gic_get_current_pending_irq(s, cpu, attrs);;
+
+ if (irq >= GIC_MAXIRQ) {
+ DPRINTF("ACK, no pending interrupt or it is hidden: %d\n", irq);
+ return irq;
+ }
+
+ if (GIC_GET_PRIORITY(irq, cpu) >= s->running_priority[cpu]) {
+ DPRINTF("ACK, pending interrupt (%d) has insufficient priority\n", irq);
return 1023;
}
s->last_active[irq][cpu] = s->running_irq[cpu];
@@ -920,7 +930,7 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
}
break;
case 0x0c: /* Acknowledge */
- *data = gic_acknowledge_irq(s, cpu);
+ *data = gic_acknowledge_irq(s, cpu, attrs);
break;
case 0x14: /* Running Priority */
*data = gic_get_running_priority(s, cpu, attrs);
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 1bfff7530a..e13b729e1d 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -131,7 +131,7 @@ int armv7m_nvic_acknowledge_irq(void *opaque)
nvic_state *s = (nvic_state *)opaque;
uint32_t irq;
- irq = gic_acknowledge_irq(&s->gic, 0);
+ irq = gic_acknowledge_irq(&s->gic, 0, MEMTXATTRS_UNSPECIFIED);
if (irq == 1023)
hw_error("Interrupt but no vector\n");
if (irq >= 32)
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index d3cebeff3b..20c1e8a242 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -78,7 +78,7 @@
#define REV_NVIC 0xffffffff
void gic_set_pending_private(GICState *s, int cpu, int irq);
-uint32_t gic_acknowledge_irq(GICState *s, int cpu);
+uint32_t gic_acknowledge_irq(GICState *s, int cpu, MemTxAttrs attrs);
void gic_complete_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs);
void gic_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s);