Skip to content

Commit b385a6f

Browse files
shivkdho28
authored andcommitted
hw/arm/xlnx-versal: include PCIe FDT node before GIC/ITS for MSI-X
Split versal_create_pcie() into two functions: versal_create_pcie_fdt(), which handles device-tree generation, and versal_create_pcie(), which handles device creation as well as IRQ wiring. The FDT generation is now invoked early in versal_realize_common(). Because fdt_add_subnode() prepends nodes, generating the PCIe node before the GIC and ITS nodes causes GIC/ITS to appear ahead of PCIe in the final DTB. This ordering ensures the ITS (MSI controller) is parsed and registered before the PCIe host bridge is enumerated, which is required for MSI-X interrupts to be delivered. Verified by booting VxWorks SMP on xlnx-versal-virt with an e1000e NIC and virtio net pci. I found that vxbPciMsiXAlloc() returns 1, the device enables MSI-X (msix_write_config: enabled 1 masked 0), and MSI-X interrupts fire (e1000e_irq_msix_notify_vec, vector 0). Signed-off-by: shivkd <shiveshkd@gmail.com>
1 parent e85993e commit b385a6f

1 file changed

Lines changed: 62 additions & 55 deletions

File tree

hw/arm/xlnx-versal.c

Lines changed: 62 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -947,60 +947,18 @@ static inline void versal_create_and_connect_gic(Versal *s,
947947
}
948948
}
949949

950-
static void versal_create_pcie(Versal *s, const struct VersalPcieMap *map)
950+
/*
951+
* Create the PCIe FDT node before the GIC/ITS FDT node is added. FDT
952+
* subnodes are prepended, so creating the PCIe node early keeps GIC/ITS
953+
* before PCIe in the final DTB. Some guests rely on this order so the
954+
* MSI controller is registered before PCIe devices are attached.
955+
*/
956+
static void versal_create_pcie_fdt(Versal *s, const struct VersalPcieMap *map)
951957
{
952-
DeviceState *dev;
953-
PCIHostState *pci;
954-
MemoryRegion *ecam_alias;
955-
MemoryRegion *ecam_reg;
956-
MemoryRegion *mmio_alias;
957-
MemoryRegion *mmio_high_alias;
958-
MemoryRegion *mmio_reg;
959-
MemoryRegion *ioport_reg;
960958
g_autofree char *node = NULL;
961959
const char compat[] = "pci-host-ecam-generic";
962960
int num_buses;
963-
int i;
964-
965-
dev = qdev_new(TYPE_GPEX_HOST);
966-
object_property_add_child(OBJECT(s), "pcie", OBJECT(dev));
967-
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
968-
969-
/* Map ECAM space */
970-
ecam_alias = g_new0(MemoryRegion, 1);
971-
ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
972-
memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
973-
ecam_reg, 0, map->ecam_size);
974-
memory_region_add_subregion(&s->mr_ps, map->ecam, ecam_alias);
975-
976-
/* Map MMIO window */
977-
mmio_alias = g_new0(MemoryRegion, 1);
978-
mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
979-
memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
980-
mmio_reg, map->mmio, map->mmio_size);
981-
memory_region_add_subregion(&s->mr_ps, map->mmio, mmio_alias);
982-
983-
/* Map high MMIO window */
984-
mmio_high_alias = g_new0(MemoryRegion, 1);
985-
memory_region_init_alias(mmio_high_alias, OBJECT(dev), "pcie-mmio-high",
986-
mmio_reg, map->mmio_high, map->mmio_high_size);
987-
memory_region_add_subregion(&s->mr_ps, map->mmio_high, mmio_high_alias);
988-
989-
/* Map IO port space */
990-
ioport_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 2);
991-
memory_region_add_subregion(&s->mr_ps, map->pio, ioport_reg);
992-
993-
/* Map IRQs */
994-
for (i = 0; i < PCI_NUM_PINS; i++) {
995-
versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), i, map->irq[i]);
996-
gpex_set_irq_num(GPEX_HOST(dev), i, map->irq[i]);
997-
}
998-
999-
/* configure root complex */
1000-
pci = PCI_HOST_BRIDGE(dev);
1001-
pci->bypass_iommu = true;
1002-
1003-
/* FDT generation */
961+
/* FDT generation */
1004962
num_buses = map->ecam_size / PCIE_MMCFG_SIZE_MIN;
1005963
node = g_strdup_printf("/pcie@%" PRIx64, map->mmio);
1006964
qemu_fdt_add_subnode(s->cfg.fdt, node);
@@ -1075,6 +1033,57 @@ static void versal_create_pcie(Versal *s, const struct VersalPcieMap *map)
10751033
compat, sizeof(compat));
10761034
}
10771035

1036+
static void versal_create_pcie(Versal *s, const struct VersalPcieMap *map)
1037+
{
1038+
DeviceState *dev;
1039+
PCIHostState *pci;
1040+
MemoryRegion *ecam_alias;
1041+
MemoryRegion *ecam_reg;
1042+
MemoryRegion *mmio_alias;
1043+
MemoryRegion *mmio_high_alias;
1044+
MemoryRegion *mmio_reg;
1045+
MemoryRegion *ioport_reg;
1046+
int i;
1047+
1048+
dev = qdev_new(TYPE_GPEX_HOST);
1049+
object_property_add_child(OBJECT(s), "pcie", OBJECT(dev));
1050+
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1051+
1052+
/* Map ECAM space */
1053+
ecam_alias = g_new0(MemoryRegion, 1);
1054+
ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
1055+
memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
1056+
ecam_reg, 0, map->ecam_size);
1057+
memory_region_add_subregion(&s->mr_ps, map->ecam, ecam_alias);
1058+
1059+
/* Map MMIO window */
1060+
mmio_alias = g_new0(MemoryRegion, 1);
1061+
mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
1062+
memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
1063+
mmio_reg, map->mmio, map->mmio_size);
1064+
memory_region_add_subregion(&s->mr_ps, map->mmio, mmio_alias);
1065+
1066+
/* Map high MMIO window */
1067+
mmio_high_alias = g_new0(MemoryRegion, 1);
1068+
memory_region_init_alias(mmio_high_alias, OBJECT(dev), "pcie-mmio-high",
1069+
mmio_reg, map->mmio_high, map->mmio_high_size);
1070+
memory_region_add_subregion(&s->mr_ps, map->mmio_high, mmio_high_alias);
1071+
1072+
/* Map IO port space */
1073+
ioport_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 2);
1074+
memory_region_add_subregion(&s->mr_ps, map->pio, ioport_reg);
1075+
1076+
/* Map IRQs */
1077+
for (i = 0; i < PCI_NUM_PINS; i++) {
1078+
versal_sysbus_connect_irq(s, SYS_BUS_DEVICE(dev), i, map->irq[i]);
1079+
gpex_set_irq_num(GPEX_HOST(dev), i, map->irq[i]);
1080+
}
1081+
1082+
/* configure root complex */
1083+
pci = PCI_HOST_BRIDGE(dev);
1084+
pci->bypass_iommu = true;
1085+
}
1086+
10781087
static DeviceState *versal_create_cpu(Versal *s,
10791088
const VersalCpuClusterMap *map,
10801089
DeviceState *qemu_cluster,
@@ -2244,10 +2253,6 @@ static void versal_realize_common(Versal *s)
22442253
versal_create_smmu(s, &map->smmu);
22452254
}
22462255

2247-
if (map->pcie.mmio) {
2248-
versal_create_pcie(s, &map->pcie);
2249-
}
2250-
22512256
if (map->lpd_iou_slcr) {
22522257
versal_create_lpd_iou_slcr(s, map->lpd_iou_slcr);
22532258
}
@@ -2289,8 +2294,10 @@ static void versal_realize_common(Versal *s)
22892294
static void versal_realize(DeviceState *dev, Error **errp)
22902295
{
22912296
Versal *s = XLNX_VERSAL_BASE(dev);
2292-
2297+
const VersalMap *map = versal_get_map(s);
2298+
versal_create_pcie_fdt(s, &map->pcie);
22932299
versal_realize_common(s);
2300+
versal_create_pcie(s, &map->pcie);
22942301
versal_unimp(s);
22952302
}
22962303

0 commit comments

Comments
 (0)