diff mbox series

[1/2] VT-d: don't pass bridge devices to domain_context_mapping_one()

Message ID 64149ced-6e88-abf5-2740-a43db6a0a4be@suse.com (mailing list archive)
State New, archived
Headers show
Series VT-d: domain_context_mapping_one() adjustments | expand

Commit Message

Jan Beulich Jan. 7, 2020, 7:37 a.m. UTC
When passed a non-NULL pdev, the function does an owner check when it
finds an already existing context mapping. Bridges, however, don't get
passed through to guests, and hence their owner is always going to be
Dom0, leading to the assigment of all but one of the function of multi-
function PCI devices behind bridges to fail.

Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
Note: This was reported as an apparent regression from XSA-302 / -306.
      So far I haven't been able to figure out how the code would have
      worked before, i.e. to me it looks like a pre-existing problem.
      This leaves the risk of the change here papering over another
      issue.

Comments

Tian, Kevin Jan. 19, 2020, 3:15 a.m. UTC | #1
> From: Jan Beulich <jbeulich@suse.com>
> Sent: Tuesday, January 7, 2020 3:38 PM
> 
> When passed a non-NULL pdev, the function does an owner check when it
> finds an already existing context mapping. Bridges, however, don't get
> passed through to guests, and hence their owner is always going to be
> Dom0, leading to the assigment of all but one of the function of multi-
> function PCI devices behind bridges to fail.
> 
> Reported-by: Marek Marczykowski-Górecki
> <marmarek@invisiblethingslab.com>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> ---
> Note: This was reported as an apparent regression from XSA-302 / -306.
>       So far I haven't been able to figure out how the code would have
>       worked before, i.e. to me it looks like a pre-existing problem.
>       This leaves the risk of the change here papering over another
>       issue.
> 
> --- a/xen/drivers/passthrough/vtd/iommu.c
> +++ b/xen/drivers/passthrough/vtd/iommu.c
> @@ -1499,7 +1499,7 @@ static int domain_context_mapping(struct
>              break;
> 
>          ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
> -                                         pci_get_pdev(seg, bus, devfn));
> +                                         NULL);

the relationship between NULL and a bridge device is not obvious
by just looking at the code. Can you at least add some comment
here, or possibly be clearer by having a mapping_bridge wrapper?

> 
>          /*
>           * Devices behind PCIe-to-PCI/PCIx bridge may generate different
> @@ -1509,7 +1509,7 @@ static int domain_context_mapping(struct
>          if ( !ret && pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE
> &&
>               (secbus != pdev->bus || pdev->devfn != 0) )
>              ret = domain_context_mapping_one(domain, drhd->iommu, secbus,
> 0,
> -                                             pci_get_pdev(seg, secbus, 0));
> +                                             NULL);
> 
>          break;
>
diff mbox series

Patch

--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -1499,7 +1499,7 @@  static int domain_context_mapping(struct
             break;
 
         ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
-                                         pci_get_pdev(seg, bus, devfn));
+                                         NULL);
 
         /*
          * Devices behind PCIe-to-PCI/PCIx bridge may generate different
@@ -1509,7 +1509,7 @@  static int domain_context_mapping(struct
         if ( !ret && pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE &&
              (secbus != pdev->bus || pdev->devfn != 0) )
             ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0,
-                                             pci_get_pdev(seg, secbus, 0));
+                                             NULL);
 
         break;