aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-05-12 11:57:18 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-05-12 11:57:18 +0100
commitdadbb58f5955053c5f5dc2252a4b183f90d7bfce (patch)
treea39fb591d7790ee059d88a7007694f79597fc6bb
parentc5619bf9e8935aeb972c0bd935549e9ee0a739f2 (diff)
downloadqemu-dadbb58f5955053c5f5dc2252a4b183f90d7bfce.zip
qemu-dadbb58f5955053c5f5dc2252a4b183f90d7bfce.tar.gz
qemu-dadbb58f5955053c5f5dc2252a4b183f90d7bfce.tar.bz2
hw/intc/arm_gic: Add grouping support to gic_update()
Add support to gic_update() for determining the current IRQ and FIQ status when interrupt grouping is supported. This simply requires that instead of always raising IRQ we check the group of the highest priority pending interrupt and the GICC_CTLR.FIQEn bit to see whether we should raise IRQ or FIQ. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Message-id: 1430502643-25909-15-git-send-email-peter.maydell@linaro.org
-rw-r--r--hw/intc/arm_gic.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 6abdb14..c1d2e70 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -60,7 +60,7 @@ void gic_update(GICState *s)
int best_irq;
int best_prio;
int irq;
- int level;
+ int irq_level, fiq_level;
int cpu;
int cm;
@@ -70,6 +70,7 @@ void gic_update(GICState *s)
if (!(s->ctlr & (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1))
|| !(s->cpu_ctlr[cpu] & (GICC_CTLR_EN_GRP0 | GICC_CTLR_EN_GRP1))) {
qemu_irq_lower(s->parent_irq[cpu]);
+ qemu_irq_lower(s->parent_fiq[cpu]);
return;
}
best_prio = 0x100;
@@ -83,15 +84,31 @@ void gic_update(GICState *s)
}
}
}
- level = 0;
+
+ irq_level = fiq_level = 0;
+
if (best_prio < s->priority_mask[cpu]) {
s->current_pending[cpu] = best_irq;
if (best_prio < s->running_priority[cpu]) {
- DPRINTF("Raised pending IRQ %d (cpu %d)\n", best_irq, cpu);
- level = 1;
+ int group = GIC_TEST_GROUP(best_irq, cm);
+
+ if (extract32(s->ctlr, group, 1) &&
+ extract32(s->cpu_ctlr[cpu], group, 1)) {
+ if (group == 0 && s->cpu_ctlr[cpu] & GICC_CTLR_FIQ_EN) {
+ DPRINTF("Raised pending FIQ %d (cpu %d)\n",
+ best_irq, cpu);
+ fiq_level = 1;
+ } else {
+ DPRINTF("Raised pending IRQ %d (cpu %d)\n",
+ best_irq, cpu);
+ irq_level = 1;
+ }
+ }
}
}
- qemu_set_irq(s->parent_irq[cpu], level);
+
+ qemu_set_irq(s->parent_irq[cpu], irq_level);
+ qemu_set_irq(s->parent_fiq[cpu], fiq_level);
}
}