File 20323-vtd-acpi-off-panic.patch of Package xen

# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1255678127 -3600
# Node ID 2370e16ab6d3a1c9de43babec48c8f14121d19bc
# Parent  648c674fcc96b09fc8fb9428843fec08c8d2fc4e
vt-d: Fixpanic in msi_msg_read_remap_rte with acpi=off

Xen panics when "acpi=off noacpi" is set. Problem is caused by
dereferencing NULL pointer in drhd after calling
acpi_find_matched_drhd_unit. As acpi_find_matched_drhd_unit can
return NULL, checks has to be done before returned value is used.

From: Miroslav Rezanina <mrezanin@redhat.com>
Signed-off-by: Keir Fraser <keir.fraser@eu.citrix.com>

# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1255955481 -3600
# Node ID ea34183c5c11a5c0525da7871be79309d3fdda64
# Parent  a8b16874a5f0ecd952cf8ef00b62c126cce66be6
vtd: A few cleanups to avoid dereferencing NULL drhd pointers.

In most cases I simply remove the reference since it is never actually
used.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>

# HG changeset patch
# User Keir Fraser <keir.fraser@citrix.com>
# Date 1255967414 -3600
# Node ID 1c928c3566e0f41ba582edd21ae02f0787bf1362
# Parent  ea34183c5c11a5c0525da7871be79309d3fdda64
vtd: Disable VT-d if no DRHD units are probed.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>

--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -507,7 +507,8 @@ void msi_msg_read_remap_rte(
     struct iommu *iommu = NULL;
     struct ir_ctrl *ir_ctrl;
 
-    drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn);
+    if ( (drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn)) == NULL )
+        return;
     iommu = drhd->iommu;
 
     ir_ctrl = iommu_ir_ctrl(iommu);
@@ -525,7 +526,8 @@ void msi_msg_write_remap_rte(
     struct iommu *iommu = NULL;
     struct ir_ctrl *ir_ctrl;
 
-    drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn);
+    if ( (drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn)) == NULL )
+        return;
     iommu = drhd->iommu;
 
     ir_ctrl = iommu_ir_ctrl(iommu);
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -1024,13 +1024,10 @@ static void iommu_free(struct acpi_drhd_
 static int intel_iommu_domain_init(struct domain *d)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
-    struct iommu *iommu = NULL;
+    struct iommu *iommu;
     u64 i;
     struct acpi_drhd_unit *drhd;
 
-    drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
-    iommu = drhd->iommu;
-
     hd->agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
 
     if ( d->domain_id == 0 )
@@ -1126,10 +1123,6 @@ static int domain_context_mapping_one(
         context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL);
     }
 
-    /*
-     * domain_id 0 is not valid on Intel's IOMMU, force domain_id to
-     * be 1 based as required by intel's iommu hw.
-     */
     context_set_domain_id(context, domain);
     context_set_address_width(*context, agaw);
     context_set_fault_enable(*context);
@@ -1414,7 +1407,8 @@ static int reassign_device_ownership(
     if ( !(pdev = pci_lock_domain_pdev(source, bus, devfn)) )
         return -ENODEV;
 
-    drhd = acpi_find_matched_drhd_unit(bus, devfn);
+    if ( (drhd = acpi_find_matched_drhd_unit(bus, devfn)) == NULL )
+        return -ENODEV;
     pdev_iommu = drhd->iommu;
     domain_context_unmap(source, bus, devfn);
 
@@ -1433,7 +1427,7 @@ static int reassign_device_ownership(
     for_each_pdev ( source, pdev )
     {
         drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn);
-        if ( drhd->iommu == pdev_iommu )
+        if ( drhd && drhd->iommu == pdev_iommu )
         {
             found = 1;
             break;
@@ -1480,9 +1474,6 @@ int intel_iommu_map_page(
     u64 pg_maddr;
     int pte_present;
 
-    drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
-    iommu = drhd->iommu;
-
     /* do nothing if dom0 and iommu supports pass thru */
     if ( iommu_passthrough && (d->domain_id == 0) )
         return 0;
@@ -1521,13 +1512,7 @@ int intel_iommu_map_page(
 
 int intel_iommu_unmap_page(struct domain *d, unsigned long gfn)
 {
-    struct acpi_drhd_unit *drhd;
-    struct iommu *iommu;
-
-    drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
-    iommu = drhd->iommu;
-
-    /* do nothing if dom0 and iommu supports pass thru */
+    /* Do nothing if dom0 and iommu supports pass thru. */
     if ( iommu_passthrough && (d->domain_id == 0) )
         return 0;
 
@@ -1828,7 +1813,7 @@ int intel_vtd_setup(void)
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
 
-    if ( !vtd_enabled )
+    if ( !vtd_enabled || list_empty(&acpi_drhd_units) )
         return -ENODEV;
 
     platform_quirks();
@@ -1866,18 +1851,15 @@ int intel_vtd_setup(void)
     P(iommu_intremap, "Interrupt Remapping");
 #undef P
 
-    /* Allocate IO page directory page for the domain. */
+    /* Allocate domain id bitmap, and set bit 0 as reserved. */
     drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
-    iommu = drhd->iommu;
-
-    /* Allocate domain id bitmap, and set bit 0 as reserved */
-    domid_bitmap_size = cap_ndoms(iommu->cap);
+    domid_bitmap_size = cap_ndoms(drhd->iommu->cap);
     domid_bitmap = xmalloc_array(unsigned long,
                                  BITS_TO_LONGS(domid_bitmap_size));
     if ( domid_bitmap == NULL )
         goto error;
     memset(domid_bitmap, 0, domid_bitmap_size / 8);
-    set_bit(0, domid_bitmap);
+    __set_bit(0, domid_bitmap);
 
     if ( init_vtd_hw() )
         goto error;
openSUSE Build Service is sponsored by