summaryrefslogtreecommitdiffstats
path: root/hw/intc/arm_gic.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/intc/arm_gic.c')
-rw-r--r--hw/intc/arm_gic.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index ea0323f969..34dc84ae81 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -543,7 +543,21 @@ static bool gic_eoi_split(GICState *s, int cpu, MemTxAttrs attrs)
static void gic_deactivate_irq(GICState *s, int cpu, int irq, MemTxAttrs attrs)
{
int cm = 1 << cpu;
- int group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
+ int group;
+
+ if (irq >= s->num_irq) {
+ /*
+ * This handles two cases:
+ * 1. If software writes the ID of a spurious interrupt [ie 1023]
+ * to the GICC_DIR, the GIC ignores that write.
+ * 2. If software writes the number of a non-existent interrupt
+ * this must be a subcase of "value written is not an active interrupt"
+ * and so this is UNPREDICTABLE. We choose to ignore it.
+ */
+ return;
+ }
+
+ group = gic_has_groups(s) && GIC_TEST_GROUP(irq, cm);
if (!gic_eoi_split(s, cpu, attrs)) {
/* This is UNPREDICTABLE; we choose to ignore it */
@@ -737,7 +751,9 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
if (irq >= s->num_irq) {
goto bad_reg;
}
- if (irq >= 29 && irq <= 31) {
+ if (irq < 29 && s->revision == REV_11MPCORE) {
+ res = 0;
+ } else if (irq < GIC_INTERNAL) {
res = cm;
} else {
res = GIC_TARGET(irq);
@@ -1000,7 +1016,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
if (irq >= s->num_irq) {
goto bad_reg;
}
- if (irq < 29) {
+ if (irq < 29 && s->revision == REV_11MPCORE) {
value = 0;
} else if (irq < GIC_INTERNAL) {
value = ALL_CPU_MASK;