[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] PCI multi-seg: VT-d specific adjustments



# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxx>
# Date 1316712446 -3600
# Node ID 85418e16852723f6cc65082834061657f7149ea8
# Parent  ec7c81fbe0de9b18f38bf2592a9e44d0992821c9
PCI multi-seg: VT-d specific adjustments

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---


diff -r ec7c81fbe0de -r 85418e168527 xen/drivers/passthrough/vtd/dmar.c
--- a/xen/drivers/passthrough/vtd/dmar.c        Thu Sep 22 18:26:54 2011 +0100
+++ b/xen/drivers/passthrough/vtd/dmar.c        Thu Sep 22 18:27:26 2011 +0100
@@ -188,6 +188,9 @@
 
     list_for_each_entry ( drhd, &acpi_drhd_units, list )
     {
+        if ( drhd->segment != pdev->seg )
+            continue;
+
         for (i = 0; i < drhd->scope.devices_cnt; i++)
             if ( drhd->scope.devices[i] == PCI_BDF2(bus, devfn) )
                 return drhd;
@@ -201,13 +204,16 @@
     return include_all;
 }
 
-struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u8 bus, u8 devfn)
+struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u16 seg, u8 bus, u8 devfn)
 {
     struct acpi_atsr_unit *atsr;
     struct acpi_atsr_unit *all_ports = NULL;
 
     list_for_each_entry ( atsr, &acpi_atsr_units, list )
     {
+        if ( atsr->segment != seg )
+            continue;
+
         if ( test_bit(bus, atsr->scope.buses) )
             return atsr;
 
@@ -269,8 +275,8 @@
 }
 
 
-static int __init acpi_parse_dev_scope(void *start, void *end,
-                                       void *acpi_entry, int type)
+static int __init acpi_parse_dev_scope(
+    void *start, void *end, void *acpi_entry, int type, u16 seg)
 {
     struct dmar_scope *scope = acpi_entry;
     struct acpi_ioapic_unit *acpi_ioapic_unit;
@@ -314,8 +320,8 @@
                 bus, path->dev, path->fn, PCI_SUBORDINATE_BUS);
             if ( iommu_verbose )
                 dprintk(VTDPREFIX,
-                        "  bridge: %x:%x.%x  start = %x sec = %x  sub = %x\n",
-                        bus, path->dev, path->fn,
+                        " bridge: %04x:%02x:%02x.%u start=%x sec=%x sub=%x\n",
+                        seg, bus, path->dev, path->fn,
                         acpi_scope->start_bus, sec_bus, sub_bus);
 
             dmar_scope_add_buses(scope, sec_bus, sub_bus);
@@ -323,20 +329,21 @@
 
         case ACPI_DEV_MSI_HPET:
             if ( iommu_verbose )
-                dprintk(VTDPREFIX, "  MSI HPET: %x:%x.%x\n",
-                        bus, path->dev, path->fn);
+                dprintk(VTDPREFIX, " MSI HPET: %04x:%02x:%02x.%u\n",
+                        seg, bus, path->dev, path->fn);
             break;
 
         case ACPI_DEV_ENDPOINT:
             if ( iommu_verbose )
-                dprintk(VTDPREFIX, "  endpoint: %x:%x.%x\n",
-                        bus, path->dev, path->fn);
+                dprintk(VTDPREFIX, " endpoint: %04x:%02x:%02x.%u\n",
+                        seg, bus, path->dev, path->fn);
 
             if ( type == DMAR_TYPE )
             {
                 struct acpi_drhd_unit *drhd = acpi_entry;
 
-                if ( (bus == 0) && (path->dev == 2) && (path->fn == 0) )
+                if ( (seg == 0) && (bus == 0) && (path->dev == 2) &&
+                     (path->fn == 0) )
                     igd_drhd_address = drhd->address;
             }
 
@@ -344,8 +351,8 @@
 
         case ACPI_DEV_IOAPIC:
             if ( iommu_verbose )
-                dprintk(VTDPREFIX, "  IOAPIC: %x:%x.%x\n",
-                        bus, path->dev, path->fn);
+                dprintk(VTDPREFIX, " IOAPIC: %04x:%02x:%02x.%u\n",
+                        seg, bus, path->dev, path->fn);
 
             if ( type == DMAR_TYPE )
             {
@@ -398,6 +405,7 @@
     memset(dmaru, 0, sizeof(struct acpi_drhd_unit));
 
     dmaru->address = drhd->address;
+    dmaru->segment = drhd->segment;
     dmaru->include_all = drhd->flags & 1; /* BIT0: INCLUDE_ALL */
     INIT_LIST_HEAD(&dmaru->ioapic_list);
     if ( iommu_verbose )
@@ -411,7 +419,7 @@
     dev_scope_start = (void *)(drhd + 1);
     dev_scope_end = ((void *)drhd) + header->length;
     ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                               dmaru, DMAR_TYPE);
+                               dmaru, DMAR_TYPE, drhd->segment);
 
     if ( dmaru->include_all )
     {
@@ -528,11 +536,12 @@
 
     rmrru->base_address = base_addr;
     rmrru->end_address = end_addr;
+    rmrru->segment = rmrr->segment;
 
     dev_scope_start = (void *)(rmrr + 1);
     dev_scope_end   = ((void *)rmrr) + header->length;
     ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                               rmrru, RMRR_TYPE);
+                               rmrru, RMRR_TYPE, rmrr->segment);
 
     if ( ret || (rmrru->scope.devices_cnt == 0) )
         xfree(rmrru);
@@ -609,6 +618,7 @@
         return -ENOMEM;
     memset(atsru, 0, sizeof(struct acpi_atsr_unit));
 
+    atsru->segment = atsr->segment;
     atsru->all_ports = atsr->flags & 1; /* BIT0: ALL_PORTS */
     if ( iommu_verbose )
         dprintk(VTDPREFIX,
@@ -618,7 +628,7 @@
         dev_scope_start = (void *)(atsr + 1);
         dev_scope_end   = ((void *)atsr) + header->length;
         ret = acpi_parse_dev_scope(dev_scope_start, dev_scope_end,
-                                   atsru, ATSR_TYPE);
+                                   atsru, ATSR_TYPE, atsr->segment);
     }
     else
     {
diff -r ec7c81fbe0de -r 85418e168527 xen/drivers/passthrough/vtd/dmar.h
--- a/xen/drivers/passthrough/vtd/dmar.h        Thu Sep 22 18:26:54 2011 +0100
+++ b/xen/drivers/passthrough/vtd/dmar.h        Thu Sep 22 18:27:26 2011 +0100
@@ -49,6 +49,7 @@
     struct dmar_scope scope;            /* must be first member of struct */
     struct list_head list;
     u64    address;                     /* register base address of the unit */
+    u16    segment;
     u8     include_all:1;
     struct iommu *iommu;
     struct list_head ioapic_list;
@@ -59,12 +60,14 @@
     struct list_head list;
     u64    base_address;
     u64    end_address;
+    u16    segment;
     u8     allow_all:1;
 };
 
 struct acpi_atsr_unit {
     struct dmar_scope scope;            /* must be first member of struct */
     struct list_head list;
+    u16    segment;
     u8     all_ports:1;
 };
 
@@ -84,7 +87,7 @@
                  idx < rmrr->scope.devices_cnt; idx++)
 
 struct acpi_drhd_unit * acpi_find_matched_drhd_unit(struct pci_dev *pdev);
-struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u8 bus, u8 devfn);
+struct acpi_atsr_unit * acpi_find_matched_atsr_unit(u16 seg, u8 bus, u8 devfn);
 
 #define DMAR_TYPE 1
 #define RMRR_TYPE 2
@@ -114,7 +117,7 @@
 
 int vtd_hw_check(void);
 void disable_pmr(struct iommu *iommu);
-int is_usb_device(u8 bus, u8 devfn);
+int is_usb_device(u16 seg, u8 bus, u8 devfn);
 int is_igd_drhd(struct acpi_drhd_unit *drhd);
 
 #endif /* _DMAR_H_ */
diff -r ec7c81fbe0de -r 85418e168527 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Thu Sep 22 18:26:54 2011 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c       Thu Sep 22 18:27:26 2011 +0100
@@ -834,16 +834,17 @@
 {
     const char *reason;
     int fault_type;
+    u16 seg = iommu->intel->drhd->segment;
     reason = iommu_get_fault_reason(fault_reason, &fault_type);
 
     if ( fault_type == DMA_REMAP )
     {
         INTEL_IOMMU_DEBUG(
-                "DMAR:[%s] Request device [%02x:%02x.%d] "
+                "DMAR:[%s] Request device [%04x:%02x:%02x.%u] "
                 "fault addr %"PRIx64", iommu reg = %p\n"
                 "DMAR:[fault reason %02xh] %s\n",
                 (type ? "DMA Read" : "DMA Write"),
-                (source_id >> 8), PCI_SLOT(source_id & 0xFF),
+                seg, (source_id >> 8), PCI_SLOT(source_id & 0xFF),
                 PCI_FUNC(source_id & 0xFF), addr, iommu->reg,
                 fault_reason, reason);
 #ifndef __i386__ /* map_domain_page() cannot be used in this context */
@@ -854,10 +855,10 @@
     }
     else
         INTEL_IOMMU_DEBUG(
-                "INTR-REMAP: Request device [%02x:%02x.%d] "
+                "INTR-REMAP: Request device [%04x:%02x:%02x.%u] "
                 "fault index %"PRIx64", iommu reg = %p\n"
                 "INTR-REMAP:[fault reason %02xh] %s\n",
-                (source_id >> 8), PCI_SLOT(source_id & 0xFF),
+                seg, (source_id >> 8), PCI_SLOT(source_id & 0xFF),
                 PCI_FUNC(source_id & 0xFF), addr >> 48, iommu->reg,
                 fault_reason, reason);
     return 0;
@@ -1252,6 +1253,7 @@
     struct hvm_iommu *hd = domain_hvm_iommu(domain);
     struct context_entry *context, *context_entries;
     u64 maddr, pgd_maddr;
+    u16 seg = iommu->intel->drhd->segment;
     int agaw;
 
     ASSERT(spin_is_locked(&pcidevs_lock));
@@ -1267,7 +1269,7 @@
 
         /* First 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(0, bus, devfn);
+        pdev = pci_get_pdev(seg, bus, devfn);
         if ( pdev )
         {
             if ( pdev->domain != domain )
@@ -1379,18 +1381,20 @@
 
     unmap_vtd_domain_page(context_entries);
 
-    me_wifi_quirk(domain, bus, devfn, MAP_ME_PHANTOM_FUNC);
+    if ( !seg )
+        me_wifi_quirk(domain, bus, devfn, MAP_ME_PHANTOM_FUNC);
 
     return 0;
 }
 
-static int domain_context_mapping(struct domain *domain, u8 bus, u8 devfn)
+static int domain_context_mapping(
+    struct domain *domain, u16 seg, u8 bus, u8 devfn)
 {
     struct acpi_drhd_unit *drhd;
     int ret = 0;
     u32 type;
     u8 secbus;
-    struct pci_dev *pdev = pci_get_pdev(0, bus, devfn);
+    struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
 
     drhd = acpi_find_matched_drhd_unit(pdev);
     if ( !drhd )
@@ -1408,18 +1412,20 @@
 
     case DEV_TYPE_PCIe_ENDPOINT:
         if ( iommu_verbose )
-            dprintk(VTDPREFIX, "d%d:PCIe: map bdf = %x:%x.%x\n",
-                    domain->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+            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(0, bus, devfn) )
-            enable_ats_device(0, bus, devfn);
+        if ( !ret && ats_device(seg, bus, devfn) )
+            enable_ats_device(seg, bus, devfn);
 
         break;
 
     case DEV_TYPE_PCI:
         if ( iommu_verbose )
-            dprintk(VTDPREFIX, "d%d:PCI: map bdf = %x:%x.%x\n",
-                    domain->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+            dprintk(VTDPREFIX, "d%d:PCI: 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 )
@@ -1442,9 +1448,9 @@
         break;
 
     default:
-        dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): bdf = %x:%x.%x\n",
+        dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): %04x:%02x:%02x.%u\n",
                 domain->domain_id, type,
-                bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+                seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
         ret = -EINVAL;
         break;
     }
@@ -1503,19 +1509,21 @@
     spin_unlock(&iommu->lock);
     unmap_vtd_domain_page(context_entries);
 
-    me_wifi_quirk(domain, bus, devfn, UNMAP_ME_PHANTOM_FUNC);
+    if ( !iommu->intel->drhd->segment )
+        me_wifi_quirk(domain, bus, devfn, UNMAP_ME_PHANTOM_FUNC);
 
     return 0;
 }
 
-static int domain_context_unmap(struct domain *domain, u8 bus, u8 devfn)
+static int domain_context_unmap(
+    struct domain *domain, u16 seg, u8 bus, u8 devfn)
 {
     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(0, bus, devfn);
+    struct pci_dev *pdev = pci_get_pdev(seg, bus, devfn);
     int found = 0;
 
     BUG_ON(!pdev);
@@ -1535,18 +1543,19 @@
 
     case DEV_TYPE_PCIe_ENDPOINT:
         if ( iommu_verbose )
-            dprintk(VTDPREFIX, "d%d:PCIe: unmap bdf = %x:%x.%x\n",
-                    domain->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+            dprintk(VTDPREFIX, "d%d:PCIe: unmap %04x:%02x:%02x.%u\n",
+                    domain->domain_id, seg, bus,
+                    PCI_SLOT(devfn), PCI_FUNC(devfn));
         ret = domain_context_unmap_one(domain, iommu, bus, devfn);
-        if ( !ret && ats_device(0, bus, devfn) )
-            disable_ats_device(0, bus, devfn);
+        if ( !ret && ats_device(seg, bus, devfn) )
+            disable_ats_device(seg, bus, devfn);
 
         break;
 
     case DEV_TYPE_PCI:
         if ( iommu_verbose )
-            dprintk(VTDPREFIX, "d%d:PCI: unmap bdf = %x:%x.%x\n",
-                    domain->domain_id, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+            dprintk(VTDPREFIX, "d%d:PCI: unmap %04x:%02x:%02x.%u\n",
+                    domain->domain_id, seg, bus, PCI_SLOT(devfn), 
PCI_FUNC(devfn));
         ret = domain_context_unmap_one(domain, iommu, bus, devfn);
         if ( ret )
             break;
@@ -1571,9 +1580,9 @@
         break;
 
     default:
-        dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): bdf = %x:%x.%x\n",
+        dprintk(XENLOG_ERR VTDPREFIX, "d%d:unknown(%u): %04x:%02x:%02x.%u\n",
                 domain->domain_id, type,
-                bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+                seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
         ret = -EINVAL;
         goto out;
     }
@@ -1584,7 +1593,7 @@
      */
     for_each_pdev ( domain, pdev )
     {
-        if ( pdev->bus == bus && pdev->devfn == devfn )
+        if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn )
             continue;
 
         drhd = acpi_find_matched_drhd_unit(pdev);
@@ -1639,11 +1648,11 @@
     if ( (target != dom0) && !iommu_intremap )
         untrusted_msi = 1;
 
-    ret = domain_context_unmap(source, bus, devfn);
+    ret = domain_context_unmap(source, seg, bus, devfn);
     if ( ret )
         return ret;
 
-    ret = domain_context_mapping(target, bus, devfn);
+    ret = domain_context_mapping(target, seg, bus, devfn);
     if ( ret )
         return ret;
 
@@ -1878,7 +1887,8 @@
     if ( !pdev->domain )
         return -EINVAL;
 
-    ret = domain_context_mapping(pdev->domain, pdev->bus, pdev->devfn);
+    ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus,
+                                 pdev->devfn);
     if ( ret )
     {
         dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n",
@@ -1888,7 +1898,9 @@
 
     for_each_rmrr_device ( rmrr, bdf, i )
     {
-        if ( PCI_BUS(bdf) == pdev->bus && PCI_DEVFN2(bdf) == pdev->devfn )
+        if ( rmrr->segment == pdev->seg &&
+             PCI_BUS(bdf) == pdev->bus &&
+             PCI_DEVFN2(bdf) == pdev->devfn )
         {
             ret = rmrr_identity_mapping(pdev->domain, rmrr);
             if ( ret )
@@ -1916,13 +1928,15 @@
     {
         for_each_rmrr_device ( rmrr, bdf, i )
         {
-            if ( PCI_BUS(bdf) == pdev->bus &&
+            if ( rmrr->segment == pdev->seg &&
+                 PCI_BUS(bdf) == pdev->bus &&
                  PCI_DEVFN2(bdf) == pdev->devfn )
                 return 0;
         }
     }
 
-    return domain_context_unmap(pdev->domain, pdev->bus, pdev->devfn);
+    return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus,
+                                pdev->devfn);
 }
 
 static void __init setup_dom0_devices(struct domain *d)
@@ -1941,7 +1955,7 @@
 
             pdev->domain = d;
             list_add(&pdev->domain_list, &d->arch.pdev_list);
-            domain_context_mapping(d, pdev->bus, pdev->devfn);
+            domain_context_mapping(d, pdev->seg, pdev->bus, pdev->devfn);
             pci_enable_acs(pdev);
             pci_vtd_quirk(pdev);
         }
@@ -2183,7 +2197,7 @@
     /* FIXME: Because USB RMRR conflicts with guest bios region,
      * ignore USB RMRR temporarily.
      */
-    if ( is_usb_device(bus, devfn) )
+    if ( is_usb_device(seg, bus, devfn) )
     {
         ret = 0;
         goto done;
@@ -2192,7 +2206,9 @@
     /* Setup rmrr identity mapping */
     for_each_rmrr_device( rmrr, bdf, i )
     {
-        if ( PCI_BUS(bdf) == bus && PCI_DEVFN2(bdf) == devfn )
+        if ( rmrr->segment == seg &&
+             PCI_BUS(bdf) == bus &&
+             PCI_DEVFN2(bdf) == devfn )
         {
             ret = rmrr_identity_mapping(d, rmrr);
             if ( ret )
diff -r ec7c81fbe0de -r 85418e168527 xen/drivers/passthrough/vtd/utils.c
--- a/xen/drivers/passthrough/vtd/utils.c       Thu Sep 22 18:26:54 2011 +0100
+++ b/xen/drivers/passthrough/vtd/utils.c       Thu Sep 22 18:27:26 2011 +0100
@@ -32,7 +32,7 @@
 #include <asm/io_apic.h>
 #endif
 
-int is_usb_device(u8 bus, u8 devfn)
+int is_usb_device(u16 seg, u8 bus, u8 devfn)
 {
     u16 class = pci_conf_read16(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
                                 PCI_CLASS_DEVICE);
@@ -106,8 +106,9 @@
     u64 *l, val;
     u32 l_index, level;
 
-    printk("print_vtd_entries: iommu = %p bdf = %x:%x.%x gmfn = %"PRIx64"\n",
-           iommu, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), gmfn);
+    printk("print_vtd_entries: iommu %p dev %04x:%02x:%02x.%u gmfn 
%"PRIx64"\n",
+           iommu, iommu->intel->drhd->segment, bus,
+           PCI_SLOT(devfn), PCI_FUNC(devfn), gmfn);
 
     if ( iommu->root_maddr == 0 )
     {
diff -r ec7c81fbe0de -r 85418e168527 xen/drivers/passthrough/vtd/x86/ats.c
--- a/xen/drivers/passthrough/vtd/x86/ats.c     Thu Sep 22 18:26:54 2011 +0100
+++ b/xen/drivers/passthrough/vtd/x86/ats.c     Thu Sep 22 18:27:26 2011 +0100
@@ -104,7 +104,7 @@
          !ecap_dev_iotlb(drhd->iommu->ecap) )
         return 0;
 
-    if ( !acpi_find_matched_atsr_unit(bus, devfn) )
+    if ( !acpi_find_matched_atsr_unit(seg, bus, devfn) )
         return 0;
 
     ats_drhd = find_ats_dev_drhd(drhd->iommu);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.