Re: [PATCH] PCI: Fix PCI bridge resource allocation when base exceeds limit

Sizhe LIU
2026-02-04T03:58:41Z

On 2026/2/3 23:14, Ilpo Järvinen wrote:
> On Tue, 3 Feb 2026, Sizhe Liu wrote:
>
>> In pci_read_bridge_mmio_pref(), pci_read_bridge_mmio() and pci_read_bridge_io(),
>> when the MEMORY_BASE value is greater than MEMORY_LIMIT,
>> resource_set_range(res, 0, 0) is called to set both the start address
>> and the size of the address of the PCI bridge resource to 0.
>> However, the end address is later calculated as:
>> res->end = res->start + size - 1
>> As a result, the resource range becomes [0x00000000-0xffffffffffffffff]
>> instead of the expected [0x00000000-0x00000000].
> Hi,
>
> Thanks for the patch but your understanding on how resources addresses
> work is not correct.
>
> A zero sized resource should have end at start - 1, just like
> resource_set_range() sets it!

Hi,

Thanks for your correction! I agree with you.

Use [0x00000000-0xffffffffffffffff] to represent a zero-length

resource address, even though it may look misleading.

If the zero-length resource address is represented as
[0x00000000-0x00000000],

the size returned by resource_size() would be 1, which is incorrect.

>> This causes an exception in the subsequent resource claiming process,
>> because the address range [0x00000000-0xffffffffffffffff] exceeds
>> the range specified in the DSDT. The abnormal bridge triggers clipping
>> when claiming resources, then the entire parent PCI bus address range
>> becomes occupied. Other bridges on the same bus will report
>> address conflicts during their claim process. The resource allocation
>> may be degraded from 64-bit to 32-bit, or even worse, it fails.
>>
>> The related boot log is as follows:
>> pci 0000:20:00.0: PCI bridge to [bus 21]
>> pci 0000:20:00.0: bridge window [io size 0x0000 disabled]: can't claim; no address assigned
>> pci 0000:20:00.0: [io 0x0000-0xffffffffffffffff disabled] clipped to [io 0x0000-0xffff disabled]
> pci_bus_clip_resource() should not touch IORESOURCE_DISABLED resources
> nor zero sized resources. The problem seems to originate from
> pci_claim_bridge_resources() and pci_claim_bridge_resource() which try to
> claim such resources no matter what.
>
> I think pci_claim_bridge_resources() should check if IORESOURCE_DISABLED
> is set and use continue, it already has check !r->flags which probably
> worked prior to 8278c6914306 ("PCI: Preserve bridge window resource type
> flags") but is no longer enough to decided if bridge window is valid or
> not.
>
> Do you want to do that patch and test it? (I'm quite busy this week
> myself.)
No problem, I've seen your patch and I will test it later.
>> pci 0000:20:00.0: bridge window [io 0x0000-0xffff disabled]
>> pci 0000:20:00.0: bridge window [mem size 0x00000000 disabled]: can't claim; no address assigned
>> pci 0000:20:00.0: [mem 0x00000000-0xffffffffffffffff disabled] clipped to [mem 0x800000000000-0x8013ffffffff disabled]
>> pci 0000:20:00.0: bridge window [mem 0x800000000000-0x8013ffffffff disabled]: can't claim; no compatible bridge window
>> pci 0000:20:00.0: bridge window [mem size 0x00000000 64bit pref disabled]: can't claim; no address assigned
>> pci 0000:20:00.0: [mem 0x00000000-0xffffffffffffffff 64bit pref disabled] clipped to [mem 0x800000000000-0x8013ffffffff 64bit pref disabled]
>> pci 0000:20:00.0: bridge window [mem 0x800000000000-0x8013ffffffff 64bit pref disabled]
>> pci 0000:20:08.0: PCI bridge to [bus 22]
>> pci 0000:20:08.0: bridge window [io size 0x0000 disabled]: can't claim; no address assigned
>> pci 0000:20:08.0: [io 0x0000-0xffffffffffffffff disabled] clipped to [io 0x0000-0xffff disabled]
>> pci 0000:20:08.0: bridge window [io 0x0000-0xffff disabled]: can't claim; address conflict with PCI Bus 0000:21 [io 0x0000-0xffff disabled]
>> pci 0000:20:08.0: bridge window [mem size 0x00000000 disabled]: can't claim; no address assigned
>> pci 0000:20:08.0: [mem 0x00000000-0xffffffffffffffff disabled] clipped to [mem 0x800000000000-0x8013ffffffff disabled]
>> pci 0000:20:08.0: bridge window [mem 0x800000000000-0x8013ffffffff disabled]: can't claim; no compatible bridge window
>> pci 0000:20:08.0: bridge window [mem size 0x00000000 64bit pref disabled]: can't claim; no address assigned
>> pci 0000:20:08.0: [mem 0x00000000-0xffffffffffffffff 64bit pref disabled] clipped to [mem 0x800000000000-0x8013ffffffff 64bit pref disabled]
>> pci 0000:20:08.0: bridge window [mem 0x800000000000-0x8013ffffffff 64bit pref disabled]: can't claim; address conflict with PCI Bus 0000:21 [mem 0x800000000000-0x8013ffffffff 64bit pref disabled]
>> pci 0000:20:09.0: PCI bridge to [bus 23]
>> pci 0000:20:09.0: bridge window [io 0x0000-0x0fff]: can't claim; address conflict with PCI Bus 0000:21 [io 0x0000-0xffff disabled]
>> pci 0000:20:09.0: bridge window [mem 0x800003000000-0x8000048fffff 64bit pref]: can't claim; address conflict with PCI Bus 0000:21 [mem 0x800000000000-0x8013ffffffff 64bit pref disabled]
>>
>> Solution:
>> A comment in pci_read_bridge_mmio_pref() states:
>> /*
>> * Some bridges set the base > limit by default, and some
>> * (broken) BIOSes do not initialize them. If we find
>> * this, just assume they are not being used.
>> */
>> When the base is greater than the limit, a proper fix is to set the
>> resource flag to IORESOURCE_UNSET or IORESOURCE_DISABLED while keeping
>> the start and end addresses as 0. This prevents the clipping process
>> from being triggered incorrectly.
>>
>> Fixes: 8278c6914306 ("PCI: Preserve bridge window resource type flags")
>> Signed-off-by: Sizhe Liu <liusizhe5@huawei.com>
>> ---
>> drivers/pci/probe.c | 3 ---
>> 1 file changed, 3 deletions(-)
>>
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index 41183aed8f5d..561f2420d9eb 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -429,7 +429,6 @@ static void pci_read_bridge_io(struct pci_dev *dev, struct resource *res,
>> if (log)
>> pci_info(dev, " bridge window %pR\n", res);
>> } else {
>> - resource_set_range(res, 0, 0);
>> res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
>> }
>> }
>> @@ -455,7 +454,6 @@ static void pci_read_bridge_mmio(struct pci_dev *dev, struct resource *res,
>> if (log)
>> pci_info(dev, " bridge window %pR\n", res);
>> } else {
>> - resource_set_range(res, 0, 0);
>> res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
>> }
>> }
>> @@ -511,7 +509,6 @@ static void pci_read_bridge_mmio_pref(struct pci_dev *dev, struct resource *res,
>> if (log)
>> pci_info(dev, " bridge window %pR\n", res);
>> } else {
>> - resource_set_range(res, 0, 0);
>> res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
>> }
>> }
>