On Thu, Jun 18, 2026 at 7:40 PM Chen Pei <[email protected]> wrote:
>
> On RISC-V QEMU virt platform with CXL enabled, the probe ordering
> of acpi_pci_root (ACPI0016) and cxl_acpi (ACPI0017) is not
> guaranteed. If cxl_acpi probes before acpi_pci_root has attached
> the CXL host bridges, the CXL port topology will be incomplete
> because to_cxl_host_bridge() silently skips devices whose PCI root
> is not yet ready.
>
> Add a _DEP object to the ACPI0017 device in the DSDT, declaring
> its dependency on the ACPI0016 CXL host bridge devices. This tells
> the OS to defer ACPI0017 enumeration until all ACPI0016 devices
> have been attached by acpi_pci_root.
>
> This requires a corresponding kernel change to call
> acpi_dev_clear_dependencies() in acpi_pci_root_add().
What happens to kernels that don't have this change?
Alistair
>
> The resulting DSDT fragment (iasl -d output) for a single CXL host
> bridge at bus 0x01 looks like:
>
> Device (CXLM)
> {
> Name (_HID, "ACPI0017")
> Name (_DEP, Package (0x01)
> {
> \_SB.PC01
> })
> Method (_STA, 0, NotSerialized)
> {
> Return (0x0B)
> }
> ...
> }
>
> Signed-off-by: Chen Pei <[email protected]>
> ---
> hw/riscv/virt-acpi-build.c | 32 ++++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
> index 309d64b322..3598e55243 100644
> --- a/hw/riscv/virt-acpi-build.c
> +++ b/hw/riscv/virt-acpi-build.c
> @@ -510,6 +510,38 @@ static void build_dsdt(GArray *table_data,
> if (s->cxl_devices_state.is_enabled) {
> Aml *cxl_dev = aml_device("CXLM");
> aml_append(cxl_dev, aml_name_decl("_HID", aml_string("ACPI0017")));
> +
> + /*
> + * Declare a _DEP on every ACPI0016 CXL host bridge so the OS
> + * defers ACPI0017 enumeration until acpi_pci_root has attached
> + * the CXL host bridges. Without this, cxl_acpi may probe before
> + * to_cxl_host_bridge() can resolve the PCI root and the CXL
> + * port topology comes up empty.
> + */
> + if (s->pci_bus) {
> + PCIBus *bus;
> + uint32_t num_cxl_hbs = 0;
> +
> + QLIST_FOREACH(bus, &s->pci_bus->child, sibling) {
> + if (pci_bus_is_root(bus) && pci_bus_is_cxl(bus)) {
> + num_cxl_hbs++;
> + }
> + }
> +
> + if (num_cxl_hbs > 0) {
> + Aml *dep_pkg = aml_package(num_cxl_hbs);
> +
> + QLIST_FOREACH(bus, &s->pci_bus->child, sibling) {
> + if (pci_bus_is_root(bus) && pci_bus_is_cxl(bus)) {
> + aml_append(dep_pkg,
> + aml_name("\\_SB.PC%.02X",
> + pci_bus_num(bus)));
> + }
> + }
> + aml_append(cxl_dev, aml_name_decl("_DEP", dep_pkg));
> + }
> + }
> +
> Aml *method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> aml_append(method, aml_return(aml_int(0x0B)));
> aml_append(cxl_dev, method);
> --
> 2.50.1
>
>