]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Aug 2021 08:27:05 +0000 (10:27 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Aug 2021 08:27:05 +0000 (10:27 +0200)
added patches:
kvm-vmx-use-current-vmcs-to-query-waitpkg-support-for-msr-emulation.patch
pci-msi-correct-misleading-comments.patch
pci-msi-do-not-set-invalid-bits-in-msi-mask.patch
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
pci-msi-protect-msi_desc-masked-for-multi-msi.patch
pci-msi-use-msi_mask_irq-in-pci_msi_shutdown.patch

queue-5.4/kvm-vmx-use-current-vmcs-to-query-waitpkg-support-for-msr-emulation.patch [new file with mode: 0644]
queue-5.4/pci-msi-correct-misleading-comments.patch [new file with mode: 0644]
queue-5.4/pci-msi-do-not-set-invalid-bits-in-msi-mask.patch [new file with mode: 0644]
queue-5.4/pci-msi-enforce-msi-entry-updates-to-be-visible.patch [new file with mode: 0644]
queue-5.4/pci-msi-enforce-that-msi-x-table-entry-is-masked-for-update.patch [new file with mode: 0644]
queue-5.4/pci-msi-mask-all-unused-msi-x-entries.patch [new file with mode: 0644]
queue-5.4/pci-msi-protect-msi_desc-masked-for-multi-msi.patch [new file with mode: 0644]
queue-5.4/pci-msi-use-msi_mask_irq-in-pci_msi_shutdown.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/kvm-vmx-use-current-vmcs-to-query-waitpkg-support-for-msr-emulation.patch b/queue-5.4/kvm-vmx-use-current-vmcs-to-query-waitpkg-support-for-msr-emulation.patch
new file mode 100644 (file)
index 0000000..807ae1f
--- /dev/null
@@ -0,0 +1,41 @@
+From 7b9cae027ba3aaac295ae23a62f47876ed97da73 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Tue, 10 Aug 2021 10:19:49 -0700
+Subject: KVM: VMX: Use current VMCS to query WAITPKG support for MSR emulation
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 7b9cae027ba3aaac295ae23a62f47876ed97da73 upstream.
+
+Use the secondary_exec_controls_get() accessor in vmx_has_waitpkg() to
+effectively get the controls for the current VMCS, as opposed to using
+vmx->secondary_exec_controls, which is the cached value of KVM's desired
+controls for vmcs01 and truly not reflective of any particular VMCS.
+
+While the waitpkg control is not dynamic, i.e. vmcs01 will always hold
+the same waitpkg configuration as vmx->secondary_exec_controls, the same
+does not hold true for vmcs02 if the L1 VMM hides the feature from L2.
+If L1 hides the feature _and_ does not intercept MSR_IA32_UMWAIT_CONTROL,
+L2 could incorrectly read/write L1's virtual MSR instead of taking a #GP.
+
+Fixes: 6e3ba4abcea5 ("KVM: vmx: Emulate MSR IA32_UMWAIT_CONTROL")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20210810171952.2758100-2-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/vmx.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/kvm/vmx/vmx.h
++++ b/arch/x86/kvm/vmx/vmx.h
+@@ -512,7 +512,7 @@ static inline void decache_tsc_multiplie
+ static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx)
+ {
+-      return vmx->secondary_exec_control &
++      return secondary_exec_controls_get(vmx) &
+               SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
+ }
diff --git a/queue-5.4/pci-msi-correct-misleading-comments.patch b/queue-5.4/pci-msi-correct-misleading-comments.patch
new file mode 100644 (file)
index 0000000..41f319b
--- /dev/null
@@ -0,0 +1,45 @@
+From 689e6b5351573c38ccf92a0dd8b3e2c2241e4aff Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 29 Jul 2021 23:51:45 +0200
+Subject: PCI/MSI: Correct misleading comments
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 689e6b5351573c38ccf92a0dd8b3e2c2241e4aff upstream.
+
+The comments about preserving the cached state in pci_msi[x]_shutdown() are
+misleading as the MSI descriptors are freed right after those functions
+return. So there is nothing to restore. Preparatory change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210729222542.621609423@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi.c |    5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -960,7 +960,6 @@ static void pci_msi_shutdown(struct pci_
+       /* Return the device with MSI unmasked as initial states */
+       mask = msi_mask(desc->msi_attrib.multi_cap);
+-      /* Keep cached state to be restored */
+       __pci_msi_desc_mask_irq(desc, mask, 0);
+       /* Restore dev->irq to its default pin-assertion IRQ */
+@@ -1046,10 +1045,8 @@ static void pci_msix_shutdown(struct pci
+       }
+       /* Return the device with MSI-X masked as initial states */
+-      for_each_pci_msi_entry(entry, dev) {
+-              /* Keep cached states to be restored */
++      for_each_pci_msi_entry(entry, dev)
+               __pci_msix_desc_mask_irq(entry, 1);
+-      }
+       pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
+       pci_intx_for_msi(dev, 1);
diff --git a/queue-5.4/pci-msi-do-not-set-invalid-bits-in-msi-mask.patch b/queue-5.4/pci-msi-do-not-set-invalid-bits-in-msi-mask.patch
new file mode 100644 (file)
index 0000000..d090e4b
--- /dev/null
@@ -0,0 +1,64 @@
+From 361fd37397f77578735907341579397d5bed0a2d Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 29 Jul 2021 23:51:44 +0200
+Subject: PCI/MSI: Do not set invalid bits in MSI mask
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 361fd37397f77578735907341579397d5bed0a2d upstream.
+
+msi_mask_irq() takes a mask and a flags argument. The mask argument is used
+to mask out bits from the cached mask and the flags argument to set bits.
+
+Some places invoke it with a flags argument which sets bits which are not
+used by the device, i.e. when the device supports up to 8 vectors a full
+unmask in some places sets the mask to 0xFFFFFF00. While devices probably
+do not care, it's still bad practice.
+
+Fixes: 7ba1930db02f ("PCI MSI: Unmask MSI if setup failed")
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210729222542.568173099@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -662,21 +662,21 @@ static int msi_capability_init(struct pc
+       /* Configure MSI capability structure */
+       ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
+       if (ret) {
+-              msi_mask_irq(entry, mask, ~mask);
++              msi_mask_irq(entry, mask, 0);
+               free_msi_irqs(dev);
+               return ret;
+       }
+       ret = msi_verify_entries(dev);
+       if (ret) {
+-              msi_mask_irq(entry, mask, ~mask);
++              msi_mask_irq(entry, mask, 0);
+               free_msi_irqs(dev);
+               return ret;
+       }
+       ret = populate_msi_sysfs(dev);
+       if (ret) {
+-              msi_mask_irq(entry, mask, ~mask);
++              msi_mask_irq(entry, mask, 0);
+               free_msi_irqs(dev);
+               return ret;
+       }
+@@ -961,7 +961,7 @@ static void pci_msi_shutdown(struct pci_
+       /* Return the device with MSI unmasked as initial states */
+       mask = msi_mask(desc->msi_attrib.multi_cap);
+       /* Keep cached state to be restored */
+-      __pci_msi_desc_mask_irq(desc, mask, ~mask);
++      __pci_msi_desc_mask_irq(desc, mask, 0);
+       /* Restore dev->irq to its default pin-assertion IRQ */
+       dev->irq = desc->msi_attrib.default_irq;
diff --git a/queue-5.4/pci-msi-enforce-msi-entry-updates-to-be-visible.patch b/queue-5.4/pci-msi-enforce-msi-entry-updates-to-be-visible.patch
new file mode 100644 (file)
index 0000000..139799b
--- /dev/null
@@ -0,0 +1,54 @@
+From b9255a7cb51754e8d2645b65dd31805e282b4f3e Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 29 Jul 2021 23:51:43 +0200
+Subject: PCI/MSI: Enforce MSI[X] entry updates to be visible
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+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 <tglx@linutronix.de>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210729222542.515188147@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -338,6 +338,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;
+@@ -358,6 +361,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);
+       }
+ skip:
diff --git a/queue-5.4/pci-msi-enforce-that-msi-x-table-entry-is-masked-for-update.patch b/queue-5.4/pci-msi-enforce-that-msi-x-table-entry-is-masked-for-update.patch
new file mode 100644 (file)
index 0000000..c64630f
--- /dev/null
@@ -0,0 +1,73 @@
+From da181dc974ad667579baece33c2c8d2d1e4558d5 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+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 <tglx@linutronix.de>
+
+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 <kevin.tian@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210729222542.462096385@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi.c |   15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -316,13 +316,28 @@ void __pci_write_msi_msg(struct msi_desc
+               /* Don't touch the hardware now */
+       } else if (entry->msi_attrib.is_msix) {
+               void __iomem *base = pci_msix_desc_addr(entry);
++              bool unmasked = !(entry->masked & PCI_MSIX_ENTRY_CTRL_MASKBIT);
+               if (!base)
+                       goto skip;
++              /*
++               * 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-5.4/pci-msi-mask-all-unused-msi-x-entries.patch b/queue-5.4/pci-msi-mask-all-unused-msi-x-entries.patch
new file mode 100644 (file)
index 0000000..a3bd382
--- /dev/null
@@ -0,0 +1,181 @@
+From 7d5ec3d3612396dc6d4b76366d20ab9fc06f399f Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 29 Jul 2021 23:51:41 +0200
+Subject: PCI/MSI: Mask all unused MSI-X entries
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+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 <tglx@linutronix.de>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210729222542.403833459@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi.c |   45 +++++++++++++++++++++++++++------------------
+ 1 file changed, 27 insertions(+), 18 deletions(-)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -697,6 +697,7 @@ static int msix_setup_entries(struct pci
+ {
+       struct irq_affinity_desc *curmsk, *masks = NULL;
+       struct msi_desc *entry;
++      void __iomem *addr;
+       int ret, i;
+       int vec_count = pci_msix_vec_count(dev);
+@@ -717,6 +718,7 @@ static int msix_setup_entries(struct pci
+               entry->msi_attrib.is_msix       = 1;
+               entry->msi_attrib.is_64         = 1;
++
+               if (entries)
+                       entry->msi_attrib.entry_nr = entries[i].entry;
+               else
+@@ -728,6 +730,10 @@ static int msix_setup_entries(struct pci
+               entry->msi_attrib.default_irq   = dev->irq;
+               entry->mask_base                = base;
++              addr = pci_msix_desc_addr(entry);
++              if (addr)
++                      entry->masked = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
++
+               list_add_tail(&entry->list, dev_to_msi_list(&dev->dev));
+               if (masks)
+                       curmsk++;
+@@ -738,26 +744,25 @@ out:
+       return ret;
+ }
+-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;
+-      void __iomem *desc_addr;
+       for_each_pci_msi_entry(entry, dev) {
+-              if (entries)
+-                      entries[i++].vector = entry->irq;
++              if (entries) {
++                      entries->vector = entry->irq;
++                      entries++;
++              }
++      }
++}
+-              desc_addr = pci_msix_desc_addr(entry);
+-              if (desc_addr)
+-                      entry->masked = readl(desc_addr +
+-                                            PCI_MSIX_ENTRY_VECTOR_CTRL);
+-              else
+-                      entry->masked = 0;
++static void msix_mask_all(void __iomem *base, int tsize)
++{
++      u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT;
++      int i;
+-              msix_mask_irq(entry, 1);
+-      }
++      for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE)
++              writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL);
+ }
+ /**
+@@ -774,9 +779,9 @@ static void msix_program_entries(struct
+ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
+                               int nvec, struct irq_affinity *affd)
+ {
+-      int ret;
+-      u16 control;
+       void __iomem *base;
++      int ret, tsize;
++      u16 control;
+       /*
+        * Some devices require MSI-X to be enabled before the MSI-X
+@@ -788,12 +793,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, affd);
+       if (ret)
+               goto out_disable;
+@@ -807,7 +816,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-5.4/pci-msi-protect-msi_desc-masked-for-multi-msi.patch b/queue-5.4/pci-msi-protect-msi_desc-masked-for-multi-msi.patch
new file mode 100644 (file)
index 0000000..0464c47
--- /dev/null
@@ -0,0 +1,114 @@
+From 77e89afc25f30abd56e76a809ee2884d7c1b63ce Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 29 Jul 2021 23:51:47 +0200
+Subject: PCI/MSI: Protect msi_desc::masked for multi-MSI
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 77e89afc25f30abd56e76a809ee2884d7c1b63ce upstream.
+
+Multi-MSI uses a single MSI descriptor and there is a single mask register
+when the device supports per vector masking. To avoid reading back the mask
+register the value is cached in the MSI descriptor and updates are done by
+clearing and setting bits in the cache and writing it to the device.
+
+But nothing protects msi_desc::masked and the mask register from being
+modified concurrently on two different CPUs for two different Linux
+interrupts which belong to the same multi-MSI descriptor.
+
+Add a lock to struct device and protect any operation on the mask and the
+mask register with it.
+
+This makes the update of msi_desc::masked unconditional, but there is no
+place which requires a modification of the hardware register without
+updating the masked cache.
+
+msi_mask_irq() is now an empty wrapper which will be cleaned up in follow
+up changes.
+
+The problem goes way back to the initial support of multi-MSI, but picking
+the commit which introduced the mask cache is a valid cut off point
+(2.6.30).
+
+Fixes: f2440d9acbe8 ("PCI MSI: Refactor interrupt masking code")
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210729222542.726833414@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/core.c    |    1 +
+ drivers/pci/msi.c      |   19 ++++++++++---------
+ include/linux/device.h |    1 +
+ include/linux/msi.h    |    2 +-
+ 4 files changed, 13 insertions(+), 10 deletions(-)
+
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -1722,6 +1722,7 @@ void device_initialize(struct device *de
+       device_pm_init(dev);
+       set_dev_node(dev, -1);
+ #ifdef CONFIG_GENERIC_MSI_IRQ
++      raw_spin_lock_init(&dev->msi_lock);
+       INIT_LIST_HEAD(&dev->msi_list);
+ #endif
+       INIT_LIST_HEAD(&dev->links.consumers);
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -170,24 +170,25 @@ static inline __attribute_const__ u32 ms
+  * reliably as devices without an INTx disable bit will then generate a
+  * level IRQ which will never be cleared.
+  */
+-u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
++void __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+ {
+-      u32 mask_bits = desc->masked;
++      raw_spinlock_t *lock = &desc->dev->msi_lock;
++      unsigned long flags;
+       if (pci_msi_ignore_mask || !desc->msi_attrib.maskbit)
+-              return 0;
++              return;
+-      mask_bits &= ~mask;
+-      mask_bits |= flag;
++      raw_spin_lock_irqsave(lock, flags);
++      desc->masked &= ~mask;
++      desc->masked |= flag;
+       pci_write_config_dword(msi_desc_to_pci_dev(desc), desc->mask_pos,
+-                             mask_bits);
+-
+-      return mask_bits;
++                             desc->masked);
++      raw_spin_unlock_irqrestore(lock, flags);
+ }
+ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+ {
+-      desc->masked = __pci_msi_desc_mask_irq(desc, mask, flag);
++      __pci_msi_desc_mask_irq(desc, mask, flag);
+ }
+ static void __iomem *pci_msix_desc_addr(struct msi_desc *desc)
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -1260,6 +1260,7 @@ struct device {
+       struct dev_pin_info     *pins;
+ #endif
+ #ifdef CONFIG_GENERIC_MSI_IRQ
++      raw_spinlock_t          msi_lock;
+       struct list_head        msi_list;
+ #endif
+--- a/include/linux/msi.h
++++ b/include/linux/msi.h
+@@ -194,7 +194,7 @@ void __pci_read_msi_msg(struct msi_desc
+ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+ u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag);
+-u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
++void __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
+ void pci_msi_mask_irq(struct irq_data *data);
+ void pci_msi_unmask_irq(struct irq_data *data);
diff --git a/queue-5.4/pci-msi-use-msi_mask_irq-in-pci_msi_shutdown.patch b/queue-5.4/pci-msi-use-msi_mask_irq-in-pci_msi_shutdown.patch
new file mode 100644 (file)
index 0000000..0475d57
--- /dev/null
@@ -0,0 +1,33 @@
+From d28d4ad2a1aef27458b3383725bb179beb8d015c Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 29 Jul 2021 23:51:46 +0200
+Subject: PCI/MSI: Use msi_mask_irq() in pci_msi_shutdown()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit d28d4ad2a1aef27458b3383725bb179beb8d015c upstream.
+
+No point in using the raw write function from shutdown. Preparatory change
+to introduce proper serialization for the msi_desc::masked cache.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210729222542.674391354@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -960,7 +960,7 @@ static void pci_msi_shutdown(struct pci_
+       /* Return the device with MSI unmasked as initial states */
+       mask = msi_mask(desc->msi_attrib.multi_cap);
+-      __pci_msi_desc_mask_irq(desc, mask, 0);
++      msi_mask_irq(desc, mask, 0);
+       /* Restore dev->irq to its default pin-assertion IRQ */
+       dev->irq = desc->msi_attrib.default_irq;
index 2b17d43961c51c752297539b15bddbdc207efce8..2b9de5141177d910a86beafe76a693df439736a7 100644 (file)
@@ -47,3 +47,11 @@ x86-resctrl-fix-default-monitoring-groups-reporting.patch
 genirq-msi-ensure-deactivation-on-teardown.patch
 genirq-timings-prevent-potential-array-overflow-in-__irq_timings_store.patch
 pci-msi-enable-and-mask-msi-x-early.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
+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
+kvm-vmx-use-current-vmcs-to-query-waitpkg-support-for-msr-emulation.patch