| From foo@baz Thu Dec 21 09:02:40 CET 2017 |
| From: Alex Williamson <alex.williamson@redhat.com> |
| Date: Mon, 2 Oct 2017 12:39:09 -0600 |
| Subject: vfio/pci: Virtualize Maximum Payload Size |
| |
| From: Alex Williamson <alex.williamson@redhat.com> |
| |
| |
| [ Upstream commit 523184972b282cd9ca17a76f6ca4742394856818 ] |
| |
| With virtual PCI-Express chipsets, we now see userspace/guest drivers |
| trying to match the physical MPS setting to a virtual downstream port. |
| Of course a lone physical device surrounded by virtual interconnects |
| cannot make a correct decision for a proper MPS setting. Instead, |
| let's virtualize the MPS control register so that writes through to |
| hardware are disallowed. Userspace drivers like QEMU assume they can |
| write anything to the device and we'll filter out anything dangerous. |
| Since mismatched MPS can lead to AER and other faults, let's add it |
| to the kernel side rather than relying on userspace virtualization to |
| handle it. |
| |
| Signed-off-by: Alex Williamson <alex.williamson@redhat.com> |
| Reviewed-by: Eric Auger <eric.auger@redhat.com> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/vfio/pci/vfio_pci_config.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/vfio/pci/vfio_pci_config.c |
| +++ b/drivers/vfio/pci/vfio_pci_config.c |
| @@ -851,11 +851,13 @@ static int __init init_pci_cap_exp_perm( |
| |
| /* |
| * Allow writes to device control fields, except devctl_phantom, |
| - * which could confuse IOMMU, and the ARI bit in devctl2, which |
| + * which could confuse IOMMU, MPS, which can break communication |
| + * with other physical devices, and the ARI bit in devctl2, which |
| * is set at probe time. FLR gets virtualized via our writefn. |
| */ |
| p_setw(perm, PCI_EXP_DEVCTL, |
| - PCI_EXP_DEVCTL_BCR_FLR, ~PCI_EXP_DEVCTL_PHANTOM); |
| + PCI_EXP_DEVCTL_BCR_FLR | PCI_EXP_DEVCTL_PAYLOAD, |
| + ~PCI_EXP_DEVCTL_PHANTOM); |
| p_setw(perm, PCI_EXP_DEVCTL2, NO_VIRT, ~PCI_EXP_DEVCTL2_ARI); |
| return 0; |
| } |