# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxx>
# Date 1316712518 -3600
# Node ID 314b147d524d8a9fbf7fdebbb1648845b8c02379
# Parent 9e0259239822535680b88ab81cd9084238a29efb
PCI multi-seg: Pass-through adjustments
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
diff -r 9e0259239822 -r 314b147d524d xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c Thu Sep 22 18:28:03
2011 +0100
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c Thu Sep 22 18:28:38
2011 +0100
@@ -123,35 +123,17 @@
spin_unlock_irqrestore(&iommu->lock, flags);
}
-static void __init amd_iommu_setup_dom0_devices(struct domain *d)
+static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev)
{
- struct amd_iommu *iommu;
- struct pci_dev *pdev;
- int bus, devfn, bdf;
+ int bdf = (pdev->bus << 8) | pdev->devfn;
+ struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
- spin_lock(&pcidevs_lock);
- for ( bus = 0; bus < 256; bus++ )
- {
- for ( devfn = 0; devfn < 256; devfn++ )
- {
- pdev = pci_get_pdev(0, bus, devfn);
- if ( !pdev )
- continue;
-
- pdev->domain = d;
- list_add(&pdev->domain_list, &d->arch.pdev_list);
-
- bdf = (bus << 8) | devfn;
- iommu = find_iommu_for_device(pdev->seg, bdf);
-
- if ( likely(iommu != NULL) )
- amd_iommu_setup_domain_device(d, iommu, bdf);
- else
- AMD_IOMMU_DEBUG("No iommu for device %02x:%02x.%x\n",
- bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
- }
- }
- spin_unlock(&pcidevs_lock);
+ if ( likely(iommu != NULL) )
+ amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
+ else
+ AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n",
+ pdev->seg, pdev->bus,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
}
int __init amd_iov_detect(void)
@@ -279,7 +261,7 @@
}
}
- amd_iommu_setup_dom0_devices(d);
+ setup_dom0_pci_devices(d, amd_iommu_setup_dom0_device);
}
static void amd_iommu_disable_domain_device(
diff -r 9e0259239822 -r 314b147d524d xen/drivers/passthrough/pci.c
--- a/xen/drivers/passthrough/pci.c Thu Sep 22 18:28:03 2011 +0100
+++ b/xen/drivers/passthrough/pci.c Thu Sep 22 18:28:38 2011 +0100
@@ -202,9 +202,7 @@
void pci_enable_acs(struct pci_dev *pdev)
{
int pos;
- u16 cap;
- u16 ctrl;
-
+ u16 cap, ctrl, seg = pdev->seg;
u8 bus = pdev->bus;
u8 dev = PCI_SLOT(pdev->devfn);
u8 func = PCI_FUNC(pdev->devfn);
@@ -212,7 +210,7 @@
if ( !iommu_enabled )
return;
- pos = pci_find_ext_capability(0, bus, pdev->devfn, PCI_EXT_CAP_ID_ACS);
+ pos = pci_find_ext_capability(seg, bus, pdev->devfn, PCI_EXT_CAP_ID_ACS);
if (!pos)
return;
@@ -453,7 +451,7 @@
#define PCI_CLASS_BRIDGE_PCI 0x0604
-int pdev_type(u8 bus, u8 devfn)
+int pdev_type(u16 seg, u8 bus, u8 devfn)
{
u16 class_device;
u16 status, creg;
@@ -488,9 +486,9 @@
* return 1: find PCIe-to-PCI/PCIX bridge or PCI legacy bridge
* return -1: fail
*/
-int find_upstream_bridge(u8 *bus, u8 *devfn, u8 *secbus)
+int find_upstream_bridge(u16 seg, u8 *bus, u8 *devfn, u8 *secbus)
{
- struct pci_seg *pseg = get_pseg(0);
+ struct pci_seg *pseg = get_pseg(seg);
int ret = 0;
int cnt = 0;
@@ -525,7 +523,7 @@
/*
* detect pci device, return 0 if it exists, or return 0
*/
-int __init pci_device_detect(u8 bus, u8 dev, u8 func)
+int __init pci_device_detect(u16 seg, u8 bus, u8 dev, u8 func)
{
u32 vendor;
@@ -554,7 +552,7 @@
{
for ( func = 0; func < 8; func++ )
{
- if ( pci_device_detect(bus, dev, func) == 0 )
+ if ( pci_device_detect(pseg->nr, bus, dev, func) == 0 )
continue;
pdev = alloc_pdev(pseg, bus, PCI_DEVFN(dev, func));
@@ -565,7 +563,7 @@
}
/* build bus2bridge */
- type = pdev_type(bus, PCI_DEVFN(dev, func));
+ type = pdev_type(pseg->nr, bus, PCI_DEVFN(dev, func));
switch ( type )
{
case DEV_TYPE_PCIe_BRIDGE:
@@ -594,8 +592,8 @@
break;
default:
- printk("%s: unknown type: bdf = %x:%x.%x\n",
- __func__, bus, dev, func);
+ printk("%s: unknown type: %04x:%02x:%02x.%u\n",
+ __func__, pseg->nr, bus, dev, func);
return -EINVAL;
}
@@ -620,6 +618,44 @@
return ret;
}
+struct setup_dom0 {
+ struct domain *d;
+ void (*handler)(struct pci_dev *);
+};
+
+static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg)
+{
+ struct setup_dom0 *ctxt = arg;
+ int bus, devfn;
+
+ for ( bus = 0; bus < 256; bus++ )
+ {
+ for ( devfn = 0; devfn < 256; devfn++ )
+ {
+ struct pci_dev *pdev = pci_get_pdev(pseg->nr, bus, devfn);
+
+ if ( !pdev )
+ continue;
+
+ pdev->domain = ctxt->d;
+ list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list);
+ ctxt->handler(pdev);
+ }
+ }
+
+ return 0;
+}
+
+void __init setup_dom0_pci_devices(
+ struct domain *d, void (*handler)(struct pci_dev *))
+{
+ struct setup_dom0 ctxt = { .d = d, .handler = handler };
+
+ spin_lock(&pcidevs_lock);
+ pci_segments_iterate(_setup_dom0_pci_devices, &ctxt);
+ spin_unlock(&pcidevs_lock);
+}
+
/* Disconnect all PCI devices from the PCI buses. From the PCI spec:
* "When a 0 is written to [the COMMAND] register, the device is
* logically disconnected from the PCI bus for all accesses except
@@ -654,8 +690,9 @@
list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list )
{
- printk("%02x:%02x.%x - dom %-3d - MSIs < ",
- pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+ printk("%04x:%02x:%02x.%u - dom %-3d - MSIs < ",
+ pseg->nr, pdev->bus,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
pdev->domain ? pdev->domain->domain_id : -1);
list_for_each_entry ( msi, &pdev->msi_list, list )
printk("%d ", msi->irq);
diff -r 9e0259239822 -r 314b147d524d xen/drivers/passthrough/vtd/dmar.c
--- a/xen/drivers/passthrough/vtd/dmar.c Thu Sep 22 18:28:03 2011 +0100
+++ b/xen/drivers/passthrough/vtd/dmar.c Thu Sep 22 18:28:38 2011 +0100
@@ -457,11 +457,11 @@
d = PCI_SLOT(dmaru->scope.devices[i]);
f = PCI_FUNC(dmaru->scope.devices[i]);
- if ( pci_device_detect(b, d, f) == 0 )
+ if ( pci_device_detect(drhd->segment, b, d, f) == 0 )
{
dprintk(XENLOG_WARNING VTDPREFIX,
- " Non-existent device (%x:%x.%x) is reported "
- "in this DRHD's scope!\n", b, d, f);
+ " Non-existent device (%04x:%02x:%02x.%u) is reported"
+ " in this DRHD's scope!\n", drhd->segment, b, d, f);
invalid_cnt++;
}
}
@@ -556,12 +556,13 @@
d = PCI_SLOT(rmrru->scope.devices[i]);
f = PCI_FUNC(rmrru->scope.devices[i]);
- if ( pci_device_detect(b, d, f) == 0 )
+ if ( pci_device_detect(rmrr->segment, b, d, f) == 0 )
{
dprintk(XENLOG_WARNING VTDPREFIX,
- " Non-existent device (%x:%x.%x) is reported "
- "in RMRR (%"PRIx64", %"PRIx64")'s scope!\n",
- b, d, f, rmrru->base_address, rmrru->end_address);
+ " Non-existent device (%04x:%02x:%02x.%u) is reported"
+ " in RMRR (%"PRIx64", %"PRIx64")'s scope!\n",
+ rmrr->segment, b, d, f,
+ rmrru->base_address, rmrru->end_address);
ignore = 1;
}
else
diff -r 9e0259239822 -r 314b147d524d xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c Thu Sep 22 18:28:03 2011 +0100
+++ b/xen/drivers/passthrough/vtd/intremap.c Thu Sep 22 18:28:38 2011 +0100
@@ -448,15 +448,17 @@
static void set_msi_source_id(struct pci_dev *pdev, struct iremap_entry *ire)
{
int type;
+ u16 seg;
u8 bus, devfn, secbus;
int ret;
if ( !pdev || !ire )
return;
+ seg = pdev->seg;
bus = pdev->bus;
devfn = pdev->devfn;
- type = pdev_type(bus, devfn);
+ type = pdev_type(seg, bus, devfn);
switch ( type )
{
case DEV_TYPE_PCIe_BRIDGE:
@@ -469,7 +471,7 @@
break;
case DEV_TYPE_PCI:
- ret = find_upstream_bridge(&bus, &devfn, &secbus);
+ ret = find_upstream_bridge(seg, &bus, &devfn, &secbus);
if ( ret == 0 ) /* integrated PCI device */
{
set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16,
@@ -477,19 +479,20 @@
}
else if ( ret == 1 ) /* find upstream bridge */
{
- if ( pdev_type(bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE )
+ if ( pdev_type(seg, bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE )
set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16,
(bus << 8) | pdev->bus);
- else if ( pdev_type(bus, devfn) == DEV_TYPE_LEGACY_PCI_BRIDGE )
+ else if ( pdev_type(seg, bus, devfn) == DEV_TYPE_LEGACY_PCI_BRIDGE
)
set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16,
PCI_BDF2(bus, devfn));
}
break;
default:
- dprintk(XENLOG_WARNING VTDPREFIX, "d%d: unknown(%u): bdf = %x:%x.%x\n",
+ dprintk(XENLOG_WARNING VTDPREFIX,
+ "d%d: unknown(%u): %04x:%02x:%02x.%u\n",
pdev->domain->domain_id, type,
- bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
break;
}
}
diff -r 9e0259239822 -r 314b147d524d xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c Thu Sep 22 18:28:03 2011 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c Thu Sep 22 18:28:38 2011 +0100
@@ -50,7 +50,7 @@
int nr_iommus;
-static void setup_dom0_devices(struct domain *d);
+static void setup_dom0_device(struct pci_dev *);
static void setup_dom0_rmrr(struct domain *d);
static int domain_iommu_domid(struct domain *d,
@@ -1234,7 +1234,7 @@
iommu_set_dom0_mapping(d);
}
- setup_dom0_devices(d);
+ setup_dom0_pci_devices(d, setup_dom0_device);
setup_dom0_rmrr(d);
iommu_flush_all();
@@ -1402,7 +1402,7 @@
ASSERT(spin_is_locked(&pcidevs_lock));
- type = pdev_type(bus, devfn);
+ type = pdev_type(seg, bus, devfn);
switch ( type )
{
case DEV_TYPE_PCIe_BRIDGE:
@@ -1431,7 +1431,7 @@
if ( ret )
break;
- if ( find_upstream_bridge(&bus, &devfn, &secbus) < 1 )
+ if ( find_upstream_bridge(seg, &bus, &devfn, &secbus) < 1 )
break;
ret = domain_context_mapping_one(domain, drhd->iommu, bus, devfn);
@@ -1441,7 +1441,7 @@
* requester-id. It may originate from devfn=0 on the secondary bus
* behind the bridge. Map that id as well if we didn't already.
*/
- if ( !ret && pdev_type(bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE &&
+ 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);
@@ -1533,7 +1533,7 @@
return -ENODEV;
iommu = drhd->iommu;
- type = pdev_type(bus, devfn);
+ type = pdev_type(seg, bus, devfn);
switch ( type )
{
case DEV_TYPE_PCIe_BRIDGE:
@@ -1562,11 +1562,11 @@
tmp_bus = bus;
tmp_devfn = devfn;
- if ( find_upstream_bridge(&tmp_bus, &tmp_devfn, &secbus) < 1 )
+ if ( find_upstream_bridge(seg, &tmp_bus, &tmp_devfn, &secbus) < 1 )
break;
/* PCIe to PCI/PCIx bridge */
- if ( pdev_type(tmp_bus, tmp_devfn) == DEV_TYPE_PCIe2PCI_BRIDGE )
+ if ( pdev_type(seg, tmp_bus, tmp_devfn) == DEV_TYPE_PCIe2PCI_BRIDGE )
{
ret = domain_context_unmap_one(domain, iommu, tmp_bus, tmp_devfn);
if ( ret )
@@ -1939,28 +1939,11 @@
pdev->devfn);
}
-static void __init setup_dom0_devices(struct domain *d)
+static void __init setup_dom0_device(struct pci_dev *pdev)
{
- struct pci_dev *pdev;
- int bus, devfn;
-
- spin_lock(&pcidevs_lock);
- for ( bus = 0; bus < 256; bus++ )
- {
- for ( devfn = 0; devfn < 256; devfn++ )
- {
- pdev = pci_get_pdev(0, bus, devfn);
- if ( !pdev )
- continue;
-
- pdev->domain = d;
- list_add(&pdev->domain_list, &d->arch.pdev_list);
- domain_context_mapping(d, pdev->seg, pdev->bus, pdev->devfn);
- pci_enable_acs(pdev);
- pci_vtd_quirk(pdev);
- }
- }
- spin_unlock(&pcidevs_lock);
+ domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, pdev->devfn);
+ pci_enable_acs(pdev);
+ pci_vtd_quirk(pdev);
}
void clear_fault_bits(struct iommu *iommu)
@@ -2227,7 +2210,7 @@
static int intel_iommu_group_id(u16 seg, u8 bus, u8 devfn)
{
u8 secbus;
- if ( find_upstream_bridge(&bus, &devfn, &secbus) < 0 )
+ if ( find_upstream_bridge(seg, &bus, &devfn, &secbus) < 0 )
return -1;
else
return PCI_BDF2(bus, devfn);
diff -r 9e0259239822 -r 314b147d524d xen/include/xen/pci.h
--- a/xen/include/xen/pci.h Thu Sep 22 18:28:03 2011 +0100
+++ b/xen/include/xen/pci.h Thu Sep 22 18:28:38 2011 +0100
@@ -82,13 +82,15 @@
DEV_TYPE_PCI,
};
-int pci_device_detect(u8 bus, u8 dev, u8 func);
+int pci_device_detect(u16 seg, u8 bus, u8 dev, u8 func);
int scan_pci_devices(void);
-int pdev_type(u8 bus, u8 devfn);
-int find_upstream_bridge(u8 *bus, u8 *devfn, u8 *secbus);
-struct pci_dev *pci_lock_pdev(int bus, int devfn);
-struct pci_dev *pci_lock_domain_pdev(struct domain *d, int bus, int devfn);
+int pdev_type(u16 seg, u8 bus, u8 devfn);
+int find_upstream_bridge(u16 seg, u8 *bus, u8 *devfn, u8 *secbus);
+struct pci_dev *pci_lock_pdev(int seg, int bus, int devfn);
+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 pci_release_devices(struct domain *d);
int pci_add_segment(u16 seg);
int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|