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-devel

[Xen-devel] [PATCH] VT-d/ATS: misc fixes

To: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] VT-d/ATS: misc fixes
From: "Jan Beulich" <JBeulich@xxxxxxxxxx>
Date: Tue, 18 Jan 2011 11:32:41 +0000
Delivery-date: Tue, 18 Jan 2011 03:35:44 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
First of all there were three places potentially de-referencing NULL
(two after an allocation failure, and one after a failed lookup).

Second, if ATS_ENABLE was already set, the device would not have got
added to the ats_devices list, potentially resulting in
dev_invalidate_iotlb() doing an incomplete job.

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

--- a/xen/drivers/passthrough/vtd/x86/ats.c
+++ b/xen/drivers/passthrough/vtd/x86/ats.c
@@ -93,6 +93,9 @@ int ats_device(int seg, int bus, int dev
         return 0;
 
     pdev = pci_get_pdev(bus, devfn);
+    if ( !pdev )
+        return 0;
+
     drhd = acpi_find_matched_drhd_unit(pdev);
     if ( !drhd )
         return 0;
@@ -110,6 +113,8 @@ int ats_device(int seg, int bus, int dev
     if ( pos && (ats_drhd == NULL) )
     {
         new_drhd = xmalloc(struct acpi_drhd_unit);
+        if ( !new_drhd )
+            return 0;
         memcpy(new_drhd, drhd, sizeof(struct acpi_drhd_unit));
         list_add_tail(&new_drhd->list, &ats_dev_drhd_units);
     }
@@ -118,9 +123,8 @@ int ats_device(int seg, int bus, int dev
 
 int enable_ats_device(int seg, int bus, int devfn)
 {
-    struct pci_ats_dev *pdev;
+    struct pci_ats_dev *pdev = NULL;
     u32 value;
-    u16 queue_depth;
     int pos;
 
     if ( !acpi_find_matched_atsr_unit(bus, devfn) )
@@ -144,26 +148,43 @@ int enable_ats_device(int seg, int bus, 
 
     /* BUGBUG: add back seg when multi-seg platform support is enabled */
     value = pci_conf_read16(bus, PCI_SLOT(devfn),
-                            PCI_FUNC(devfn), pos + ATS_REG_CAP);
-    queue_depth = value & ATS_QUEUE_DEPTH_MASK;
-
-    value = pci_conf_read16(bus, PCI_SLOT(devfn),
                             PCI_FUNC(devfn), pos + ATS_REG_CTL);
     if ( value & ATS_ENABLE )
-        return 0;
+    {
+        list_for_each_entry ( pdev, &ats_devices, list )
+        {
+            if ( pdev->bus == bus && pdev->devfn == devfn )
+            {
+                pos = 0;
+                break;
+            }
+        }
+    }
+    if ( pos )
+        pdev = xmalloc(struct pci_ats_dev);
+    if ( !pdev )
+        return -ENOMEM;
 
-    value |= ATS_ENABLE;
-    pci_conf_write16(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
-                     pos + ATS_REG_CTL, value);
+    if ( !(value & ATS_ENABLE) )
+    {
+        value |= ATS_ENABLE;
+        pci_conf_write16(bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+                         pos + ATS_REG_CTL, value);
+    }
+
+    if ( pos )
+    {
+        pdev->bus = bus;
+        pdev->devfn = devfn;
+        value = pci_conf_read16(bus, PCI_SLOT(devfn),
+                                PCI_FUNC(devfn), pos + ATS_REG_CAP);
+        pdev->ats_queue_depth = value & ATS_QUEUE_DEPTH_MASK;
+        list_add(&pdev->list, &ats_devices);
+    }
 
-    pdev = xmalloc(struct pci_ats_dev);
-    pdev->bus = bus;
-    pdev->devfn = devfn;
-    pdev->ats_queue_depth = queue_depth;
-    list_add(&(pdev->list), &ats_devices);
     if ( iommu_verbose )
-        dprintk(XENLOG_INFO VTDPREFIX, "%x:%x.%x: ATS is enabled\n",
-                bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+        dprintk(XENLOG_INFO VTDPREFIX, "%x:%x.%x: ATS %s enabled\n",
+                bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos ? "is" : "was");
 
     return pos;
 }



Attachment: vtd-ats-null-deref.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>