diff options
Diffstat (limited to 'hw/intc/arm_gic.c')
-rw-r--r-- | hw/intc/arm_gic.c | 22 |
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; |