hw/intc/arm_gic: Change behavior of IAR writes
authorFabian Aggeler <aggelerf@ethz.ch>
Tue, 12 May 2015 10:57:18 +0000 (11:57 +0100)
committerPeter Maydell <peter.maydell@linaro.org>
Tue, 12 May 2015 10:57:18 +0000 (11:57 +0100)
Grouping (GICv2) and Security Extensions change the behavior of IAR
reads. Acknowledging Group0 interrupts is only allowed from Secure
state and acknowledging Group1 interrupts from Secure state is only
allowed if AckCtl bit is set.

Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Signed-off-by: Greg Bellows <greg.bellows@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1430502643-25909-14-git-send-email-peter.maydell@linaro.org
Message-id: 1429113742-8371-14-git-send-email-greg.bellows@linaro.org
[PMM: simplify significantly by reusing the existing
 gic_get_current_pending_irq() rather than reimplementing the
 same logic here]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
hw/intc/arm_gic.c
hw/intc/armv7m_nvic.c
hw/intc/gic_internal.h

index 4ad80e77bb9746832b7263915120cd47e21775a5..6abdb143792584e4a667fe29c4091604ee766254 100644 (file)
@@ -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);
index 1bfff7530aaeba4b6f858871457c1e3621ba660b..e13b729e1d4cd8361f6e625cc7958669773e70a2 100644 (file)
@@ -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)
index d3cebeff3be4a84b0fd9259b30b2dff4d30f9cbe..20c1e8a2427d9c761b86d642d2ad3df05febbeb6 100644 (file)
@@ -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);