From: Greg Kroah-Hartman Date: Wed, 18 Aug 2021 08:33:43 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v5.13.13~53 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=872b80ac85eb300683257dc08274d0d4c9ef4e6f;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: pci-msi-enforce-msi-entry-updates-to-be-visible.patch pci-msi-enforce-that-msi-x-table-entry-is-masked-for-update.patch pci-msi-mask-all-unused-msi-x-entries.patch --- diff --git a/queue-4.4/pci-msi-enforce-msi-entry-updates-to-be-visible.patch b/queue-4.4/pci-msi-enforce-msi-entry-updates-to-be-visible.patch new file mode 100644 index 00000000000..3dd6f5debcd --- /dev/null +++ b/queue-4.4/pci-msi-enforce-msi-entry-updates-to-be-visible.patch @@ -0,0 +1,55 @@ +From b9255a7cb51754e8d2645b65dd31805e282b4f3e Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Thu, 29 Jul 2021 23:51:43 +0200 +Subject: PCI/MSI: Enforce MSI[X] entry updates to be visible + +From: Thomas Gleixner + +commit b9255a7cb51754e8d2645b65dd31805e282b4f3e upstream. + +Nothing enforces the posted writes to be visible when the function +returns. Flush them even if the flush might be redundant when the entry is +masked already as the unmask will flush as well. This is either setup or a +rare affinity change event so the extra flush is not the end of the world. + +While this is more a theoretical issue especially the logic in the X86 +specific msi_set_affinity() function relies on the assumption that the +update has reached the hardware when the function returns. + +Again, as this never has been enforced the Fixes tag refers to a commit in: + git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git + +Fixes: f036d4ea5fa7 ("[PATCH] ia32 Message Signalled Interrupt support") +Signed-off-by: Thomas Gleixner +Tested-by: Marc Zyngier +Reviewed-by: Marc Zyngier +Acked-by: Bjorn Helgaas +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20210729222542.515188147@linutronix.de +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/msi.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -340,6 +340,9 @@ void __pci_write_msi_msg(struct msi_desc + + if (unmasked) + __pci_msix_desc_mask_irq(entry, 0); ++ ++ /* Ensure that the writes are visible in the device */ ++ readl(base + PCI_MSIX_ENTRY_DATA); + } else { + int pos = dev->msi_cap; + u16 msgctl; +@@ -360,6 +363,8 @@ void __pci_write_msi_msg(struct msi_desc + pci_write_config_word(dev, pos + PCI_MSI_DATA_32, + msg->data); + } ++ /* Ensure that the writes are visible in the device */ ++ pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); + } + entry->msg = *msg; + } diff --git a/queue-4.4/pci-msi-enforce-that-msi-x-table-entry-is-masked-for-update.patch b/queue-4.4/pci-msi-enforce-that-msi-x-table-entry-is-masked-for-update.patch new file mode 100644 index 00000000000..adc1b9b5cae --- /dev/null +++ b/queue-4.4/pci-msi-enforce-that-msi-x-table-entry-is-masked-for-update.patch @@ -0,0 +1,75 @@ +From da181dc974ad667579baece33c2c8d2d1e4558d5 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Thu, 29 Jul 2021 23:51:42 +0200 +Subject: PCI/MSI: Enforce that MSI-X table entry is masked for update + +From: Thomas Gleixner + +commit da181dc974ad667579baece33c2c8d2d1e4558d5 upstream. + +The specification (PCIe r5.0, sec 6.1.4.5) states: + + For MSI-X, a function is permitted to cache Address and Data values + from unmasked MSI-X Table entries. However, anytime software unmasks a + currently masked MSI-X Table entry either by clearing its Mask bit or + by clearing the Function Mask bit, the function must update any Address + or Data values that it cached from that entry. If software changes the + Address or Data value of an entry while the entry is unmasked, the + result is undefined. + +The Linux kernel's MSI-X support never enforced that the entry is masked +before the entry is modified hence the Fixes tag refers to a commit in: + git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git + +Enforce the entry to be masked across the update. + +There is no point in enforcing this to be handled at all possible call +sites as this is just pointless code duplication and the common update +function is the obvious place to enforce this. + +Fixes: f036d4ea5fa7 ("[PATCH] ia32 Message Signalled Interrupt support") +Reported-by: Kevin Tian +Signed-off-by: Thomas Gleixner +Tested-by: Marc Zyngier +Reviewed-by: Marc Zyngier +Acked-by: Bjorn Helgaas +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20210729222542.462096385@linutronix.de +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/msi.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -320,13 +320,26 @@ void __pci_write_msi_msg(struct msi_desc + if (dev->current_state != PCI_D0) { + /* Don't touch the hardware now */ + } else if (entry->msi_attrib.is_msix) { +- void __iomem *base; +- base = entry->mask_base + +- entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; ++ void __iomem *base = pci_msix_desc_addr(entry); ++ bool unmasked = !(entry->masked & PCI_MSIX_ENTRY_CTRL_MASKBIT); ++ ++ /* ++ * The specification mandates that the entry is masked ++ * when the message is modified: ++ * ++ * "If software changes the Address or Data value of an ++ * entry while the entry is unmasked, the result is ++ * undefined." ++ */ ++ if (unmasked) ++ __pci_msix_desc_mask_irq(entry, PCI_MSIX_ENTRY_CTRL_MASKBIT); + + writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR); + writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR); + writel(msg->data, base + PCI_MSIX_ENTRY_DATA); ++ ++ if (unmasked) ++ __pci_msix_desc_mask_irq(entry, 0); + } else { + int pos = dev->msi_cap; + u16 msgctl; diff --git a/queue-4.4/pci-msi-mask-all-unused-msi-x-entries.patch b/queue-4.4/pci-msi-mask-all-unused-msi-x-entries.patch new file mode 100644 index 00000000000..8ad1143d7f1 --- /dev/null +++ b/queue-4.4/pci-msi-mask-all-unused-msi-x-entries.patch @@ -0,0 +1,182 @@ +From 7d5ec3d3612396dc6d4b76366d20ab9fc06f399f Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Thu, 29 Jul 2021 23:51:41 +0200 +Subject: PCI/MSI: Mask all unused MSI-X entries + +From: Thomas Gleixner + +commit 7d5ec3d3612396dc6d4b76366d20ab9fc06f399f upstream. + +When MSI-X is enabled the ordering of calls is: + + msix_map_region(); + msix_setup_entries(); + pci_msi_setup_msi_irqs(); + msix_program_entries(); + +This has a few interesting issues: + + 1) msix_setup_entries() allocates the MSI descriptors and initializes them + except for the msi_desc:masked member which is left zero initialized. + + 2) pci_msi_setup_msi_irqs() allocates the interrupt descriptors and sets + up the MSI interrupts which ends up in pci_write_msi_msg() unless the + interrupt chip provides its own irq_write_msi_msg() function. + + 3) msix_program_entries() does not do what the name suggests. It solely + updates the entries array (if not NULL) and initializes the masked + member for each MSI descriptor by reading the hardware state and then + masks the entry. + +Obviously this has some issues: + + 1) The uninitialized masked member of msi_desc prevents the enforcement + of masking the entry in pci_write_msi_msg() depending on the cached + masked bit. Aside of that half initialized data is a NONO in general + + 2) msix_program_entries() only ensures that the actually allocated entries + are masked. This is wrong as experimentation with crash testing and + crash kernel kexec has shown. + + This limited testing unearthed that when the production kernel had more + entries in use and unmasked when it crashed and the crash kernel + allocated a smaller amount of entries, then a full scan of all entries + found unmasked entries which were in use in the production kernel. + + This is obviously a device or emulation issue as the device reset + should mask all MSI-X table entries, but obviously that's just part + of the paper specification. + +Cure this by: + + 1) Masking all table entries in hardware + 2) Initializing msi_desc::masked in msix_setup_entries() + 3) Removing the mask dance in msix_program_entries() + 4) Renaming msix_program_entries() to msix_update_entries() to + reflect the purpose of that function. + +As the masking of unused entries has never been done the Fixes tag refers +to a commit in: + git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git + +Fixes: f036d4ea5fa7 ("[PATCH] ia32 Message Signalled Interrupt support") +Signed-off-by: Thomas Gleixner +Tested-by: Marc Zyngier +Reviewed-by: Marc Zyngier +Acked-by: Bjorn Helgaas +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20210729222542.403833459@linutronix.de +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/msi.c | 45 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 31 insertions(+), 14 deletions(-) + +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -208,6 +208,12 @@ static void msi_mask_irq(struct msi_desc + __pci_msi_desc_mask_irq(desc, mask, flag); + } + ++static void __iomem *pci_msix_desc_addr(struct msi_desc *desc) ++{ ++ return desc->mask_base + ++ desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; ++} ++ + /* + * This internal function does not flush PCI writes to the device. + * All users must ensure that they read from the device before either +@@ -678,6 +684,7 @@ static int msix_setup_entries(struct pci + struct msix_entry *entries, int nvec) + { + struct msi_desc *entry; ++ void __iomem *addr; + int i; + + for (i = 0; i < nvec; i++) { +@@ -698,29 +705,35 @@ static int msix_setup_entries(struct pci + entry->mask_base = base; + entry->nvec_used = 1; + ++ addr = pci_msix_desc_addr(entry); ++ entry->masked = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL); + list_add_tail(&entry->list, dev_to_msi_list(&dev->dev)); + } + + return 0; + } + +-static void msix_program_entries(struct pci_dev *dev, +- struct msix_entry *entries) ++static void msix_update_entries(struct pci_dev *dev, struct msix_entry *entries) + { + struct msi_desc *entry; +- int i = 0; + + for_each_pci_msi_entry(entry, dev) { +- int offset = entries[i].entry * PCI_MSIX_ENTRY_SIZE + +- PCI_MSIX_ENTRY_VECTOR_CTRL; +- +- entries[i].vector = entry->irq; +- entry->masked = readl(entry->mask_base + offset); +- msix_mask_irq(entry, 1); +- i++; ++ if (entries) { ++ entries->vector = entry->irq; ++ entries++; ++ } + } + } + ++static void msix_mask_all(void __iomem *base, int tsize) ++{ ++ u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT; ++ int i; ++ ++ for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE) ++ writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL); ++} ++ + /** + * msix_capability_init - configure device's MSI-X capability + * @dev: pointer to the pci_dev data structure of MSI-X device function +@@ -734,9 +747,9 @@ static void msix_program_entries(struct + static int msix_capability_init(struct pci_dev *dev, + struct msix_entry *entries, int nvec) + { +- int ret; +- u16 control; + void __iomem *base; ++ int ret, tsize; ++ u16 control; + + /* + * Some devices require MSI-X to be enabled before the MSI-X +@@ -748,12 +761,16 @@ static int msix_capability_init(struct p + + pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); + /* Request & Map MSI-X table region */ +- base = msix_map_region(dev, msix_table_size(control)); ++ tsize = msix_table_size(control); ++ base = msix_map_region(dev, tsize); + if (!base) { + ret = -ENOMEM; + goto out_disable; + } + ++ /* Ensure that all table entries are masked. */ ++ msix_mask_all(base, tsize); ++ + ret = msix_setup_entries(dev, base, entries, nvec); + if (ret) + goto out_disable; +@@ -767,7 +784,7 @@ static int msix_capability_init(struct p + if (ret) + goto out_free; + +- msix_program_entries(dev, entries); ++ msix_update_entries(dev, entries); + + ret = populate_msi_sysfs(dev); + if (ret) diff --git a/queue-4.4/series b/queue-4.4/series index 2fa65594843..c0dc8be570c 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -8,5 +8,8 @@ pci-msi-do-not-set-invalid-bits-in-msi-mask.patch pci-msi-correct-misleading-comments.patch pci-msi-use-msi_mask_irq-in-pci_msi_shutdown.patch pci-msi-protect-msi_desc-masked-for-multi-msi.patch +pci-msi-mask-all-unused-msi-x-entries.patch +pci-msi-enforce-that-msi-x-table-entry-is-masked-for-update.patch +pci-msi-enforce-msi-entry-updates-to-be-visible.patch vmlinux.lds.h-handle-clang-s-module.-c-d-tor-sections.patch kvm-nsvm-avoid-picking-up-unsupported-bits-from-l2-in-int_ctl-cve-2021-3653.patch