lspci.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
Use bridge_flags to determine address size bits (16- vs 32-bit for I/O,
32- vs 64-bit for prefetchable memory) when displaying bridge ranges
populated via PCI_FILL_BRIDGE_BASES.
Commit ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if
range behind bridge is disabled or unsupported") introduced code in
show_htype1() that reads PCI_IO_RANGE_TYPE_MASK and
PCI_MEMORY_RANGE_TYPE_MASK from bridge_base_addr[]. However,
bridge_base_addr[] holds base addresses without flags, as documented in
lib/pci.h and implemented across backends like sysfs.c and
win32-cfgmgr32.c.
Because bridge_base_addr[] does not contain configuration register flag
bits, masking the lower bits evaluates to zero. As a result, 32-bit I/O
windows are mislabeled as "[16-bit]" and 64-bit prefetchable memory
windows are mislabeled as "[32-bit]" when using PCI_FILL_BRIDGE_BASES.
Fixes: ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported")
Signed-off-by: David Matlack <dmatlack@google.com>
---
v2:
- Fix lspci.c to use bridge_flags[], per lib/pci.h, rather than
changing the behavior of just the sysfs backend (Pali Rohár)
v1: https://lore.kernel.org/linux-pci/20260626213047.189951-1-bhelgaas@google.com/
lspci.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/lspci.c b/lspci.c
index 2a14303e74f6..52fd9247aefb 100644
--- a/lspci.c
+++ b/lspci.c
@@ -571,10 +571,9 @@ show_htype1(struct device *d)
if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !io_disabled)
{
- io_base = p->bridge_base_addr[0] & PCI_IO_RANGE_MASK;
+ io_base = p->bridge_base_addr[0];
io_limit = io_base + p->bridge_size[0] - 1;
- io_type = p->bridge_base_addr[0] & PCI_IO_RANGE_TYPE_MASK;
- io_bits = (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16;
+ io_bits = (p->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) ? 16 : 32;
show_range("\tI/O behind bridge", io_base, io_limit, io_bits, io_disabled);
}
else if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
@@ -600,7 +599,7 @@ show_htype1(struct device *d)
if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !mem_disabled)
{
- mem_base = p->bridge_base_addr[1] & PCI_MEMORY_RANGE_MASK;
+ mem_base = p->bridge_base_addr[1];
mem_limit = mem_base + p->bridge_size[1] - 1;
show_range("\tMemory behind bridge", mem_base, mem_limit, 32, mem_disabled);
}
@@ -616,10 +615,9 @@ show_htype1(struct device *d)
if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !pref_disabled)
{
- u64 pref_base_64 = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_MASK;
+ u64 pref_base_64 = p->bridge_base_addr[2];
u64 pref_limit_64 = pref_base_64 + p->bridge_size[2] - 1;
- pref_type = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_TYPE_MASK;
- pref_bits = (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32;
+ pref_bits = (p->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ? 64 : 32;
show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64, pref_bits, pref_disabled);
}
else if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
base-commit: b41ce14da749fb44ca7940ba9797027bfa62c23e
--
2.55.0.766.g2966f0265a-goog
Hello!
> Use bridge_flags to determine address size bits (16- vs 32-bit for I/O,
> 32- vs 64-bit for prefetchable memory) when displaying bridge ranges
> populated via PCI_FILL_BRIDGE_BASES.
>
> Commit ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if
> range behind bridge is disabled or unsupported") introduced code in
> show_htype1() that reads PCI_IO_RANGE_TYPE_MASK and
> PCI_MEMORY_RANGE_TYPE_MASK from bridge_base_addr[]. However,
> bridge_base_addr[] holds base addresses without flags, as documented in
> lib/pci.h and implemented across backends like sysfs.c and
> win32-cfgmgr32.c.
>
> Because bridge_base_addr[] does not contain configuration register flag
> bits, masking the lower bits evaluates to zero. As a result, 32-bit I/O
> windows are mislabeled as "[16-bit]" and 64-bit prefetchable memory
> windows are mislabeled as "[32-bit]" when using PCI_FILL_BRIDGE_BASES.
>
> Fixes: ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported")
> Signed-off-by: David Matlack <dmatlack@google.com>
Thanks, applied.
Unfortunately, the current system of test cases cannot handle this
type of errors, because it is based solely on parsing dumps. Maybe
we should collect sysfs subtrees instead?
Martin
Hello! Thank you for taking this issue. I briefly checked the change and
I think that this is the right way how to address that issue.
Anyway, it would be nice to provide some example of config space of PCI
Bridge (lspci -x) which is affected by this issue and have it in
pciutils/tests/ directory.
On Friday 21 August 2026 22:15:59 David Matlack wrote:
> Use bridge_flags to determine address size bits (16- vs 32-bit for I/O,
> 32- vs 64-bit for prefetchable memory) when displaying bridge ranges
> populated via PCI_FILL_BRIDGE_BASES.
>
> Commit ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if
> range behind bridge is disabled or unsupported") introduced code in
> show_htype1() that reads PCI_IO_RANGE_TYPE_MASK and
> PCI_MEMORY_RANGE_TYPE_MASK from bridge_base_addr[]. However,
> bridge_base_addr[] holds base addresses without flags, as documented in
> lib/pci.h and implemented across backends like sysfs.c and
> win32-cfgmgr32.c.
>
> Because bridge_base_addr[] does not contain configuration register flag
> bits, masking the lower bits evaluates to zero. As a result, 32-bit I/O
> windows are mislabeled as "[16-bit]" and 64-bit prefetchable memory
> windows are mislabeled as "[32-bit]" when using PCI_FILL_BRIDGE_BASES.
>
> Fixes: ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported")
> Signed-off-by: David Matlack <dmatlack@google.com>
> ---
> v2:
> - Fix lspci.c to use bridge_flags[], per lib/pci.h, rather than
> changing the behavior of just the sysfs backend (Pali Rohár)
>
> v1: https://lore.kernel.org/linux-pci/20260626213047.189951-1-bhelgaas@google.com/
>
> lspci.c | 12 +++++-------
> 1 file changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/lspci.c b/lspci.c
> index 2a14303e74f6..52fd9247aefb 100644
> --- a/lspci.c
> +++ b/lspci.c
> @@ -571,10 +571,9 @@ show_htype1(struct device *d)
>
> if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !io_disabled)
> {
> - io_base = p->bridge_base_addr[0] & PCI_IO_RANGE_MASK;
> + io_base = p->bridge_base_addr[0];
> io_limit = io_base + p->bridge_size[0] - 1;
> - io_type = p->bridge_base_addr[0] & PCI_IO_RANGE_TYPE_MASK;
> - io_bits = (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16;
> + io_bits = (p->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) ? 16 : 32;
> show_range("\tI/O behind bridge", io_base, io_limit, io_bits, io_disabled);
> }
> else if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
> @@ -600,7 +599,7 @@ show_htype1(struct device *d)
>
> if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !mem_disabled)
> {
> - mem_base = p->bridge_base_addr[1] & PCI_MEMORY_RANGE_MASK;
> + mem_base = p->bridge_base_addr[1];
> mem_limit = mem_base + p->bridge_size[1] - 1;
> show_range("\tMemory behind bridge", mem_base, mem_limit, 32, mem_disabled);
> }
> @@ -616,10 +615,9 @@ show_htype1(struct device *d)
>
> if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !pref_disabled)
> {
> - u64 pref_base_64 = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_MASK;
> + u64 pref_base_64 = p->bridge_base_addr[2];
> u64 pref_limit_64 = pref_base_64 + p->bridge_size[2] - 1;
> - pref_type = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_TYPE_MASK;
> - pref_bits = (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32;
> + pref_bits = (p->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ? 64 : 32;
> show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64, pref_bits, pref_disabled);
> }
> else if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
>
> base-commit: b41ce14da749fb44ca7940ba9797027bfa62c23e
> --
> 2.55.0.766.g2966f0265a-goog
>
On Fri, Aug 21, 2026 at 4:06 PM Pali Rohár <pali@kernel.org> wrote:
>
> Hello! Thank you for taking this issue. I briefly checked the change and
> I think that this is the right way how to address that issue.
>
> Anyway, it would be nice to provide some example of config space of PCI
> Bridge (lspci -x) which is affected by this issue and have it in
> pciutils/tests/ directory.
Ack, I will incorporate that into a v3.
> On Friday 21 August 2026 22:15:59 David Matlack wrote:
> > Use bridge_flags to determine address size bits (16- vs 32-bit for I/O,
> > 32- vs 64-bit for prefetchable memory) when displaying bridge ranges
> > populated via PCI_FILL_BRIDGE_BASES.
> >
> > Commit ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if
> > range behind bridge is disabled or unsupported") introduced code in
> > show_htype1() that reads PCI_IO_RANGE_TYPE_MASK and
> > PCI_MEMORY_RANGE_TYPE_MASK from bridge_base_addr[]. However,
> > bridge_base_addr[] holds base addresses without flags, as documented in
> > lib/pci.h and implemented across backends like sysfs.c and
> > win32-cfgmgr32.c.
> >
> > Because bridge_base_addr[] does not contain configuration register flag
> > bits, masking the lower bits evaluates to zero. As a result, 32-bit I/O
> > windows are mislabeled as "[16-bit]" and 64-bit prefetchable memory
> > windows are mislabeled as "[32-bit]" when using PCI_FILL_BRIDGE_BASES.
> >
> > Fixes: ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported")
> > Signed-off-by: David Matlack <dmatlack@google.com>
> > ---
> > v2:
> > - Fix lspci.c to use bridge_flags[], per lib/pci.h, rather than
> > changing the behavior of just the sysfs backend (Pali Rohár)
> >
> > v1: https://lore.kernel.org/linux-pci/20260626213047.189951-1-bhelgaas@google.com/
> >
> > lspci.c | 12 +++++-------
> > 1 file changed, 5 insertions(+), 7 deletions(-)
> >
> > diff --git a/lspci.c b/lspci.c
> > index 2a14303e74f6..52fd9247aefb 100644
> > --- a/lspci.c
> > +++ b/lspci.c
> > @@ -571,10 +571,9 @@ show_htype1(struct device *d)
> >
> > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !io_disabled)
> > {
> > - io_base = p->bridge_base_addr[0] & PCI_IO_RANGE_MASK;
> > + io_base = p->bridge_base_addr[0];
> > io_limit = io_base + p->bridge_size[0] - 1;
> > - io_type = p->bridge_base_addr[0] & PCI_IO_RANGE_TYPE_MASK;
> > - io_bits = (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16;
> > + io_bits = (p->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) ? 16 : 32;
> > show_range("\tI/O behind bridge", io_base, io_limit, io_bits, io_disabled);
> > }
> > else if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
> > @@ -600,7 +599,7 @@ show_htype1(struct device *d)
> >
> > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !mem_disabled)
> > {
> > - mem_base = p->bridge_base_addr[1] & PCI_MEMORY_RANGE_MASK;
> > + mem_base = p->bridge_base_addr[1];
> > mem_limit = mem_base + p->bridge_size[1] - 1;
> > show_range("\tMemory behind bridge", mem_base, mem_limit, 32, mem_disabled);
> > }
> > @@ -616,10 +615,9 @@ show_htype1(struct device *d)
> >
> > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !pref_disabled)
> > {
> > - u64 pref_base_64 = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_MASK;
> > + u64 pref_base_64 = p->bridge_base_addr[2];
> > u64 pref_limit_64 = pref_base_64 + p->bridge_size[2] - 1;
> > - pref_type = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_TYPE_MASK;
> > - pref_bits = (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32;
> > + pref_bits = (p->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ? 64 : 32;
> > show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64, pref_bits, pref_disabled);
> > }
> > else if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
> >
> > base-commit: b41ce14da749fb44ca7940ba9797027bfa62c23e
> > --
> > 2.55.0.766.g2966f0265a-goog
> >
>
On Monday 24 August 2026 09:24:33 David Matlack wrote:
> On Fri, Aug 21, 2026 at 4:06 PM Pali Rohár <pali@kernel.org> wrote:
> >
> > Hello! Thank you for taking this issue. I briefly checked the change and
> > I think that this is the right way how to address that issue.
> >
> > Anyway, it would be nice to provide some example of config space of PCI
> > Bridge (lspci -x) which is affected by this issue and have it in
> > pciutils/tests/ directory.
>
> Ack, I will incorporate that into a v3.
Feel free to send it separately. No need to have it in this one change.
> > On Friday 21 August 2026 22:15:59 David Matlack wrote:
> > > Use bridge_flags to determine address size bits (16- vs 32-bit for I/O,
> > > 32- vs 64-bit for prefetchable memory) when displaying bridge ranges
> > > populated via PCI_FILL_BRIDGE_BASES.
> > >
> > > Commit ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if
> > > range behind bridge is disabled or unsupported") introduced code in
> > > show_htype1() that reads PCI_IO_RANGE_TYPE_MASK and
> > > PCI_MEMORY_RANGE_TYPE_MASK from bridge_base_addr[]. However,
> > > bridge_base_addr[] holds base addresses without flags, as documented in
> > > lib/pci.h and implemented across backends like sysfs.c and
> > > win32-cfgmgr32.c.
> > >
> > > Because bridge_base_addr[] does not contain configuration register flag
> > > bits, masking the lower bits evaluates to zero. As a result, 32-bit I/O
> > > windows are mislabeled as "[16-bit]" and 64-bit prefetchable memory
> > > windows are mislabeled as "[32-bit]" when using PCI_FILL_BRIDGE_BASES.
> > >
> > > Fixes: ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported")
> > > Signed-off-by: David Matlack <dmatlack@google.com>
> > > ---
> > > v2:
> > > - Fix lspci.c to use bridge_flags[], per lib/pci.h, rather than
> > > changing the behavior of just the sysfs backend (Pali Rohár)
> > >
> > > v1: https://lore.kernel.org/linux-pci/20260626213047.189951-1-bhelgaas@google.com/
> > >
> > > lspci.c | 12 +++++-------
> > > 1 file changed, 5 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/lspci.c b/lspci.c
> > > index 2a14303e74f6..52fd9247aefb 100644
> > > --- a/lspci.c
> > > +++ b/lspci.c
> > > @@ -571,10 +571,9 @@ show_htype1(struct device *d)
> > >
> > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !io_disabled)
> > > {
> > > - io_base = p->bridge_base_addr[0] & PCI_IO_RANGE_MASK;
> > > + io_base = p->bridge_base_addr[0];
> > > io_limit = io_base + p->bridge_size[0] - 1;
> > > - io_type = p->bridge_base_addr[0] & PCI_IO_RANGE_TYPE_MASK;
> > > - io_bits = (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16;
> > > + io_bits = (p->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) ? 16 : 32;
> > > show_range("\tI/O behind bridge", io_base, io_limit, io_bits, io_disabled);
> > > }
> > > else if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
> > > @@ -600,7 +599,7 @@ show_htype1(struct device *d)
> > >
> > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !mem_disabled)
> > > {
> > > - mem_base = p->bridge_base_addr[1] & PCI_MEMORY_RANGE_MASK;
> > > + mem_base = p->bridge_base_addr[1];
> > > mem_limit = mem_base + p->bridge_size[1] - 1;
> > > show_range("\tMemory behind bridge", mem_base, mem_limit, 32, mem_disabled);
> > > }
> > > @@ -616,10 +615,9 @@ show_htype1(struct device *d)
> > >
> > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !pref_disabled)
> > > {
> > > - u64 pref_base_64 = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_MASK;
> > > + u64 pref_base_64 = p->bridge_base_addr[2];
> > > u64 pref_limit_64 = pref_base_64 + p->bridge_size[2] - 1;
> > > - pref_type = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_TYPE_MASK;
> > > - pref_bits = (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32;
> > > + pref_bits = (p->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ? 64 : 32;
> > > show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64, pref_bits, pref_disabled);
> > > }
> > > else if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
> > >
> > > base-commit: b41ce14da749fb44ca7940ba9797027bfa62c23e
> > > --
> > > 2.55.0.766.g2966f0265a-goog
> > >
> >
On Mon, Aug 24, 2026 at 10:36 AM Pali Rohár <pali@kernel.org> wrote:
>
> On Monday 24 August 2026 09:24:33 David Matlack wrote:
> > On Fri, Aug 21, 2026 at 4:06 PM Pali Rohár <pali@kernel.org> wrote:
> > >
> > > Hello! Thank you for taking this issue. I briefly checked the change and
> > > I think that this is the right way how to address that issue.
> > >
> > > Anyway, it would be nice to provide some example of config space of PCI
> > > Bridge (lspci -x) which is affected by this issue and have it in
> > > pciutils/tests/ directory.
> >
> > Ack, I will incorporate that into a v3.
>
> Feel free to send it separately. No need to have it in this one change.
Sure, I can send a 2 patch series in v3 if that's what you mean?
By the way, since lspci parsing of the pciutils/tests/ directory would
use the dump backend, which does not use PCI_FILL_BRIDGE_BASES, it
will not exercise the bug fixed by this commit. Is it still worth
adding the test case? I am happy to send it, but I'm curious how it
will be used.
>
> > > On Friday 21 August 2026 22:15:59 David Matlack wrote:
> > > > Use bridge_flags to determine address size bits (16- vs 32-bit for I/O,
> > > > 32- vs 64-bit for prefetchable memory) when displaying bridge ranges
> > > > populated via PCI_FILL_BRIDGE_BASES.
> > > >
> > > > Commit ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if
> > > > range behind bridge is disabled or unsupported") introduced code in
> > > > show_htype1() that reads PCI_IO_RANGE_TYPE_MASK and
> > > > PCI_MEMORY_RANGE_TYPE_MASK from bridge_base_addr[]. However,
> > > > bridge_base_addr[] holds base addresses without flags, as documented in
> > > > lib/pci.h and implemented across backends like sysfs.c and
> > > > win32-cfgmgr32.c.
> > > >
> > > > Because bridge_base_addr[] does not contain configuration register flag
> > > > bits, masking the lower bits evaluates to zero. As a result, 32-bit I/O
> > > > windows are mislabeled as "[16-bit]" and 64-bit prefetchable memory
> > > > windows are mislabeled as "[32-bit]" when using PCI_FILL_BRIDGE_BASES.
> > > >
> > > > Fixes: ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported")
> > > > Signed-off-by: David Matlack <dmatlack@google.com>
> > > > ---
> > > > v2:
> > > > - Fix lspci.c to use bridge_flags[], per lib/pci.h, rather than
> > > > changing the behavior of just the sysfs backend (Pali Rohár)
> > > >
> > > > v1: https://lore.kernel.org/linux-pci/20260626213047.189951-1-bhelgaas@google.com/
> > > >
> > > > lspci.c | 12 +++++-------
> > > > 1 file changed, 5 insertions(+), 7 deletions(-)
> > > >
> > > > diff --git a/lspci.c b/lspci.c
> > > > index 2a14303e74f6..52fd9247aefb 100644
> > > > --- a/lspci.c
> > > > +++ b/lspci.c
> > > > @@ -571,10 +571,9 @@ show_htype1(struct device *d)
> > > >
> > > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !io_disabled)
> > > > {
> > > > - io_base = p->bridge_base_addr[0] & PCI_IO_RANGE_MASK;
> > > > + io_base = p->bridge_base_addr[0];
> > > > io_limit = io_base + p->bridge_size[0] - 1;
> > > > - io_type = p->bridge_base_addr[0] & PCI_IO_RANGE_TYPE_MASK;
> > > > - io_bits = (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16;
> > > > + io_bits = (p->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) ? 16 : 32;
> > > > show_range("\tI/O behind bridge", io_base, io_limit, io_bits, io_disabled);
> > > > }
> > > > else if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
> > > > @@ -600,7 +599,7 @@ show_htype1(struct device *d)
> > > >
> > > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !mem_disabled)
> > > > {
> > > > - mem_base = p->bridge_base_addr[1] & PCI_MEMORY_RANGE_MASK;
> > > > + mem_base = p->bridge_base_addr[1];
> > > > mem_limit = mem_base + p->bridge_size[1] - 1;
> > > > show_range("\tMemory behind bridge", mem_base, mem_limit, 32, mem_disabled);
> > > > }
> > > > @@ -616,10 +615,9 @@ show_htype1(struct device *d)
> > > >
> > > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !pref_disabled)
> > > > {
> > > > - u64 pref_base_64 = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_MASK;
> > > > + u64 pref_base_64 = p->bridge_base_addr[2];
> > > > u64 pref_limit_64 = pref_base_64 + p->bridge_size[2] - 1;
> > > > - pref_type = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_TYPE_MASK;
> > > > - pref_bits = (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32;
> > > > + pref_bits = (p->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ? 64 : 32;
> > > > show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64, pref_bits, pref_disabled);
> > > > }
> > > > else if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
> > > >
> > > > base-commit: b41ce14da749fb44ca7940ba9797027bfa62c23e
> > > > --
> > > > 2.55.0.766.g2966f0265a-goog
> > > >
> > >
On Monday 24 August 2026 13:22:32 David Matlack wrote:
> On Mon, Aug 24, 2026 at 10:36 AM Pali Rohár <pali@kernel.org> wrote:
> >
> > On Monday 24 August 2026 09:24:33 David Matlack wrote:
> > > On Fri, Aug 21, 2026 at 4:06 PM Pali Rohár <pali@kernel.org> wrote:
> > > >
> > > > Hello! Thank you for taking this issue. I briefly checked the change and
> > > > I think that this is the right way how to address that issue.
> > > >
> > > > Anyway, it would be nice to provide some example of config space of PCI
> > > > Bridge (lspci -x) which is affected by this issue and have it in
> > > > pciutils/tests/ directory.
> > >
> > > Ack, I will incorporate that into a v3.
> >
> > Feel free to send it separately. No need to have it in this one change.
>
> Sure, I can send a 2 patch series in v3 if that's what you mean?
>
> By the way, since lspci parsing of the pciutils/tests/ directory would
> use the dump backend, which does not use PCI_FILL_BRIDGE_BASES, it
> will not exercise the bug fixed by this commit. Is it still worth
> adding the test case? I am happy to send it, but I'm curious how it
> will be used.
I see. Those flags cannot be read from the PCI config space and they
need to be provided by OS when it is doing enumeration / setup of PCI.
So lspci -x dump outputs will not provide them.
> >
> > > > On Friday 21 August 2026 22:15:59 David Matlack wrote:
> > > > > Use bridge_flags to determine address size bits (16- vs 32-bit for I/O,
> > > > > 32- vs 64-bit for prefetchable memory) when displaying bridge ranges
> > > > > populated via PCI_FILL_BRIDGE_BASES.
> > > > >
> > > > > Commit ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if
> > > > > range behind bridge is disabled or unsupported") introduced code in
> > > > > show_htype1() that reads PCI_IO_RANGE_TYPE_MASK and
> > > > > PCI_MEMORY_RANGE_TYPE_MASK from bridge_base_addr[]. However,
> > > > > bridge_base_addr[] holds base addresses without flags, as documented in
> > > > > lib/pci.h and implemented across backends like sysfs.c and
> > > > > win32-cfgmgr32.c.
> > > > >
> > > > > Because bridge_base_addr[] does not contain configuration register flag
> > > > > bits, masking the lower bits evaluates to zero. As a result, 32-bit I/O
> > > > > windows are mislabeled as "[16-bit]" and 64-bit prefetchable memory
> > > > > windows are mislabeled as "[32-bit]" when using PCI_FILL_BRIDGE_BASES.
> > > > >
> > > > > Fixes: ccf68033a452 ("lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported")
> > > > > Signed-off-by: David Matlack <dmatlack@google.com>
> > > > > ---
> > > > > v2:
> > > > > - Fix lspci.c to use bridge_flags[], per lib/pci.h, rather than
> > > > > changing the behavior of just the sysfs backend (Pali Rohár)
> > > > >
> > > > > v1: https://lore.kernel.org/linux-pci/20260626213047.189951-1-bhelgaas@google.com/
> > > > >
> > > > > lspci.c | 12 +++++-------
> > > > > 1 file changed, 5 insertions(+), 7 deletions(-)
> > > > >
> > > > > diff --git a/lspci.c b/lspci.c
> > > > > index 2a14303e74f6..52fd9247aefb 100644
> > > > > --- a/lspci.c
> > > > > +++ b/lspci.c
> > > > > @@ -571,10 +571,9 @@ show_htype1(struct device *d)
> > > > >
> > > > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !io_disabled)
> > > > > {
> > > > > - io_base = p->bridge_base_addr[0] & PCI_IO_RANGE_MASK;
> > > > > + io_base = p->bridge_base_addr[0];
> > > > > io_limit = io_base + p->bridge_size[0] - 1;
> > > > > - io_type = p->bridge_base_addr[0] & PCI_IO_RANGE_TYPE_MASK;
> > > > > - io_bits = (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16;
> > > > > + io_bits = (p->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) ? 16 : 32;
> > > > > show_range("\tI/O behind bridge", io_base, io_limit, io_bits, io_disabled);
> > > > > }
> > > > > else if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
> > > > > @@ -600,7 +599,7 @@ show_htype1(struct device *d)
> > > > >
> > > > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !mem_disabled)
> > > > > {
> > > > > - mem_base = p->bridge_base_addr[1] & PCI_MEMORY_RANGE_MASK;
> > > > > + mem_base = p->bridge_base_addr[1];
> > > > > mem_limit = mem_base + p->bridge_size[1] - 1;
> > > > > show_range("\tMemory behind bridge", mem_base, mem_limit, 32, mem_disabled);
> > > > > }
> > > > > @@ -616,10 +615,9 @@ show_htype1(struct device *d)
> > > > >
> > > > > if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !pref_disabled)
> > > > > {
> > > > > - u64 pref_base_64 = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_MASK;
> > > > > + u64 pref_base_64 = p->bridge_base_addr[2];
> > > > > u64 pref_limit_64 = pref_base_64 + p->bridge_size[2] - 1;
> > > > > - pref_type = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_TYPE_MASK;
> > > > > - pref_bits = (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32;
> > > > > + pref_bits = (p->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ? 64 : 32;
> > > > > show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64, pref_bits, pref_disabled);
> > > > > }
> > > > > else if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
> > > > >
> > > > > base-commit: b41ce14da749fb44ca7940ba9797027bfa62c23e
> > > > > --
> > > > > 2.55.0.766.g2966f0265a-goog
> > > > >
> > > >
On Mon, Aug 24, 2026 at 1:34 PM Pali Rohár <pali@kernel.org> wrote: > > On Monday 24 August 2026 13:22:32 David Matlack wrote: > > On Mon, Aug 24, 2026 at 10:36 AM Pali Rohár <pali@kernel.org> wrote: > > > > > > On Monday 24 August 2026 09:24:33 David Matlack wrote: > > > > On Fri, Aug 21, 2026 at 4:06 PM Pali Rohár <pali@kernel.org> wrote: > > > > > > > > > > Hello! Thank you for taking this issue. I briefly checked the change and > > > > > I think that this is the right way how to address that issue. > > > > > > > > > > Anyway, it would be nice to provide some example of config space of PCI > > > > > Bridge (lspci -x) which is affected by this issue and have it in > > > > > pciutils/tests/ directory. > > > > > > > > Ack, I will incorporate that into a v3. > > > > > > Feel free to send it separately. No need to have it in this one change. > > > > Sure, I can send a 2 patch series in v3 if that's what you mean? > > > > By the way, since lspci parsing of the pciutils/tests/ directory would > > use the dump backend, which does not use PCI_FILL_BRIDGE_BASES, it > > will not exercise the bug fixed by this commit. Is it still worth > > adding the test case? I am happy to send it, but I'm curious how it > > will be used. > > I see. Those flags cannot be read from the PCI config space and they > need to be provided by OS when it is doing enumeration / setup of PCI. > So lspci -x dump outputs will not provide them. lspci -x will provide enough information for lspci to determine the bit-size of bridge windows. But when PCI_FILL_BRIDGE_BASES is set, show_hypte1() ignores the flags in the config space and uses the OS-provided flags instead, and that's where the bug was. So when testing (./lspci -v -F tests/bridge-window-sizes), it outputted the correct bridge windows with and without the fix.
© 2016 - 2026 Red Hat, Inc.