| From 408fb0e5aa7fda0059db282ff58c3b2a4278baa0 Mon Sep 17 00:00:00 2001 |
| From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Date: Mon, 2 Nov 2015 18:13:27 -0500 |
| Subject: xen/pciback: Don't allow MSI-X ops if PCI_COMMAND_MEMORY is not set. |
| |
| commit 408fb0e5aa7fda0059db282ff58c3b2a4278baa0 upstream. |
| |
| commit f598282f51 ("PCI: Fix the NIU MSI-X problem in a better way") |
| teaches us that dealing with MSI-X can be troublesome. |
| |
| Further checks in the MSI-X architecture shows that if the |
| PCI_COMMAND_MEMORY bit is turned of in the PCI_COMMAND we |
| may not be able to access the BAR (since they are memory regions). |
| |
| Since the MSI-X tables are located in there.. that can lead |
| to us causing PCIe errors. Inhibit us performing any |
| operation on the MSI-X unless the MEMORY bit is set. |
| |
| Note that Xen hypervisor with: |
| "x86/MSI-X: access MSI-X table only after having enabled MSI-X" |
| will return: |
| xen_pciback: 0000:0a:00.1: error -6 enabling MSI-X for guest 3! |
| |
| When the generic MSI code tries to setup the PIRQ without |
| MEMORY bit set. Which means with later versions of Xen |
| (4.6) this patch is not neccessary. |
| |
| This is part of XSA-157 |
| |
| Reviewed-by: Jan Beulich <jbeulich@suse.com> |
| Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Signed-off-by: Zefan Li <lizefan@huawei.com> |
| --- |
| drivers/xen/xen-pciback/pciback_ops.c | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/xen/xen-pciback/pciback_ops.c |
| +++ b/drivers/xen/xen-pciback/pciback_ops.c |
| @@ -211,6 +211,7 @@ int xen_pcibk_enable_msix(struct xen_pci |
| struct xen_pcibk_dev_data *dev_data; |
| int i, result; |
| struct msix_entry *entries; |
| + u16 cmd; |
| |
| if (unlikely(verbose_request)) |
| printk(KERN_DEBUG DRV_NAME ": %s: enable MSI-X\n", |
| @@ -222,7 +223,12 @@ int xen_pcibk_enable_msix(struct xen_pci |
| if (dev->msix_enabled) |
| return -EALREADY; |
| |
| - if (dev->msi_enabled) |
| + /* |
| + * PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able |
| + * to access the BARs where the MSI-X entries reside. |
| + */ |
| + pci_read_config_word(dev, PCI_COMMAND, &cmd); |
| + if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY)) |
| return -ENXIO; |
| |
| entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL); |