From nobody Tue Jun 23 21:34:02 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53E72C433FE for ; Sat, 26 Feb 2022 10:47:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231179AbiBZKru (ORCPT ); Sat, 26 Feb 2022 05:47:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229796AbiBZKrq (ORCPT ); Sat, 26 Feb 2022 05:47:46 -0500 Received: from angie.orcam.me.uk (angie.orcam.me.uk [78.133.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 8CA5329C46F for ; Sat, 26 Feb 2022 02:47:11 -0800 (PST) Received: by angie.orcam.me.uk (Postfix, from userid 500) id 78EC392009C; Sat, 26 Feb 2022 11:47:10 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 6B9CA92009B; Sat, 26 Feb 2022 10:47:10 +0000 (GMT) Date: Sat, 26 Feb 2022 10:47:10 +0000 (GMT) From: "Maciej W. Rozycki" To: Bjorn Helgaas cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] PCI: Avoid handing out address 0 to devices Message-ID: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" We have numerous platforms that permit assigning addresses from 0 to PCI=20 devices, both in the memory and the I/O bus space, and we happily do so=20 if there is no conflict, e.g.: pci 0000:07:00.0: BAR 0: assigned [io 0x0000-0x0007] pci 0000:07:00.1: BAR 0: assigned [io 0x0008-0x000f] pci 0000:06:01.0: PCI bridge to [bus 07] pci 0000:06:01.0: bridge window [io 0x0000-0x0fff] (with the SiFive HiFive Unmatched RISC-V board and a dual serial port=20 option card based on the OxSemi OXPCIe952 device wired for the legacy=20 UART mode). Address 0 is treated specially however in many places, for example in=20 `pci_iomap_range' and `pci_iomap_wc_range' we require that the start=20 address is non-zero, and even if we let such an address through, then=20 individual device drivers could reject a request to handle a device at=20 such an address, such as in `uart_configure_port'. Consequently given devices configured as shown above only one is actually usable: Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled serial 0000:07:00.0: enabling device (0000 -> 0001) serial: probe of 0000:07:00.0 failed with error -12 serial 0000:07:00.1: enabling device (0000 -> 0001) serial 0000:07:00.1: detected caps 00000700 should be 00000500 0000:07:00.1: ttyS0 at I/O 0x8 (irq =3D 39, base_baud =3D 15625000) is a 16= C950/954 Especially I/O space ranges are particularly valuable, because bridges=20 only decode bits from 12 up and consequently where 16-bit addressing is=20 in effect, as few as 16 separate ranges can be assigned to individual=20 buses only. Therefore avoid handing out address 0, however rather than bumping the=20 lowest address available to PCI via PCIBIOS_MIN_IO and PCIBIOS_MIN_MEM,=20 or doing an equivalent arrangement in `__pci_assign_resource', let the=20 whole range assigned to a bus start from that address and instead only=20 avoid it for actual devices. Do it in `pci_bus_alloc_from_region' then=20 observing that bridge resources will have the IORESOURCE_STARTALIGN flag=20 set rather than IORESOURCE_SIZEALIGN and by making the least significant=20 bit decoded 1 according to the resource type, either memory or I/O. With this in place the system in question we have: pci 0000:07:00.0: BAR 0: assigned [io 0x0008-0x000f] pci 0000:07:00.1: BAR 0: assigned [io 0x0010-0x0017] pci 0000:06:01.0: PCI bridge to [bus 07] pci 0000:06:01.0: bridge window [io 0x0000-0x0fff] and then devices work correctly: Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled serial 0000:07:00.0: enabling device (0000 -> 0001) serial 0000:07:00.0: detected caps 00000700 should be 00000500 0000:07:00.0: ttyS0 at I/O 0x8 (irq =3D 38, base_baud =3D 15625000) is a 16= C950/954 serial 0000:07:00.1: enabling device (0000 -> 0001) serial 0000:07:00.1: detected caps 00000700 should be 00000500 0000:07:00.1: ttyS1 at I/O 0x10 (irq =3D 39, base_baud =3D 15625000) is a 1= 6C950/954 Signed-off-by: Maciej W. Rozycki --- Hi, NB I have an OxSemi OXPCIe952 based card that can be wired to either the=20 native or the legacy mode via a jumper block and I am so glad that I have=20 checked whether it works in the legacy mode as well. I guess there are so=20 few legacy-free platforms still for nobody else to notice this issue yet. I think I've chosen the right solution, but I'll be happy to hear any=20 suggestions for an alternative one. Otherwise please apply. Maciej --- drivers/pci/bus.c | 9 +++++++++ 1 file changed, 9 insertions(+) linux-pci-bus-alloc-from-region-min.diff Index: linux-macro/drivers/pci/bus.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-macro.orig/drivers/pci/bus.c +++ linux-macro/drivers/pci/bus.c @@ -194,6 +194,15 @@ static int pci_bus_alloc_from_region(str */ if (avail.start) min_used =3D avail.start; + /* + * For non-bridge resources avoid assigning address 0 as + * we assume that to mean no assignment in many places, + * starting from `pci_iomap_range'. + */ + if (min_used =3D=3D 0 && (res->flags & IORESOURCE_SIZEALIGN)) + min_used =3D res->flags & IORESOURCE_IO ? + ~PCI_BASE_ADDRESS_IO_MASK + 1 : + ~PCI_BASE_ADDRESS_MEM_MASK + 1; =20 max =3D avail.end;