355 lines
12 KiB
Diff
355 lines
12 KiB
Diff
References: bnc#787169
|
|
|
|
# HG changeset patch
|
|
# User Jan Beulich <jbeulich@suse.com>
|
|
# Date 1357559482 -3600
|
|
# Node ID 75cc4943b1ff509c4074800a23ff51d773233b8a
|
|
# Parent 62dd78a4e3fc9d190840549f13b4d613f2d19c41
|
|
IOMMU: adjust add/remove operation 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/amd/pci_amd_iommu.c
|
|
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c
|
|
@@ -83,14 +83,14 @@ static void disable_translation(u32 *dte
|
|
}
|
|
|
|
static void amd_iommu_setup_domain_device(
|
|
- struct domain *domain, struct amd_iommu *iommu, int bdf)
|
|
+ struct domain *domain, struct amd_iommu *iommu,
|
|
+ u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
void *dte;
|
|
unsigned long flags;
|
|
int req_id, valid = 1;
|
|
int dte_i = 0;
|
|
- u8 bus = PCI_BUS(bdf);
|
|
- u8 devfn = PCI_DEVFN2(bdf);
|
|
+ u8 bus = pdev->bus;
|
|
|
|
struct hvm_iommu *hd = domain_hvm_iommu(domain);
|
|
|
|
@@ -103,7 +103,7 @@ static void amd_iommu_setup_domain_devic
|
|
dte_i = 1;
|
|
|
|
/* get device-table entry */
|
|
- req_id = get_dma_requestor_id(iommu->seg, bdf);
|
|
+ req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn));
|
|
dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
|
|
|
|
spin_lock_irqsave(&iommu->lock, flags);
|
|
@@ -115,7 +115,7 @@ static void amd_iommu_setup_domain_devic
|
|
(u32 *)dte, page_to_maddr(hd->root_table), hd->domain_id,
|
|
hd->paging_mode, valid);
|
|
|
|
- if ( pci_ats_device(iommu->seg, bus, devfn) &&
|
|
+ if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
|
|
iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )
|
|
iommu_dte_set_iotlb((u32 *)dte, dte_i);
|
|
|
|
@@ -132,32 +132,31 @@ static void amd_iommu_setup_domain_devic
|
|
|
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
|
|
|
- if ( pci_ats_device(iommu->seg, bus, devfn) &&
|
|
- !pci_ats_enabled(iommu->seg, bus, devfn) )
|
|
+ if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
|
|
+ !pci_ats_enabled(iommu->seg, bus, pdev->devfn) )
|
|
{
|
|
- struct pci_dev *pdev;
|
|
+ if ( devfn == pdev->devfn )
|
|
+ enable_ats_device(iommu->seg, bus, devfn);
|
|
|
|
- enable_ats_device(iommu->seg, bus, devfn);
|
|
-
|
|
- ASSERT(spin_is_locked(&pcidevs_lock));
|
|
- pdev = pci_get_pdev(iommu->seg, bus, devfn);
|
|
-
|
|
- ASSERT( pdev != NULL );
|
|
amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
|
|
}
|
|
}
|
|
|
|
-static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev)
|
|
+static int __init amd_iommu_setup_dom0_device(u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
int bdf = PCI_BDF2(pdev->bus, pdev->devfn);
|
|
struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
|
|
|
|
- if ( likely(iommu != NULL) )
|
|
- amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
|
|
- else
|
|
+ if ( unlikely(!iommu) )
|
|
+ {
|
|
AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n",
|
|
pdev->seg, pdev->bus,
|
|
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
|
|
+ PCI_SLOT(devfn), PCI_FUNC(devfn));
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev);
|
|
+ return 0;
|
|
}
|
|
|
|
int __init amd_iov_detect(void)
|
|
@@ -291,16 +290,16 @@ static void __init amd_iommu_dom0_init(s
|
|
}
|
|
|
|
void amd_iommu_disable_domain_device(struct domain *domain,
|
|
- struct amd_iommu *iommu, int bdf)
|
|
+ struct amd_iommu *iommu,
|
|
+ u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
void *dte;
|
|
unsigned long flags;
|
|
int req_id;
|
|
- u8 bus = PCI_BUS(bdf);
|
|
- u8 devfn = PCI_DEVFN2(bdf);
|
|
+ u8 bus = pdev->bus;
|
|
|
|
BUG_ON ( iommu->dev_table.buffer == NULL );
|
|
- req_id = get_dma_requestor_id(iommu->seg, bdf);
|
|
+ req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn));
|
|
dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
|
|
|
|
spin_lock_irqsave(&iommu->lock, flags);
|
|
@@ -308,7 +307,7 @@ void amd_iommu_disable_domain_device(str
|
|
{
|
|
disable_translation((u32 *)dte);
|
|
|
|
- if ( pci_ats_device(iommu->seg, bus, devfn) &&
|
|
+ if ( pci_ats_device(iommu->seg, bus, pdev->devfn) &&
|
|
iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )
|
|
iommu_dte_set_iotlb((u32 *)dte, 0);
|
|
|
|
@@ -323,7 +322,8 @@ void amd_iommu_disable_domain_device(str
|
|
|
|
ASSERT(spin_is_locked(&pcidevs_lock));
|
|
|
|
- if ( pci_ats_device(iommu->seg, bus, devfn) &&
|
|
+ if ( devfn == pdev->devfn &&
|
|
+ pci_ats_device(iommu->seg, bus, devfn) &&
|
|
pci_ats_enabled(iommu->seg, bus, devfn) )
|
|
disable_ats_device(iommu->seg, bus, devfn);
|
|
}
|
|
@@ -346,7 +346,7 @@ static int reassign_device(struct domain
|
|
return -ENODEV;
|
|
}
|
|
|
|
- amd_iommu_disable_domain_device(source, iommu, bdf);
|
|
+ amd_iommu_disable_domain_device(source, iommu, devfn, pdev);
|
|
|
|
if ( devfn == pdev->devfn )
|
|
{
|
|
@@ -359,7 +359,7 @@ static int reassign_device(struct domain
|
|
if ( t->root_table == NULL )
|
|
allocate_domain_resources(t);
|
|
|
|
- amd_iommu_setup_domain_device(target, iommu, bdf);
|
|
+ amd_iommu_setup_domain_device(target, iommu, devfn, pdev);
|
|
AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n",
|
|
pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
|
source->domain_id, target->domain_id);
|
|
@@ -449,7 +449,7 @@ static void amd_iommu_domain_destroy(str
|
|
amd_iommu_flush_all_pages(d);
|
|
}
|
|
|
|
-static int amd_iommu_add_device(struct pci_dev *pdev)
|
|
+static int amd_iommu_add_device(u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
struct amd_iommu *iommu;
|
|
u16 bdf;
|
|
@@ -462,16 +462,16 @@ static int amd_iommu_add_device(struct p
|
|
{
|
|
AMD_IOMMU_DEBUG("Fail to find iommu."
|
|
" %04x:%02x:%02x.%u cannot be assigned to dom%d\n",
|
|
- pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
|
|
- PCI_FUNC(pdev->devfn), pdev->domain->domain_id);
|
|
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
|
+ pdev->domain->domain_id);
|
|
return -ENODEV;
|
|
}
|
|
|
|
- amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
|
|
+ amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev);
|
|
return 0;
|
|
}
|
|
|
|
-static int amd_iommu_remove_device(struct pci_dev *pdev)
|
|
+static int amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
struct amd_iommu *iommu;
|
|
u16 bdf;
|
|
@@ -484,12 +484,12 @@ static int amd_iommu_remove_device(struc
|
|
{
|
|
AMD_IOMMU_DEBUG("Fail to find iommu."
|
|
" %04x:%02x:%02x.%u cannot be removed from dom%d\n",
|
|
- pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn),
|
|
- PCI_FUNC(pdev->devfn), pdev->domain->domain_id);
|
|
+ pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
|
|
+ pdev->domain->domain_id);
|
|
return -ENODEV;
|
|
}
|
|
|
|
- amd_iommu_disable_domain_device(pdev->domain, iommu, bdf);
|
|
+ amd_iommu_disable_domain_device(pdev->domain, iommu, devfn, pdev);
|
|
return 0;
|
|
}
|
|
|
|
--- a/xen/drivers/passthrough/iommu.c
|
|
+++ b/xen/drivers/passthrough/iommu.c
|
|
@@ -167,7 +167,7 @@ int iommu_add_device(struct pci_dev *pde
|
|
if ( !iommu_enabled || !hd->platform_ops )
|
|
return 0;
|
|
|
|
- return hd->platform_ops->add_device(pdev);
|
|
+ return hd->platform_ops->add_device(pdev->devfn, pdev);
|
|
}
|
|
|
|
int iommu_enable_device(struct pci_dev *pdev)
|
|
@@ -197,7 +197,7 @@ int iommu_remove_device(struct pci_dev *
|
|
if ( !iommu_enabled || !hd->platform_ops )
|
|
return 0;
|
|
|
|
- return hd->platform_ops->remove_device(pdev);
|
|
+ return hd->platform_ops->remove_device(pdev->devfn, pdev);
|
|
}
|
|
|
|
/*
|
|
--- a/xen/drivers/passthrough/pci.c
|
|
+++ b/xen/drivers/passthrough/pci.c
|
|
@@ -715,7 +715,7 @@ int __init scan_pci_devices(void)
|
|
|
|
struct setup_dom0 {
|
|
struct domain *d;
|
|
- void (*handler)(struct pci_dev *);
|
|
+ int (*handler)(u8 devfn, struct pci_dev *);
|
|
};
|
|
|
|
static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg)
|
|
@@ -734,7 +734,7 @@ static int __init _setup_dom0_pci_device
|
|
|
|
pdev->domain = ctxt->d;
|
|
list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list);
|
|
- ctxt->handler(pdev);
|
|
+ ctxt->handler(devfn, pdev);
|
|
}
|
|
}
|
|
|
|
@@ -742,7 +742,7 @@ static int __init _setup_dom0_pci_device
|
|
}
|
|
|
|
void __init setup_dom0_pci_devices(
|
|
- struct domain *d, void (*handler)(struct pci_dev *))
|
|
+ struct domain *d, int (*handler)(u8 devfn, struct pci_dev *))
|
|
{
|
|
struct setup_dom0 ctxt = { .d = d, .handler = handler };
|
|
|
|
--- a/xen/drivers/passthrough/vtd/iommu.c
|
|
+++ b/xen/drivers/passthrough/vtd/iommu.c
|
|
@@ -52,7 +52,7 @@ int nr_iommus;
|
|
|
|
static struct tasklet vtd_fault_tasklet;
|
|
|
|
-static void setup_dom0_device(struct pci_dev *);
|
|
+static int setup_dom0_device(u8 devfn, struct pci_dev *);
|
|
static void setup_dom0_rmrr(struct domain *d);
|
|
|
|
static int domain_iommu_domid(struct domain *d,
|
|
@@ -1904,7 +1904,7 @@ static int rmrr_identity_mapping(struct
|
|
return 0;
|
|
}
|
|
|
|
-static int intel_iommu_add_device(struct pci_dev *pdev)
|
|
+static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
struct acpi_rmrr_unit *rmrr;
|
|
u16 bdf;
|
|
@@ -1915,8 +1915,7 @@ static int intel_iommu_add_device(struct
|
|
if ( !pdev->domain )
|
|
return -EINVAL;
|
|
|
|
- ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus,
|
|
- pdev->devfn);
|
|
+ ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
|
|
if ( ret )
|
|
{
|
|
dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n",
|
|
@@ -1928,7 +1927,7 @@ static int intel_iommu_add_device(struct
|
|
{
|
|
if ( rmrr->segment == pdev->seg &&
|
|
PCI_BUS(bdf) == pdev->bus &&
|
|
- PCI_DEVFN2(bdf) == pdev->devfn )
|
|
+ PCI_DEVFN2(bdf) == devfn )
|
|
{
|
|
ret = rmrr_identity_mapping(pdev->domain, rmrr);
|
|
if ( ret )
|
|
@@ -1953,7 +1952,7 @@ static int intel_iommu_enable_device(str
|
|
return ret >= 0 ? 0 : ret;
|
|
}
|
|
|
|
-static int intel_iommu_remove_device(struct pci_dev *pdev)
|
|
+static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
struct acpi_rmrr_unit *rmrr;
|
|
u16 bdf;
|
|
@@ -1971,19 +1970,22 @@ static int intel_iommu_remove_device(str
|
|
{
|
|
if ( rmrr->segment == pdev->seg &&
|
|
PCI_BUS(bdf) == pdev->bus &&
|
|
- PCI_DEVFN2(bdf) == pdev->devfn )
|
|
+ PCI_DEVFN2(bdf) == devfn )
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
- return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus,
|
|
- pdev->devfn);
|
|
+ return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus, devfn);
|
|
}
|
|
|
|
-static void __init setup_dom0_device(struct pci_dev *pdev)
|
|
+static int __init setup_dom0_device(u8 devfn, struct pci_dev *pdev)
|
|
{
|
|
- domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, pdev->devfn);
|
|
- pci_vtd_quirk(pdev);
|
|
+ int err;
|
|
+
|
|
+ err = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn);
|
|
+ if ( !err && devfn == pdev->devfn )
|
|
+ pci_vtd_quirk(pdev);
|
|
+ return err;
|
|
}
|
|
|
|
void clear_fault_bits(struct iommu *iommu)
|
|
--- a/xen/include/xen/iommu.h
|
|
+++ b/xen/include/xen/iommu.h
|
|
@@ -120,9 +120,9 @@ bool_t pt_irq_need_timer(uint32_t flags)
|
|
struct iommu_ops {
|
|
int (*init)(struct domain *d);
|
|
void (*dom0_init)(struct domain *d);
|
|
- int (*add_device)(struct pci_dev *pdev);
|
|
+ int (*add_device)(u8 devfn, struct pci_dev *);
|
|
int (*enable_device)(struct pci_dev *pdev);
|
|
- int (*remove_device)(struct pci_dev *pdev);
|
|
+ int (*remove_device)(u8 devfn, struct pci_dev *);
|
|
int (*assign_device)(struct domain *, u8 devfn, struct pci_dev *);
|
|
void (*teardown)(struct domain *d);
|
|
int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn,
|
|
--- a/xen/include/xen/pci.h
|
|
+++ b/xen/include/xen/pci.h
|
|
@@ -100,7 +100,8 @@ struct pci_dev *pci_lock_pdev(int seg, i
|
|
struct pci_dev *pci_lock_domain_pdev(
|
|
struct domain *, int seg, int bus, int devfn);
|
|
|
|
-void setup_dom0_pci_devices(struct domain *, void (*)(struct pci_dev *));
|
|
+void setup_dom0_pci_devices(struct domain *,
|
|
+ int (*)(u8 devfn, struct pci_dev *));
|
|
void pci_release_devices(struct domain *d);
|
|
int pci_add_segment(u16 seg);
|
|
const unsigned long *pci_get_ro_map(u16 seg);
|