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 <peter.maydell@linaro.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
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