]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
PCI: pci-bridge-emul: Properly mark reserved PCIe bits in PCI config space
authorPali Rohár <pali@kernel.org>
Wed, 24 Nov 2021 15:59:40 +0000 (16:59 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jan 2022 08:19:50 +0000 (09:19 +0100)
commit 7b067ac63a5730d2fae18399fed7e45f23d36912 upstream.

Some bits in PCI config space are reserved when device is PCIe. Properly
define behavior of PCI registers for PCIe emulated bridge and ensure that
it would not be possible change these reserved bits.

Link: https://lore.kernel.org/r/20211124155944.1290-3-pali@kernel.org
Fixes: 23a5fba4d941 ("PCI: Introduce PCI bridge emulated config space common logic")
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pci/pci-bridge-emul.c

index 3026346ccb18cd060fd2b491f2e02940082a1625..e47eb2a89579e8b6b4c334989feda9c7b8b6fe63 100644 (file)
@@ -300,6 +300,27 @@ int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
                        kfree(bridge->pci_regs_behavior);
                        return -ENOMEM;
                }
+               /* These bits are applicable only for PCI and reserved on PCIe */
+               bridge->pci_regs_behavior[PCI_CACHE_LINE_SIZE / 4].ro &=
+                       ~GENMASK(15, 8);
+               bridge->pci_regs_behavior[PCI_COMMAND / 4].ro &=
+                       ~((PCI_COMMAND_SPECIAL | PCI_COMMAND_INVALIDATE |
+                          PCI_COMMAND_VGA_PALETTE | PCI_COMMAND_WAIT |
+                          PCI_COMMAND_FAST_BACK) |
+                         (PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK |
+                          PCI_STATUS_DEVSEL_MASK) << 16);
+               bridge->pci_regs_behavior[PCI_PRIMARY_BUS / 4].ro &=
+                       ~GENMASK(31, 24);
+               bridge->pci_regs_behavior[PCI_IO_BASE / 4].ro &=
+                       ~((PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK |
+                          PCI_STATUS_DEVSEL_MASK) << 16);
+               bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].rw &=
+                       ~((PCI_BRIDGE_CTL_MASTER_ABORT |
+                          BIT(8) | BIT(9) | BIT(11)) << 16);
+               bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].ro &=
+                       ~((PCI_BRIDGE_CTL_FAST_BACK) << 16);
+               bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].w1c &=
+                       ~(BIT(10) << 16);
        }
 
        if (flags & PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR) {