Message ID | 87iknwyp2o.ffs@tglx (mailing list archive) |
---|---|
State | Accepted |
Commit | 3ece3e8e5976c49c3f887e5923f998eabd54ff40 |
Headers | show |
Series | PCI/MSI: Handle the NOMASK flag correctly for all PCI/MSI backends | expand |
On 26.03.25 13:05, Thomas Gleixner wrote: > The conversion of the XEN specific global variable pci_msi_ignore_mask to a > MSI domain flag, missed the facts that: > > 1) Legacy architectures do not provide a interrupt domain > 2) Parent MSI domains do not necessarily have a domain info attached > > Both cases result in an unconditional NULL pointer dereference. > > Cure this by using the existing pci_msi_domain_supports() helper, which > handles all possible cases correctly. > > Fixes: c3164d2e0d18 ("PCI/MSI: Convert pci_msi_ignore_mask to per MSI domain flag") > Reported-by: Daniel Gomez <da.gomez@kernel.org> > Reported-by: Borislav Petkov <bp@alien8.de> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de> > Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> > Tested-by: Borislav Petkov <bp@alien8.de> > Tested-by: Daniel Gomez <da.gomez@kernel.org> As the patch introducing the problem went in via the Xen tree, should this fix go in via the Xen tree, too? Juergen
On 26.03.25 13:05, Thomas Gleixner wrote: > The conversion of the XEN specific global variable pci_msi_ignore_mask to a > MSI domain flag, missed the facts that: > > 1) Legacy architectures do not provide a interrupt domain > 2) Parent MSI domains do not necessarily have a domain info attached > > Both cases result in an unconditional NULL pointer dereference. > > Cure this by using the existing pci_msi_domain_supports() helper, which > handles all possible cases correctly. > > Fixes: c3164d2e0d18 ("PCI/MSI: Convert pci_msi_ignore_mask to per MSI domain flag") > Reported-by: Daniel Gomez <da.gomez@kernel.org> > Reported-by: Borislav Petkov <bp@alien8.de> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de> > Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> > Tested-by: Borislav Petkov <bp@alien8.de> > Tested-by: Daniel Gomez <da.gomez@kernel.org> Reviewed-by: Juergen Gross <jgross@suse.com> Juergen
On Wed, Mar 26 2025 at 13:09, Jürgen Groß wrote: > On 26.03.25 13:05, Thomas Gleixner wrote: >> The conversion of the XEN specific global variable pci_msi_ignore_mask to a >> MSI domain flag, missed the facts that: >> >> 1) Legacy architectures do not provide a interrupt domain >> 2) Parent MSI domains do not necessarily have a domain info attached >> >> Both cases result in an unconditional NULL pointer dereference. >> >> Cure this by using the existing pci_msi_domain_supports() helper, which >> handles all possible cases correctly. >> >> Fixes: c3164d2e0d18 ("PCI/MSI: Convert pci_msi_ignore_mask to per MSI domain flag") >> Reported-by: Daniel Gomez <da.gomez@kernel.org> >> Reported-by: Borislav Petkov <bp@alien8.de> >> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> >> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com> >> Tested-by: Borislav Petkov <bp@alien8.de> >> Tested-by: Daniel Gomez <da.gomez@kernel.org> > > As the patch introducing the problem went in via the Xen tree, should > this fix go in via the Xen tree, too? I'll queue it up now and send Linus a pull request.
--- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -285,8 +285,6 @@ static void pci_msi_set_enable(struct pc static int msi_setup_msi_desc(struct pci_dev *dev, int nvec, struct irq_affinity_desc *masks) { - const struct irq_domain *d = dev_get_msi_domain(&dev->dev); - const struct msi_domain_info *info = d->host_data; struct msi_desc desc; u16 control; @@ -297,7 +295,7 @@ static int msi_setup_msi_desc(struct pci /* Lies, damned lies, and MSIs */ if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING) control |= PCI_MSI_FLAGS_MASKBIT; - if (info->flags & MSI_FLAG_NO_MASK) + if (pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY)) control &= ~PCI_MSI_FLAGS_MASKBIT; desc.nvec_used = nvec; @@ -604,20 +602,18 @@ static void __iomem *msix_map_region(str */ void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc) { - const struct irq_domain *d = dev_get_msi_domain(&dev->dev); - const struct msi_domain_info *info = d->host_data; - desc->nvec_used = 1; desc->pci.msi_attrib.is_msix = 1; desc->pci.msi_attrib.is_64 = 1; desc->pci.msi_attrib.default_irq = dev->irq; desc->pci.mask_base = dev->msix_base; - desc->pci.msi_attrib.can_mask = !(info->flags & MSI_FLAG_NO_MASK) && - !desc->pci.msi_attrib.is_virtual; - if (desc->pci.msi_attrib.can_mask) { + + if (!pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY) && + !desc->pci.msi_attrib.is_virtual) { void __iomem *addr = pci_msix_desc_addr(desc); + desc->pci.msi_attrib.can_mask = 1; desc->pci.msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL); } } @@ -715,8 +711,6 @@ static int msix_setup_interrupts(struct static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec, struct irq_affinity *affd) { - const struct irq_domain *d = dev_get_msi_domain(&dev->dev); - const struct msi_domain_info *info = d->host_data; int ret, tsize; u16 control; @@ -747,7 +741,7 @@ static int msix_capability_init(struct p /* Disable INTX */ pci_intx_for_msi(dev, 0); - if (!(info->flags & MSI_FLAG_NO_MASK)) { + if (!pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY)) { /* * Ensure that all table entries are masked to prevent * stale entries from firing in a crash kernel.