From 38737d82f9f0168955f9944c3f8bd3bb262c7e88 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Mon, 27 Oct 2014 10:44:36 +0800 Subject: [PATCH] PCI/MSI: Add pci_msi_ignore_mask to prevent writes to MSI/MSI-X Mask Bits MSI-X vector Mask Bits are in MSI-X Tables in PCI memory space. Xen PV guests can't write to those tables. MSI vector Mask Bits are in PCI configuration space. Xen PV guests can write to config space, but those writes are ignored. Commit 0e4ccb1505a9 ("PCI: Add x86_msi.msi_mask_irq() and msix_mask_irq()") added a way to override default_mask_msi_irqs() and default_mask_msix_irqs() so they can be no-ops in Xen guests, but this is more complicated than necessary. Add "pci_msi_ignore_mask" in the core PCI MSI code. If set, default_mask_msi_irqs() and default_mask_msix_irqs() return without doing anything. This is less flexible, but much simpler. [bhelgaas: changelog] Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: David Vrabel CC: Konrad Rzeszutek Wilk CC: xen-devel@lists.xenproject.org --- arch/x86/pci/xen.c | 2 ++ drivers/pci/msi.c | 7 ++++++- include/linux/msi.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 093f5f4272d3..5ef62ed20ba4 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -427,6 +427,7 @@ int __init pci_xen_init(void) x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs; x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; + pci_msi_ignore_mask = 1; #endif return 0; } @@ -508,6 +509,7 @@ int __init pci_xen_initial_domain(void) x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; x86_msi.msi_mask_irq = xen_nop_msi_mask_irq; x86_msi.msix_mask_irq = xen_nop_msix_mask_irq; + pci_msi_ignore_mask = 1; #endif xen_setup_acpi_sci(); __acpi_register_gsi = acpi_register_gsi_xen; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9fab30af0e75..066c2fb9763a 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -23,6 +23,7 @@ #include "pci.h" static int pci_msi_enable = 1; +int pci_msi_ignore_mask; #define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) @@ -167,7 +168,7 @@ u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) { u32 mask_bits = desc->masked; - if (!desc->msi_attrib.maskbit) + if (pci_msi_ignore_mask || !desc->msi_attrib.maskbit) return 0; mask_bits &= ~mask; @@ -199,6 +200,10 @@ u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag) u32 mask_bits = desc->masked; unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; + + if (pci_msi_ignore_mask) + return 0; + mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; if (flag) mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; diff --git a/include/linux/msi.h b/include/linux/msi.h index 44f4746d033b..86dc501a1534 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -10,6 +10,7 @@ struct msi_msg { u32 data; /* 16 bits of msi message data */ }; +extern int pci_msi_ignore_mask; /* Helper functions */ struct irq_data; struct msi_desc; -- 2.20.1