Currently create_gic() handles GICv2 and GICv3/4 in a single
function, with large sections that are conditional on the
vms->gic_version. GICv5 will be different to both.
Refactor into create_gicv2() and create_gicv3().
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
hw/arm/virt.c | 137 ++++++++++++++++++++++++++++++--------------------
1 file changed, 82 insertions(+), 55 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 5a2cb81919..8c383d7e40 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -861,26 +861,58 @@ static void gic_connect_ppis(VirtMachineState *vms)
}
}
-static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
+static void create_gicv2(VirtMachineState *vms, MemoryRegion *mem)
{
MachineState *ms = MACHINE(vms);
/* We create a standalone GIC */
SysBusDevice *gicbusdev;
- const char *gictype;
unsigned int smp_cpus = ms->smp.cpus;
- uint32_t nb_redist_regions = 0;
- int revision;
- if (vms->gic_version == VIRT_GIC_VERSION_2) {
- gictype = gic_class_name();
- } else {
- gictype = gicv3_class_name();
+ if (kvm_enabled() && vms->virt) {
+ error_report("KVM EL2 is only supported with in-kernel GICv3");
+ exit(1);
}
+ vms->gic = qdev_new(gic_class_name());
+ qdev_prop_set_uint32(vms->gic, "revision", 2);
+ qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
+ /*
+ * Note that the num-irq property counts both internal and external
+ * interrupts; there are always 32 of the former (mandated by GIC spec).
+ */
+ qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
+ if (!kvm_irqchip_in_kernel()) {
+ qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
+ qdev_prop_set_bit(vms->gic, "has-virtualization-extensions", vms->virt);
+ }
+
+ gicbusdev = SYS_BUS_DEVICE(vms->gic);
+ sysbus_realize_and_unref(gicbusdev, &error_fatal);
+ sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
+ sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
+ if (vms->virt) {
+ sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_HYP].base);
+ sysbus_mmio_map(gicbusdev, 3, vms->memmap[VIRT_GIC_VCPU].base);
+ }
+
+ gic_connect_ppis(vms);
+
+ fdt_add_gic_node(vms);
+}
+
+static void create_gicv3(VirtMachineState *vms, MemoryRegion *mem)
+{
+ MachineState *ms = MACHINE(vms);
+ /* We create a standalone GIC */
+ SysBusDevice *gicbusdev;
+ unsigned int smp_cpus = ms->smp.cpus;
+ uint32_t nb_redist_regions;
+ int revision;
+ QList *redist_region_count;
+ uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
+ uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
+
switch (vms->gic_version) {
- case VIRT_GIC_VERSION_2:
- revision = 2;
- break;
case VIRT_GIC_VERSION_3:
revision = 3;
break;
@@ -897,10 +929,11 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
exit(1);
}
- vms->gic = qdev_new(gictype);
+ vms->gic = qdev_new(gicv3_class_name());
qdev_prop_set_uint32(vms->gic, "revision", revision);
qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
- /* Note that the num-irq property counts both internal and external
+ /*
+ * Note that the num-irq property counts both internal and external
* interrupts; there are always 32 of the former (mandated by GIC spec).
*/
qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
@@ -908,40 +941,28 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
}
- if (vms->gic_version != VIRT_GIC_VERSION_2) {
- QList *redist_region_count;
- uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
- uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
+ nb_redist_regions = virt_gicv3_redist_region_count(vms);
- nb_redist_regions = virt_gicv3_redist_region_count(vms);
+ redist_region_count = qlist_new();
+ qlist_append_int(redist_region_count, redist0_count);
+ if (nb_redist_regions == 2) {
+ uint32_t redist1_capacity =
+ virt_redist_capacity(vms, VIRT_HIGH_GIC_REDIST2);
- redist_region_count = qlist_new();
- qlist_append_int(redist_region_count, redist0_count);
- if (nb_redist_regions == 2) {
- uint32_t redist1_capacity =
- virt_redist_capacity(vms, VIRT_HIGH_GIC_REDIST2);
+ qlist_append_int(redist_region_count,
+ MIN(smp_cpus - redist0_count, redist1_capacity));
+ }
+ qdev_prop_set_array(vms->gic, "redist-region-count", redist_region_count);
- qlist_append_int(redist_region_count,
- MIN(smp_cpus - redist0_count, redist1_capacity));
- }
- qdev_prop_set_array(vms->gic, "redist-region-count",
- redist_region_count);
-
- if (!kvm_irqchip_in_kernel()) {
- if (vms->tcg_its) {
- object_property_set_link(OBJECT(vms->gic), "sysmem",
- OBJECT(mem), &error_fatal);
- qdev_prop_set_bit(vms->gic, "has-lpi", true);
- }
- } else if (vms->virt) {
- qdev_prop_set_uint32(vms->gic, "maintenance-interrupt-id",
- ARCH_GIC_MAINT_IRQ);
- }
- } else {
- if (!kvm_irqchip_in_kernel()) {
- qdev_prop_set_bit(vms->gic, "has-virtualization-extensions",
- vms->virt);
+ if (!kvm_irqchip_in_kernel()) {
+ if (vms->tcg_its) {
+ object_property_set_link(OBJECT(vms->gic), "sysmem", OBJECT(mem),
+ &error_fatal);
+ qdev_prop_set_bit(vms->gic, "has-lpi", true);
}
+ } else if (vms->virt) {
+ qdev_prop_set_uint32(vms->gic, "maintenance-interrupt-id",
+ ARCH_GIC_MAINT_IRQ);
}
if (gicv3_nmi_present(vms)) {
@@ -951,18 +972,9 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
gicbusdev = SYS_BUS_DEVICE(vms->gic);
sysbus_realize_and_unref(gicbusdev, &error_fatal);
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
- if (vms->gic_version != VIRT_GIC_VERSION_2) {
- sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
- if (nb_redist_regions == 2) {
- sysbus_mmio_map(gicbusdev, 2,
- vms->memmap[VIRT_HIGH_GIC_REDIST2].base);
- }
- } else {
- sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
- if (vms->virt) {
- sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_HYP].base);
- sysbus_mmio_map(gicbusdev, 3, vms->memmap[VIRT_GIC_VCPU].base);
- }
+ sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
+ if (nb_redist_regions == 2) {
+ sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_HIGH_GIC_REDIST2].base);
}
gic_connect_ppis(vms);
@@ -970,6 +982,21 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
fdt_add_gic_node(vms);
}
+static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
+{
+ switch (vms->gic_version) {
+ case VIRT_GIC_VERSION_2:
+ create_gicv2(vms, mem);
+ break;
+ case VIRT_GIC_VERSION_3:
+ case VIRT_GIC_VERSION_4:
+ create_gicv3(vms, mem);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
static void create_msi_controller(VirtMachineState *vms)
{
switch (vms->msi_controller) {
--
2.43.0