Re: [PATCH v2] dm: pci: fix uninitialized fdt_pci_addr fall-through in pci_get_devfn

Simon Glass <[email protected]>
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <CAFLszTg6V8MBHgxBwpjeYF_TKEDv3-V036G7zbfSOgVx=DCjNQ__15483.9684766316$1786137581$gmane$org@mail.gmail.com>
On 2026-08-06T18:18:18, Scott Moser <[email protected]> wrote:
> dm: pci: fix uninitialized fdt_pci_addr fall-through in pci_get_devfn
>
> pci_get_devfn() reads addr.phys_hi and returns the low bits of it as the
> requested devfn even on the -ENOENT branch, where ofnode_read_pci_addr()
> has NOT written *addr. The C standard leaves that read undefined; in
> practice the returned value depends on the compilers stack layout and on
> -ftrivial-auto-var-init. That value ends up in pplat->devfn (set by
> pci_uclass_child_post_bind()) and is later compared for equality in
> pci_bus_find_devfn() during PCI enumeration, so an under-determined
> value produces an under-determined driver-binding outcome.
>
> Concretely, this fires on Raspberry Pi 5 (BCM2712) when built with GCC
> -ftrivial-auto-var-init=zero. In that build addr.phys_hi is zeroed
> rather than left as stack junk, so pci_get_devfn() returns 0 for every
> DT-declared non-PCI child of a PCI bus. The Pi 5 device tree includes
> one such child under the second root complex -- the rp1 simple-bus
> node representing the on-SoC RP1 south bridge as seen from the OS
> side. Under zero-init:
>
>   * pci_uclass_child_post_bind(rp1) sets pplat->devfn = 0
>   * pci_bind_bus_devices() of the second root complex reads vendor at
>     bdf 02:00.0, calls pci_bus_find_devfn(bus, 0x0000, &dev)
>   * pci_bus_find_devfn() finds rp1 with pplat->devfn == 0x0000 == the
>     requested devfn, returns it as the pre-bound match
>   * pci_find_and_bind_driver() is skipped; the RP1 root port is never
>     bound as pci_bridge_drv and its downstream bus is never enumerated
>   * dm_pciauto_postscan_setup_bridge() then writes PCI_SUBORDINATE_BUS
>     = 0 and PCI_MEMORY_LIMIT = 0 on the root port; Linux flags the
>     bridge as "bridge configuration invalid ([bus 01-00])", the rp1
>     driver fails to enable the endpoint with -EINVAL, and every
>     RP1-hosted peripheral (USB, onboard Ethernet, ttyAMA10) is
>     non-functional for the rest of boot.
>
> Under the default -ftrivial-auto-var-init=uninitialized, addr.phys_hi
> happens to be non-zero stack residue that does not collide with the
> requested devfn, so the same code path just returns -ENODEV from
> pci_bus_find_devfn() and pci_find_and_bind_driver() correctly runs the
> fallback. The bug has been latent since introduction; -zero exposes it
> deterministically.
>
> A "reg" property that is simply absent now consistently returns -ENODEV,
> matching the documented contract in include/dm/pci.h, instead of a value
> that depends on stack state. A malformed "reg" property still returns
> -EINVAL, as it did before this fix.
>
> Fixes: b52142004fbd ("pci: Add pci_get_devfn() to extract devfn from the fdt_pci_addr")
> Signed-off-by: Dustin Kirkland <[email protected]>
> Cc: Scott Moser <[email protected]>
>
> drivers/core/util.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Simon Glass <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.