WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] PCI multi-seg: VT-d specific adjustments
From: Xen patchbot-unstable <patchbot@xxxxxxx>
Date: Wed, 28 Sep 2011 02:55:11 +0100
Delivery-date: Tue, 27 Sep 2011 18:55:20 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] PCI multi-seg: VT-d specific adjustments, Xen patchbot-unstable <=