diff options
author | Fabian Aggeler <aggelerf@ethz.ch> | 2015-05-12 11:57:18 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-05-12 11:57:18 +0100 |
commit | c5619bf9e8935aeb972c0bd935549e9ee0a739f2 (patch) | |
tree | 5e8b6078292ecea8d4340a3f5ac188e8cf7e8593 /hw/intc/arm_gic.c | |
parent | f9c6a7f1395c6d88a3bb1a0cb48811994709966e (diff) |
hw/intc/arm_gic: Change behavior of IAR writes
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>
Diffstat (limited to 'hw/intc/arm_gic.c')
-rw-r--r-- | hw/intc/arm_gic.c | 22 |
1 files changed, 16 insertions, 6 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); |