@samitouri / QOSamiQemu / commits / 1d2f92600d

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) {