[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |