|
[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 |