The pxb-cxl expander bridge presents as a class 0x0600 host bridge with a type-0 header, so EDK2's PciBusDxe never recurses into it and never assigns the CXL root port a memory window or bus numbers. As a result build_crs() produces an empty _CRS for the ACPI0016 host bridge and the CXL devices behind it are not enumerated by the OS.
Advertise the pxb-cxl expander root buses to firmware via the etc/extra-pci-roots fw_cfg file, the same way arm/virt and x86 do, by calling pci_bus_add_fw_cfg_extra_pci_roots() from virt_machine_done(). EDK2's PciBusDxe then enumerates behind the CXL host bridge and assigns the root-port window and bus numbers. The ACPI tables are rebuilt when the guest reads them (after that firmware enumeration), so build_crs() then emits a correct _CRS for the ACPI0016 host bridge. The call is made unconditionally, in line with arm/virt, pc and hppa, so plain pxb-pcie expander bridges, which likewise depend on etc/extra-pci-roots, are advertised as well; the generator simply returns nothing when there is no expander root bus. This approach also scales to multiple pxb-cxl host bridges (each gets its own window from the shared aperture) and lets firmware size the window to what is actually behind the bridge, rather than reserving a fixed carve-out. Verified by booting an RVA22 guest: the CXL root port and Type3 device enumerate, and 'cxl enable-memdev' / 'cxl create-region' / 'daxctl online-memory' bring the CXL memory online as system RAM. Reviewed-by: Junjie Cao <[email protected]> Tested-by: Junjie Cao <[email protected]> Signed-off-by: Chen Pei <[email protected]> --- v5: - Move pci_bus_add_fw_cfg_extra_pci_roots() out of the cxl block so plain pxb-pcie is advertised with cxl=off as well, in line with arm/virt, pc and hppa. hw/riscv/virt.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index e903551263..fb1941fe00 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -1246,6 +1246,15 @@ static void virt_machine_done(Notifier *notifier, void *data) cxl_fmws_link_targets(&error_fatal); } + /* + * Advertise the pxb/pxb-cxl expander root buses to firmware so that + * it enumerates behind them and assigns bus numbers and windows. For + * the CXL host bridges, build_crs() then builds the ACPI0016 _CRS + * from the resulting state when the guest reads the ACPI tables. + * This is a no-op without any expander root bus. + */ + pci_bus_add_fw_cfg_extra_pci_roots(s->fw_cfg, s->pci_bus, &error_abort); + /* * An user provided dtb must include everything, including * dynamic sysbus devices. Our FDT needs to be finalized. -- 2.50.1
