The GICv3 and GICv5 CPU interfaces are not compatible, and a CPU will only implement either one or the other. If we find that we're trying to connect a GICv3 to a CPU that implements FEAT_GCIE, fail. This will only happen if the board code has a bug and doesn't configure its CPUs and its GIC consistently.
Signed-off-by: Peter Maydell <[email protected]> --- hw/intc/arm_gicv3.c | 2 +- hw/intc/arm_gicv3_cpuif.c | 14 +++++++++++++- hw/intc/gicv3_internal.h | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c index 542f81ea49..e93c1df5b4 100644 --- a/hw/intc/arm_gicv3.c +++ b/hw/intc/arm_gicv3.c @@ -449,7 +449,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops); - gicv3_init_cpuif(s); + gicv3_init_cpuif(s, errp); } static void arm_gicv3_class_init(ObjectClass *klass, const void *data) diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index eaf1e512ed..73e06f87d4 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -16,6 +16,7 @@ #include "qemu/bitops.h" #include "qemu/log.h" #include "qemu/main-loop.h" +#include "qapi/error.h" #include "trace.h" #include "gicv3_internal.h" #include "hw/core/irq.h" @@ -3016,7 +3017,7 @@ static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque) gicv3_cpuif_virt_irq_fiq_update(cs); } -void gicv3_init_cpuif(GICv3State *s) +void gicv3_init_cpuif(GICv3State *s, Error **errp) { /* Called from the GICv3 realize function; register our system * registers with the CPU @@ -3027,6 +3028,17 @@ void gicv3_init_cpuif(GICv3State *s) ARMCPU *cpu = ARM_CPU(qemu_get_cpu(s->first_cpu_idx + i)); GICv3CPUState *cs = &s->cpu[i]; + if (cpu_isar_feature(aa64_gcie, cpu)) { + /* + * Attempt to connect GICv3 to a CPU with GICv5 cpuif + * (almost certainly a bug in the board code) + */ + error_setg(errp, + "Cannot connect GICv3 to CPU %d which has GICv5 cpuif", + i); + return; + } + /* * If the CPU doesn't define a GICv3 configuration, probably because * in real hardware it doesn't have one, then we use default values diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 880dbe52d8..c01be70464 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -722,7 +722,7 @@ void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr, void gicv3_redist_vinvall(GICv3CPUState *cs, uint64_t vptaddr); void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); -void gicv3_init_cpuif(GICv3State *s); +void gicv3_init_cpuif(GICv3State *s, Error **errp); /** * gicv3_cpuif_update: -- 2.43.0
