[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] VT-d: fix VF of RC integrated endpoint matched to wrong VT-d unit



+ Eric

On Fri, Jun 16, 2017 at 02:48:39PM +0800, Chao Gao wrote:
>The problem is a VF of RC integrated PF (e.g. PF's BDF is 00:02.0),
>we would wrongly use 00:00.0 to search VT-d unit.
>
>To search VT-d unit for a VF, the BDF of the PF is used. And If the
>PF is an Extended Function, the BDF of one traditional function is
>used. The following line (from acpi_find_matched_drhd_unit()):
>    devfn = PCI_SLOT(pdev->info.physfn.devfn) ? 0 : pdev->info.physfn.devfn;
>sets 'devfn' to 0 if PF's devfn > 8. Apparently, this line treats all
>PFs as ARI-capable function and assumes the Root Port or Switch
>Downstream Port immediately above the PF has ARIforwarding enabled.
>However, according to SRIOV spec 3.7.3, ARI is not applicable to RC
>integrated PF. For this case, we should use PF's BDF directly other
>than using 0 as devfn.
>
>This patch adds a new pdev type to indicate a function is RC
>integrated. And check whether PF is a RC integrated endpoint when
>searching VT-d unit.
>
>Reported-by: Crawford, Eric R <Eric.R.Crawford@xxxxxxxxx>
>Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx>
>---
> xen/drivers/passthrough/pci.c          | 28 +++++++++++++++++++---------
> xen/drivers/passthrough/vtd/dmar.c     |  7 ++++++-
> xen/drivers/passthrough/vtd/intremap.c |  1 +
> xen/drivers/passthrough/vtd/iommu.c    |  2 ++
> xen/include/xen/pci.h                  |  1 +
> 5 files changed, 29 insertions(+), 10 deletions(-)
>
>diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
>index 6e7126b..9842d76 100644
>--- a/xen/drivers/passthrough/pci.c
>+++ b/xen/drivers/passthrough/pci.c
>@@ -345,6 +345,7 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 
>bus, u8 devfn)
>             break;
> 
>         case DEV_TYPE_PCIe_ENDPOINT:
>+        case DEV_TYPE_RC_ENDPOINT:
>             pos = pci_find_cap_offset(pseg->nr, bus, PCI_SLOT(devfn),
>                                       PCI_FUNC(devfn), PCI_CAP_ID_EXP);
>             BUG_ON(!pos);
>@@ -854,23 +855,24 @@ int pci_release_devices(struct domain *d)
> 
> enum pdev_type pdev_type(u16 seg, u8 bus, u8 devfn)
> {
>-    u16 class_device, creg;
>-    u8 d = PCI_SLOT(devfn), f = PCI_FUNC(devfn);
>+    uint8_t d = PCI_SLOT(devfn), f = PCI_FUNC(devfn);
>     int pos = pci_find_cap_offset(seg, bus, d, f, PCI_CAP_ID_EXP);
>+    int pcie_type = -1;
> 
>-    class_device = pci_conf_read16(seg, bus, d, f, PCI_CLASS_DEVICE);
>-    switch ( class_device )
>+    if ( pos )
>+        pcie_type = MASK_EXTR(pci_conf_read16(seg, bus, d, f,
>+                                  pos + PCI_EXP_FLAGS), PCI_EXP_FLAGS_TYPE);
>+    switch ( pci_conf_read16(seg, bus, d, f, PCI_CLASS_DEVICE) )
>     {
>     case PCI_CLASS_BRIDGE_PCI:
>-        if ( !pos )
>-            return DEV_TYPE_LEGACY_PCI_BRIDGE;
>-        creg = pci_conf_read16(seg, bus, d, f, pos + PCI_EXP_FLAGS);
>-        switch ( (creg & PCI_EXP_FLAGS_TYPE) >> 4 )
>+        switch ( pcie_type )
>         {
>         case PCI_EXP_TYPE_PCI_BRIDGE:
>             return DEV_TYPE_PCIe2PCI_BRIDGE;
>         case PCI_EXP_TYPE_PCIE_BRIDGE:
>             return DEV_TYPE_PCI2PCIe_BRIDGE;
>+        case -1:
>+            return DEV_TYPE_LEGACY_PCI_BRIDGE;
>         }
>         return DEV_TYPE_PCIe_BRIDGE;
>     case PCI_CLASS_BRIDGE_HOST:
>@@ -880,7 +882,15 @@ enum pdev_type pdev_type(u16 seg, u8 bus, u8 devfn)
>         return DEV_TYPE_PCI_UNKNOWN;
>     }
> 
>-    return pos ? DEV_TYPE_PCIe_ENDPOINT : DEV_TYPE_PCI;
>+    switch ( pcie_type )
>+    {
>+    case PCI_EXP_TYPE_RC_END:
>+        return DEV_TYPE_RC_ENDPOINT;
>+    case -1:
>+        return DEV_TYPE_PCI;
>+    }
>+
>+    return DEV_TYPE_PCIe_ENDPOINT;
> }
> 
> /*
>diff --git a/xen/drivers/passthrough/vtd/dmar.c 
>b/xen/drivers/passthrough/vtd/dmar.c
>index 82040dd..7c9d17b 100644
>--- a/xen/drivers/passthrough/vtd/dmar.c
>+++ b/xen/drivers/passthrough/vtd/dmar.c
>@@ -219,7 +219,12 @@ struct acpi_drhd_unit *acpi_find_matched_drhd_unit(const 
>struct pci_dev *pdev)
>     else if ( pdev->info.is_virtfn )
>     {
>         bus = pdev->info.physfn.bus;
>-        devfn = PCI_SLOT(pdev->info.physfn.devfn) ? 0 : 
>pdev->info.physfn.devfn;
>+        /* ARI is not appliable to Root Complex Integrated Endpoints */
>+        if ( PCI_SLOT(pdev->info.physfn.devfn) &&
>+             (pdev->type != DEV_TYPE_RC_ENDPOINT) )
>+            devfn = 0;
>+        else
>+            devfn = pdev->info.physfn.devfn;
>     }
>     else
>     {
>diff --git a/xen/drivers/passthrough/vtd/intremap.c 
>b/xen/drivers/passthrough/vtd/intremap.c
>index 1e0317c..bae0d3b 100644
>--- a/xen/drivers/passthrough/vtd/intremap.c
>+++ b/xen/drivers/passthrough/vtd/intremap.c
>@@ -486,6 +486,7 @@ static void set_msi_source_id(struct pci_dev *pdev, struct 
>iremap_entry *ire)
>         unsigned int sq;
> 
>     case DEV_TYPE_PCIe_ENDPOINT:
>+    case DEV_TYPE_RC_ENDPOINT:
>     case DEV_TYPE_PCIe_BRIDGE:
>     case DEV_TYPE_PCIe2PCI_BRIDGE:
>     case DEV_TYPE_PCI_HOST_BRIDGE:
>diff --git a/xen/drivers/passthrough/vtd/iommu.c 
>b/xen/drivers/passthrough/vtd/iommu.c
>index 19328f6..73f3095 100644
>--- a/xen/drivers/passthrough/vtd/iommu.c
>+++ b/xen/drivers/passthrough/vtd/iommu.c
>@@ -1493,6 +1493,7 @@ static int domain_context_mapping(struct domain *domain, 
>u8 devfn,
>         break;
> 
>     case DEV_TYPE_PCIe_ENDPOINT:
>+    case DEV_TYPE_RC_ENDPOINT:
>         if ( iommu_debug )
>             printk(VTDPREFIX "d%d:PCIe: map %04x:%02x:%02x.%u\n",
>                    domain->domain_id, seg, bus,
>@@ -1644,6 +1645,7 @@ static int domain_context_unmap(struct domain *domain, 
>u8 devfn,
>         goto out;
> 
>     case DEV_TYPE_PCIe_ENDPOINT:
>+    case DEV_TYPE_RC_ENDPOINT:
>         if ( iommu_debug )
>             printk(VTDPREFIX "d%d:PCIe: unmap %04x:%02x:%02x.%u\n",
>                    domain->domain_id, seg, bus,
>diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
>index 59b6e8a..4ec74b1 100644
>--- a/xen/include/xen/pci.h
>+++ b/xen/include/xen/pci.h
>@@ -67,6 +67,7 @@ struct pci_dev {
>     enum pdev_type {
>         DEV_TYPE_PCI_UNKNOWN,
>         DEV_TYPE_PCIe_ENDPOINT,
>+        DEV_TYPE_RC_ENDPOINT,       // Root Complex Integrated Endpoint
>         DEV_TYPE_PCIe_BRIDGE,       // PCIe root port, switch
>         DEV_TYPE_PCIe2PCI_BRIDGE,   // PCIe-to-PCI/PCIx bridge
>         DEV_TYPE_PCI2PCIe_BRIDGE,   // PCI/PCIx-to-PCIe bridge
>-- 
>1.8.3.1
>

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.