188 lines
7.0 KiB
Diff
188 lines
7.0 KiB
Diff
References: bnc#787169
|
|
|
|
# HG changeset patch
|
|
# User Jan Beulich <jbeulich@suse.com>
|
|
# Date 1357559549 -3600
|
|
# Node ID afb598bd0f5436bea15b7ef842e8ad5c6adefa1a
|
|
# Parent 75cc4943b1ff509c4074800a23ff51d773233b8a
|
|
VT-d: adjust context map/unmap parameters
|
|
|
|
... to use a (struct pci_dev *, devfn) pair.
|
|
|
|
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
|
|
|
|
--- a/xen/drivers/passthrough/vtd/extern.h
|
|
+++ b/xen/drivers/passthrough/vtd/extern.h
|
|
@@ -95,7 +95,7 @@ void free_pgtable_maddr(u64 maddr);
|
|
void *map_vtd_domain_page(u64 maddr);
|
|
void unmap_vtd_domain_page(void *va);
|
|
int domain_context_mapping_one(struct domain *domain, struct iommu *iommu,
|
|
- u8 bus, u8 devfn);
|
|
+ u8 bus, u8 devfn, const struct pci_dev *);
|
|
int domain_context_unmap_one(struct domain *domain, struct iommu *iommu,
|
|
u8 bus, u8 devfn);
|
|
|
|
--- a/xen/drivers/passthrough/vtd/iommu.c
|
|
+++ b/xen/drivers/passthrough/vtd/iommu.c
|
|
@@ -1308,7 +1308,7 @@ static void __init intel_iommu_dom0_init
|
|
int domain_context_mapping_one(
|
|
struct domain *domain,
|
|
struct iommu *iommu,
|
|
- u8 bus, u8 devfn)
|
|
+ u8 bus, u8 devfn, const struct pci_dev *pdev)
|
|
{
|
|
struct hvm_iommu *hd = domain_hvm_iommu(domain);
|
|
struct context_entry *context, *context_entries;
|
|
@@ -1325,11 +1325,9 @@ int domain_context_mapping_one(
|
|
if ( context_present(*context) )
|
|
{
|
|
int res = 0;
|
|
- struct pci_dev *pdev = NULL;
|
|
|
|
- /* First try to get domain ownership from device structure. If that's
|
|
+ /* Try to get domain ownership from device structure. If that's
|
|
* not available, try to read it from the context itself. */
|
|
- pdev = pci_get_pdev(seg, bus, devfn);
|
|
if ( pdev )
|
|
{
|
|
if ( pdev->domain != domain )
|
|
@@ -1448,13 +1446,12 @@ int domain_context_mapping_one(
|
|
}
|
|
|
|
static int domain_context_mapping(
|
|
- struct domain *domain, u16 seg, u8 bus, u8 devfn)
|
|
+ struct domain *domain, u8 devfn, const struct pci_dev *pdev)
|
|
{
|
|
struct acpi_drhd_unit *drhd;
|
|
int ret = 0;
|
|
u32 type;
|
|
- u8 secbus;
|
|
- struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
|
|
+ u8 seg = pdev->seg, bus = pdev->bus, secbus;
|
|
|
|
drhd = acpi_find_matched_drhd_unit(pdev);
|
|
if ( !drhd )
|
|
@@ -1475,8 +1472,9 @@ static int domain_context_mapping(
|
|
dprintk(VTDPREFIX, "d%d:PCIe: map %04x:%02x:%02x.%u\n",
|
|
domain->domain_id, seg, bus,
|
|
PCI_SLOT(devfn), PCI_FUNC(devfn));
|
|
- ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
|
|
- if ( !ret && ats_device(pdev, drhd) > 0 )
|
|
+ ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
|
|
+ pdev);
|
|
+ if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 )
|
|
enable_ats_device(seg, bus, devfn);
|
|
|
|
break;
|
|
@@ -1487,14 +1485,16 @@ static int domain_context_mapping(
|
|
domain->domain_id, seg, bus,
|
|
PCI_SLOT(devfn), PCI_FUNC(devfn));
|
|
|
|
- ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
|
|
+ ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
|
|
+ pdev);
|
|
if ( ret )
|
|
break;
|
|
|
|
if ( find_upstream_bridge(seg, &bus, &devfn, &secbus) < 1 )
|
|
break;
|
|
|
|
- ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
|
|
+ ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn,
|
|
+ pci_get_pdev(seg, bus, devfn));
|
|
|
|
/*
|
|
* Devices behind PCIe-to-PCI/PCIx bridge may generate different
|
|
@@ -1503,7 +1503,8 @@ static int domain_context_mapping(
|
|
*/
|
|
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);
|
|
+ ret = domain_context_mapping_one(domain, drhd->iommu, secbus, 0,
|
|
+ pci_get_pdev(seg, secbus, 0));
|
|
|
|
break;
|
|
|
|
@@ -1576,18 +1577,15 @@ int domain_context_unmap_one(
|
|
}
|
|
|
|
static int domain_context_unmap(
|
|
- struct domain *domain, u16 seg, u8 bus, u8 devfn)
|
|
+ struct domain *domain, u8 devfn, const struct pci_dev *pdev)
|
|
{
|
|
struct acpi_drhd_unit *drhd;
|
|
struct iommu *iommu;
|
|
int ret = 0;
|
|
u32 type;
|
|
- u8 tmp_bus, tmp_devfn, secbus;
|
|
- struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
|
|
+ u8 seg = pdev->seg, bus = pdev->bus, tmp_bus, tmp_devfn, secbus;
|
|
int found = 0;
|
|
|
|
- BUG_ON(!pdev);
|
|
-
|
|
drhd = acpi_find_matched_drhd_unit(pdev);
|
|
if ( !drhd )
|
|
return -ENODEV;
|
|
@@ -1607,7 +1605,7 @@ static int domain_context_unmap(
|
|
domain->domain_id, seg, bus,
|
|
PCI_SLOT(devfn), PCI_FUNC(devfn));
|
|
ret = domain_context_unmap_one(domain, iommu, bus, devfn);
|
|
- if ( !ret && ats_device(pdev, drhd) > 0 )
|
|
+ if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 )
|
|
disable_ats_device(seg, bus, devfn);
|
|
|
|
break;
|
|
@@ -1701,11 +1699,11 @@ static int reassign_device_ownership(
|
|
if ( (target != dom0) && !iommu_intremap )
|
|
untrusted_msi = 1;
|
|
|
|
- ret = domain_context_unmap(source, pdev->seg, pdev->bus, devfn);
|
|
+ ret = domain_context_unmap(source, devfn, pdev);
|
|
if ( ret )
|
|
return ret;
|
|
|
|
- ret = domain_context_mapping(target, pdev->seg, pdev->bus, devfn);
|
|
+ ret = domain_context_mapping(target, devfn, pdev);
|
|
if ( ret )
|
|
return ret;
|
|
|
|
@@ -1915,7 +1913,7 @@ static int intel_iommu_add_device(u8 dev
|
|
if ( !pdev->domain )
|
|
return -EINVAL;
|
|
|
|
- ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
|
|
+ ret = domain_context_mapping(pdev->domain, devfn, pdev);
|
|
if ( ret )
|
|
{
|
|
dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n",
|
|
@@ -1975,14 +1973,14 @@ static int intel_iommu_remove_device(u8
|
|
}
|
|
}
|
|
|
|
- return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus, devfn);
|
|
+ return domain_context_unmap(pdev->domain, devfn, pdev);
|
|
}
|
|
|
|
static int __init setup_dom0_device(u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
int err;
|
|
|
|
- err = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
|
|
+ err = domain_context_mapping(pdev->domain, devfn, pdev);
|
|
if ( !err && devfn == pdev->devfn )
|
|
pci_vtd_quirk(pdev);
|
|
return err;
|
|
--- a/xen/drivers/passthrough/vtd/quirks.c
|
|
+++ b/xen/drivers/passthrough/vtd/quirks.c
|
|
@@ -292,7 +292,7 @@ static void map_me_phantom_function(stru
|
|
/* map or unmap ME phantom function */
|
|
if ( map )
|
|
domain_context_mapping_one(domain, drhd->iommu, 0,
|
|
- PCI_DEVFN(dev, 7));
|
|
+ PCI_DEVFN(dev, 7), NULL);
|
|
else
|
|
domain_context_unmap_one(domain, drhd->iommu, 0,
|
|
PCI_DEVFN(dev, 7));
|