On Wed, Jul 16, 2025 at 11:54:08AM +0200, Luc Michel wrote: > Add support for GICv2 instantiation in the Versal SoC. This is in > preparation for the RPU refactoring. > > Signed-off-by: Luc Michel <luc.mic...@amd.com>
Reviewed-by: Francisco Iglesias <francisco.igles...@amd.com> > --- > hw/arm/xlnx-versal.c | 82 +++++++++++++++++++++++++++++++++----------- > 1 file changed, 62 insertions(+), 20 deletions(-) > > diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c > index 58cd874f81f..771f6108558 100644 > --- a/hw/arm/xlnx-versal.c > +++ b/hw/arm/xlnx-versal.c > @@ -43,10 +43,11 @@ > #include "hw/misc/xlnx-versal-cframe-reg.h" > #include "hw/or-irq.h" > #include "hw/misc/xlnx-versal-crl.h" > #include "hw/intc/arm_gicv3_common.h" > #include "hw/intc/arm_gicv3_its_common.h" > +#include "hw/intc/arm_gic.h" > #include "hw/core/split-irq.h" > > #define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72") > #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f") > #define GEM_REVISION 0x40070106 > @@ -72,10 +73,11 @@ typedef struct VersalSimplePeriphMap { > > typedef struct VersalGicMap { > int version; > uint64_t dist; > uint64_t redist; > + uint64_t cpu_iface; > uint64_t its; > size_t num_irq; > bool has_its; > } VersalGicMap; > > @@ -504,10 +506,14 @@ static void versal_create_gic_its(Versal *s, > DeviceState *dev; > SysBusDevice *sbd; > g_autofree char *node_pat = NULL, *node = NULL; > const char compatible[] = "arm,gic-v3-its"; > > + if (map->gic.version != 3) { > + return; > + } > + > if (!map->gic.has_its) { > return; > } > > dev = qdev_new(TYPE_ARM_GICV3_ITS); > @@ -543,49 +549,85 @@ static DeviceState *versal_create_gic(Versal *s, > int first_cpu_idx, > size_t num_cpu) > { > DeviceState *dev; > SysBusDevice *sbd; > - QList *redist_region_count; > g_autofree char *node = NULL; > g_autofree char *name = NULL; > - const char compatible[] = "arm,gic-v3"; > + const char gicv3_compat[] = "arm,gic-v3"; > + const char gicv2_compat[] = "arm,cortex-a15-gic"; > + > + switch (map->gic.version) { > + case 2: > + dev = qdev_new(gic_class_name()); > + break; > + > + case 3: > + dev = qdev_new(gicv3_class_name()); > + break; > + > + default: > + g_assert_not_reached(); > + } > > - dev = qdev_new(gicv3_class_name()); > name = g_strdup_printf("%s-gic[*]", map->name); > object_property_add_child(OBJECT(s), name, OBJECT(dev)); > sbd = SYS_BUS_DEVICE(dev); > - qdev_prop_set_uint32(dev, "revision", 3); > + qdev_prop_set_uint32(dev, "revision", map->gic.version); > qdev_prop_set_uint32(dev, "num-cpu", num_cpu); > qdev_prop_set_uint32(dev, "num-irq", map->gic.num_irq + 32); > - > - redist_region_count = qlist_new(); > - qlist_append_int(redist_region_count, num_cpu); > - qdev_prop_set_array(dev, "redist-region-count", redist_region_count); > - > qdev_prop_set_bit(dev, "has-security-extensions", true); > - qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its); > - object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), > &error_abort); > qdev_prop_set_uint32(dev, "first-cpu-index", first_cpu_idx); > > + if (map->gic.version == 3) { > + QList *redist_region_count; > + > + redist_region_count = qlist_new(); > + qlist_append_int(redist_region_count, num_cpu); > + qdev_prop_set_array(dev, "redist-region-count", redist_region_count); > + qdev_prop_set_bit(dev, "has-lpi", map->gic.has_its); > + object_property_set_link(OBJECT(dev), "sysmem", OBJECT(mr), > + &error_abort); > + > + } > + > sysbus_realize_and_unref(sbd, &error_fatal); > > memory_region_add_subregion(mr, map->gic.dist, > sysbus_mmio_get_region(sbd, 0)); > - memory_region_add_subregion(mr, map->gic.redist, > - sysbus_mmio_get_region(sbd, 1)); > + > + if (map->gic.version == 3) { > + memory_region_add_subregion(mr, map->gic.redist, > + sysbus_mmio_get_region(sbd, 1)); > + } else { > + memory_region_add_subregion(mr, map->gic.cpu_iface, > + sysbus_mmio_get_region(sbd, 1)); > + } > > if (map->dtb_expose) { > - node = versal_fdt_add_subnode(s, "/gic", map->gic.dist, compatible, > - sizeof(compatible)); > + if (map->gic.version == 3) { > + node = versal_fdt_add_subnode(s, "/gic", map->gic.dist, > + gicv3_compat, > + sizeof(gicv3_compat)); > + qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg", > + 2, map->gic.dist, > + 2, 0x10000, > + 2, map->gic.redist, > + 2, GICV3_REDIST_SIZE * num_cpu); > + } else { > + node = versal_fdt_add_subnode(s, "/gic", map->gic.dist, > + gicv2_compat, > + sizeof(gicv2_compat)); > + qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg", > + 2, map->gic.dist, > + 2, 0x1000, > + 2, map->gic.cpu_iface, > + 2, 0x1000); > + } > + > qemu_fdt_setprop_cell(s->cfg.fdt, node, "phandle", s->phandle.gic); > qemu_fdt_setprop_cell(s->cfg.fdt, node, "#interrupt-cells", 3); > - qemu_fdt_setprop_sized_cells(s->cfg.fdt, node, "reg", > - 2, map->gic.dist, > - 2, 0x10000, > - 2, map->gic.redist, > - 2, GICV3_REDIST_SIZE * num_cpu); > qemu_fdt_setprop_cells(s->cfg.fdt, node, "interrupts", > GIC_FDT_IRQ_TYPE_PPI, VERSAL_GIC_MAINT_IRQ, > GIC_FDT_IRQ_FLAGS_LEVEL_HI); > qemu_fdt_setprop(s->cfg.fdt, node, "interrupt-controller", NULL, 0); > } > -- > 2.50.0 >