hw/arm/virt: Split GICv2 and GICv3/4 creation
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> Message-id: 20260327111700.795099-60-peter.maydell@linaro.org
Peter Maydell committed
Mar 27, 2026 at 11:16 UTC
1d2f92600ddaf14107b439f48f189c464e462f07
1 file changed
+83
-56
hw/arm/virt.c
+83
-56
@@ -1187,26 +1187,58 @@ static void gic_connect_ppis(VirtMachineState *vms)
1187
}
1188
}
1189
1190
-static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
1190
+static void create_gicv2(VirtMachineState *vms, MemoryRegion *mem)
1191
{
1192
MachineState *ms = MACHINE(vms);
1193
/* We create a standalone GIC */
1194
SysBusDevice *gicbusdev;
1195
- const char *gictype;
1195
unsigned int smp_cpus = ms->smp.cpus;
1197
- uint32_t nb_redist_regions = 0;
1198
- int revision;
1196
1200
- if (vms->gic_version == VIRT_GIC_VERSION_2) {
1201
- gictype = gic_class_name();
1202
- } else {
1203
- gictype = gicv3_class_name();
1197
+ if (kvm_enabled() && vms->virt) {
1198
+ error_report("KVM EL2 is only supported with in-kernel GICv3");
1199
+ exit(1);
1200
+ }
1201
+
1202
+ vms->gic = qdev_new(gic_class_name());
1203
+ qdev_prop_set_uint32(vms->gic, "revision", 2);
1204
+ qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
1205
+ /*
1206
+ * Note that the num-irq property counts both internal and external
1207
+ * interrupts; there are always 32 of the former (mandated by GIC spec).
1208
+ */
1209
+ qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
1210
+ if (!kvm_irqchip_in_kernel()) {
1211
+ qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
1212
+ qdev_prop_set_bit(vms->gic, "has-virtualization-extensions", vms->virt);
1213
+ }
1214
+
1215
+ gicbusdev = SYS_BUS_DEVICE(vms->gic);
1216
+ sysbus_realize_and_unref(gicbusdev, &error_fatal);
1217
+ sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
1218
+ sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
1219
+ if (vms->virt) {
1220
+ sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_HYP].base);
1221
+ sysbus_mmio_map(gicbusdev, 3, vms->memmap[VIRT_GIC_VCPU].base);
1222
}
1223
1224
+ gic_connect_ppis(vms);
1225
+
1226
+ fdt_add_gic_node(vms);
1227
+}
1228
+
1229
+static void create_gicv3(VirtMachineState *vms, MemoryRegion *mem)
1230
+{
1231
+ MachineState *ms = MACHINE(vms);
1232
+ /* We create a standalone GIC */
1233
+ SysBusDevice *gicbusdev;
1234
+ unsigned int smp_cpus = ms->smp.cpus;
1235
+ uint32_t nb_redist_regions;
1236
+ int revision;
1237
+ QList *redist_region_count;
1238
+ uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
1239
+ uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
1240
+
1241
switch (vms->gic_version) {
1207
- case VIRT_GIC_VERSION_2:
1208
- revision = 2;
1209
- break;
1242
case VIRT_GIC_VERSION_3:
1243
revision = 3;
1244
break;
@@ -1223,10 +1255,11 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
1255
exit(1);
1256
}
1257
1226
- vms->gic = qdev_new(gictype);
1258
+ vms->gic = qdev_new(gicv3_class_name());
1259
qdev_prop_set_uint32(vms->gic, "revision", revision);
1260
qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
1229
- /* Note that the num-irq property counts both internal and external
1261
+ /*
1262
+ * Note that the num-irq property counts both internal and external
1263
* interrupts; there are always 32 of the former (mandated by GIC spec).
1264
*/
1265
qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
@@ -1234,41 +1267,29 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
1267
qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure);
1268
}
1269
1237
- if (vms->gic_version != VIRT_GIC_VERSION_2) {
1238
- QList *redist_region_count;
1239
- uint32_t redist0_capacity = virt_redist_capacity(vms, VIRT_GIC_REDIST);
1240
- uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
1270
+ nb_redist_regions = virt_gicv3_redist_region_count(vms);
1271
1242
- nb_redist_regions = virt_gicv3_redist_region_count(vms);
1272
+ redist_region_count = qlist_new();
1273
+ qlist_append_int(redist_region_count, redist0_count);
1274
+ if (nb_redist_regions == 2) {
1275
+ uint32_t redist1_capacity =
1276
+ virt_redist_capacity(vms, VIRT_HIGH_GIC_REDIST2);
1277
1244
- redist_region_count = qlist_new();
1245
- qlist_append_int(redist_region_count, redist0_count);
1246
- if (nb_redist_regions == 2) {
1247
- uint32_t redist1_capacity =
1248
- virt_redist_capacity(vms, VIRT_HIGH_GIC_REDIST2);
1278
+ qlist_append_int(redist_region_count,
1279
+ MIN(smp_cpus - redist0_count, redist1_capacity));
1280
+ }
1281
+ qdev_prop_set_array(vms->gic, "redist-region-count", redist_region_count);
1282
1250
- qlist_append_int(redist_region_count,
1251
- MIN(smp_cpus - redist0_count, redist1_capacity));
1252
- }
1253
- qdev_prop_set_array(vms->gic, "redist-region-count",
1254
- redist_region_count);
1255
-
1256
- if (!kvm_irqchip_in_kernel() &&
1257
- !(hvf_enabled() && hvf_irqchip_in_kernel())) {
1258
- if (vms->tcg_its) {
1259
- object_property_set_link(OBJECT(vms->gic), "sysmem",
1260
- OBJECT(mem), &error_fatal);
1261
- qdev_prop_set_bit(vms->gic, "has-lpi", true);
1262
- }
1263
- } else if (vms->virt) {
1264
- qdev_prop_set_uint32(vms->gic, "maintenance-interrupt-id",
1265
- ARCH_GIC_MAINT_IRQ);
1266
- }
1267
- } else {
1268
- if (!kvm_irqchip_in_kernel() && !hvf_irqchip_in_kernel()) {
1269
- qdev_prop_set_bit(vms->gic, "has-virtualization-extensions",
1270
- vms->virt);
1283
+ if (!kvm_irqchip_in_kernel() &&
1284
+ !(hvf_enabled() && hvf_irqchip_in_kernel())) {
1285
+ if (vms->tcg_its) {
1286
+ object_property_set_link(OBJECT(vms->gic), "sysmem", OBJECT(mem),
1287
+ &error_fatal);
1288
+ qdev_prop_set_bit(vms->gic, "has-lpi", true);
1289
}
1290
+ } else if (vms->virt) {
1291
+ qdev_prop_set_uint32(vms->gic, "maintenance-interrupt-id",
1292
+ ARCH_GIC_MAINT_IRQ);
1293
}
1294
1295
if (gicv3_nmi_present(vms)) {
@@ -1278,18 +1299,9 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
1299
gicbusdev = SYS_BUS_DEVICE(vms->gic);
1300
sysbus_realize_and_unref(gicbusdev, &error_fatal);
1301
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
1281
- if (vms->gic_version != VIRT_GIC_VERSION_2) {
1282
- sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
1283
- if (nb_redist_regions == 2) {
1284
- sysbus_mmio_map(gicbusdev, 2,
1285
- vms->memmap[VIRT_HIGH_GIC_REDIST2].base);
1286
- }
1287
- } else {
1288
- sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
1289
- if (vms->virt) {
1290
- sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_HYP].base);
1291
- sysbus_mmio_map(gicbusdev, 3, vms->memmap[VIRT_GIC_VCPU].base);
1292
- }
1302
+ sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
1303
+ if (nb_redist_regions == 2) {
1304
+ sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_HIGH_GIC_REDIST2].base);
1305
}
1306
1307
gic_connect_ppis(vms);
@@ -1297,6 +1309,21 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
1309
fdt_add_gic_node(vms);
1310
}
1311
1312
+static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
1313
+{
1314
+ switch (vms->gic_version) {
1315
+ case VIRT_GIC_VERSION_2:
1316
+ create_gicv2(vms, mem);
1317
+ break;
1318
+ case VIRT_GIC_VERSION_3:
1319
+ case VIRT_GIC_VERSION_4:
1320
+ create_gicv3(vms, mem);
1321
+ break;
1322
+ default:
1323
+ g_assert_not_reached();
1324
+ }
1325
+}
1326
+
1327
static void create_msi_controller(VirtMachineState *vms)
1328
{
1329
switch (vms->msi_controller) {