Hi Igor,

Thanks for the review.

On Mon, 27 Jul 2026 11:06:15 +0200
Igor Mammedov <[email protected]> wrote:

> I kind of dislike (basically riscv specific hack) in generic code.
> well, correct way to tackle this is
>  1: fix UEFI to perform required initialization.

I agree this is not a clean solution, and I acknowledge the concern
about putting riscv-specific behavior into the shared gpex code.

I did try the "fix UEFI" direction first. With the current EDK2
(edk2-stable202602, the same FdtPciHostBridgeLib/PciBusDxe used by
both aarch64 and riscv virt), I booted a riscv virt machine with
pxb-cxl and dumped the ECAM config space after the firmware finished
enumeration:

  - pxb-cxl (1b36:000b) on bus 0: class 0x0600 (host bridge),
    header type 0, memory/prefetchable window registers all zero;
  - cxl-rp on bus 12: memory window base > limit (empty, reset value);
  - cxl-type3 on bus 13: entire config space reads 0xffffffff,
    i.e. the firmware never enumerated behind the CXL host bridge.

The root cause is that PciBusDxe only recurses into devices for which
IS_PCI_BRIDGE() is true (header layout 1), while pxb-cxl presents
header type 0 and class 0x0600, so the firmware neither assigns it a
secondary bus number nor any MMIO window. FdtPciHostBridgeLib likewise
only consumes the single "pci-host-ecam-generic" node describing PCI0
and has no knowledge of the expander bridge. As a result build_crs()
genuinely returns an empty set on riscv today - this is not a timing
artifact.

> if you have to put a hack into QEMU, make it work with current build_crs()
> and localize 'proper simulated initialization' in riscv codebase
> (i.e. do not spread it to common codebase). But before doing it see (#1 not=
e).

Understood. Since #1 (a UEFI that performs the initialization) is not
available on riscv at the moment, the static window is currently the
only path that makes CXL host bridge _CRS usable here.

For what it is worth, this is consistent with how CXL is being handled
on the ARM side. The sbsa-ref enablement (Yuquan Wang, RFC up to v7,
"hw/arm/sbsa-ref: Support CXL Host Bridge & CFMW" [1], plus the
matching edk2-platforms RFC [2]) deliberately carves out exclusive
static MMIO32/MMIO64 and bus-number ranges for the CXL host bridge and
builds static ACPI tables, explicitly noting that it "doesn't need to
communicate CXL contents via DT to edk2". Jonathan Cameron's arm/virt
approach instead relies on EDK2 performing the enumeration and QEMU
reading the result back via build_crs(), but that depends on a recent
EDK2 with expander-bridge support that we do not have on riscv yet;
his earlier DT-binding RFC for expander bridges [3] also notes that on
the DT path QEMU has to allocate the windows itself.

[1] 
https://lore.kernel.org/all/[email protected]/
[2] 
https://op-lists.linaro.org/archives/list/[email protected]/thread/EPPN4R6KLGKYLWPOZUBWJG5HCXAAO3SQ/
[3] 
https://lore.kernel.org/all/[email protected]/

Given that, my tentative plan for v3 is to keep the static-window
approach for now but address your objection by localizing it: drop the
cxl_mmio32 field and the is_cxl branch from the common gpex code, and
instead simulate the initialization in riscv virt code so that the
existing build_crs() path produces the correct _CRS (i.e. have riscv
pre-populate the bridge window registers / range set the way a
firmware would), keeping the common codebase untouched.

Before I rework it that way, I would appreciate any suggestions you
may have on this approach.

Thanks,
Pei

Reply via email to