Re: [PATCH 3/4] hw/riscv/virt: Provide a 32-bit MMIO window for CXL host bridges
Junjie Cao <[email protected]>
| Newsgroups | org.nongnu.qemu-riscv,org.kernel.vger.linux-cxl,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
Hi Chen Pei,
On Fri, 21 Aug 2026 16:19:53 +0800, Chen Pei wrote:
> - The CXL host bridge _CRS is produced by the generic build_crs()
> path. EDK2's PciBusDxe only recurses into PCI-to-PCI bridges, while
> the pxb-cxl expander bridge presents as a class 0x0600 host bridge
> with a type-0 header, so firmware never enumerates behind it and
> leaves the CXL root port's window and bus-number registers unset;
> build_crs() would therefore return an empty _CRS. Simulate the
I see the same empty _CRS you traced for Igor on v2, but the cause
sits one level up: riscv virt never tells the firmware that the
expander bus is there.
etc/extra-pci-roots is how the other machines advertise expander root
buses. hw/arm/virt.c, hw/i386/pc.c and hw/hppa/machine.c all call
pci_bus_add_fw_cfg_extra_pci_roots(); arm got it in 09fad16744 as
part of the pxb enablement there. hw/riscv/virt.c has no such call,
and since PXB is default y only for Q35 and ARM_VIRT, this series is
what first brings pxb to riscv at all -- so nothing has needed that
fw_cfg entry until now.
Same binary, in-tree edk2-riscv, only difference on the command line
being -fw_cfg name=etc/extra-pci-roots,file=<le64 1>:
PciHostBridgeUtilityGetRootBridgesBusScan: 1 extra root buses ...
PciHostBridgeUtilityInitRootBridge: populated root bus 12, ...
PciBus: Resource Map for Bridge [0C|00|00]
Type = Mem32; Base = 0x40400000; Length = 0x200000; ...
Base = 0x40400000; Length = 0x10000; ... Owner = PCI [0D|00|00:10]
so PciBusDxe does go behind the pxb-cxl once it knows the root bus
exists, and it assigns the root port window and the Type3 BARs itself.
With this patch dropped and pci_bus_add_fw_cfg_extra_pci_roots()
called from virt_machine_done() instead, next to
cxl_fmws_link_targets(), the regenerated DSDT has PC0C as
DWordMemory (ResourceProducer, ...)
0x40400000, // Range Minimum
0x405FFFFF, // Range Maximum
QWordMemory (ResourceProducer, ...)
0x0000000400100000, // Range Minimum
0x000000040010FFFF, // Range Maximum
WordBusNumber (...)
0x000C, // Range Minimum
0x000D, // Range Maximum
with PCI0 keeping the rest of the 32-bit aperture
(0x40000000-0x403FFFFF and 0x40600000-0x7FFFFFFF). Firmware
partitions the aperture itself, sizes the window to what is actually
behind the bridge, and the 64-bit window comes along too. With a
second pxb-cxl added (bus_nr 12 and 200), the two bridges get
0x40400000-0x405FFFFF and 0x40600000-0x407FFFFF, so the
single-bridge limitation in the TODO would not arise either.
I have only looked at firmware enumeration and the generated tables
here, not at a booting CXL guest, so your RVA22 run may well turn up
something this misses. But if it holds, it drops the 256 MiB carve-out,
virt_cxl_init_bridge_windows() and the reset handler, and it is the
"fix UEFI to perform required initialization" option Igor raised on
v2, with the UEFI side already in place.
Many thanks,
Junjie