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

[Xen-changelog] [xen-unstable] vtd: Only enable some VT-d features if all VT-d engines support them.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1237376792 0
# Node ID 6d65dc14d21b5b598de925d1b1e0aa8305092273
# Parent  33270c9a3d2f56006a166b42ae0d717bc6b1644f
vtd: Only enable some VT-d features if all VT-d engines support them.

By default, we enable snoop control, queued invalidation and interrupt
remapping if all VT-d engines support them, and for DMA passthrough we
don't enable it by default.

A user can use 'iommu=passthrough' to enable DMA passthrough (only
for Dom0). A user can use 'iommu=no-snoop,no-qinval,no-intremap' to
disable the 3 features.

Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>=
---
 xen/drivers/passthrough/iommu.c     |   18 ++++--
 xen/drivers/passthrough/vtd/dmar.c  |    2 
 xen/drivers/passthrough/vtd/iommu.c |   95 +++++++++++++++++++++---------------
 xen/include/xen/iommu.h             |    2 
 4 files changed, 74 insertions(+), 43 deletions(-)

diff -r 33270c9a3d2f -r 6d65dc14d21b xen/drivers/passthrough/iommu.c
--- a/xen/drivers/passthrough/iommu.c   Wed Mar 18 11:37:59 2009 +0000
+++ b/xen/drivers/passthrough/iommu.c   Wed Mar 18 11:46:32 2009 +0000
@@ -32,9 +32,11 @@ int amd_iov_detect(void);
  *   pv                         Enable IOMMU for PV domains
  *   no-pv                      Disable IOMMU for PV domains (default)
  *   force|required             Don't boot unless IOMMU is enabled
- *   passthrough                Bypass VT-d translation for Dom0
- *   snoop                      Utilize the snoop control for IOMMU (default)
- *   no-snoop                   Dont utilize the snoop control for IOMMU
+ *   passthrough                Enable VT-d DMA passthrough (no DMA
+ *                              translation for Dom0)
+ *   no-snoop                   Disable VT-d Snoop Control
+ *   no-qinval                  Disable VT-d Queued Invalidation
+ *   no-intremap                Disable VT-d Interrupt Remapping
  */
 custom_param("iommu", parse_iommu_param);
 int iommu_enabled = 0;
@@ -42,12 +44,16 @@ int force_iommu = 0;
 int force_iommu = 0;
 int iommu_passthrough = 0;
 int iommu_snoop = 0;
+int iommu_qinval = 0;
+int iommu_intremap = 0;
 
 static void __init parse_iommu_param(char *s)
 {
     char *ss;
     iommu_enabled = 1;
     iommu_snoop = 1;
+    iommu_qinval = 1;
+    iommu_intremap = 1;
 
     do {
         ss = strchr(s, ',');
@@ -65,10 +71,12 @@ static void __init parse_iommu_param(cha
             force_iommu = 1;
         else if ( !strcmp(s, "passthrough") )
             iommu_passthrough = 1;
-        else if ( !strcmp(s, "snoop") )
-            iommu_snoop = 1;
         else if ( !strcmp(s, "no-snoop") )
             iommu_snoop = 0;
+        else if ( !strcmp(s, "no-qinval") )
+            iommu_qinval = 0;
+        else if ( !strcmp(s, "no-intremap") )
+            iommu_intremap = 0;
 
         s = ss + 1;
     } while ( ss );
diff -r 33270c9a3d2f -r 6d65dc14d21b xen/drivers/passthrough/vtd/dmar.c
--- a/xen/drivers/passthrough/vtd/dmar.c        Wed Mar 18 11:37:59 2009 +0000
+++ b/xen/drivers/passthrough/vtd/dmar.c        Wed Mar 18 11:46:32 2009 +0000
@@ -548,7 +548,7 @@ int acpi_dmar_init(void)
     if ( list_empty(&acpi_drhd_units) )
         goto fail;
 
-    printk("Intel VT-d has been enabled\n");
+    printk("Intel VT-d DMAR tables have been parsed.\n");
 
     return 0;
 
diff -r 33270c9a3d2f -r 6d65dc14d21b xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Wed Mar 18 11:37:59 2009 +0000
+++ b/xen/drivers/passthrough/vtd/iommu.c       Wed Mar 18 11:46:32 2009 +0000
@@ -1041,8 +1041,7 @@ static int domain_context_mapping_one(
         return res;
     }
 
-    if ( iommu_passthrough &&
-         ecap_pass_thru(iommu->ecap) && (domain->domain_id == 0) )
+    if ( iommu_passthrough && (domain->domain_id == 0) )
     {
         context_set_translation_type(*context, CONTEXT_TT_PASS_THRU);
         agaw = level_to_agaw(iommu->nr_pt_levels);
@@ -1449,8 +1448,7 @@ int intel_iommu_map_page(
     iommu = drhd->iommu;
 
     /* do nothing if dom0 and iommu supports pass thru */
-    if ( iommu_passthrough &&
-         ecap_pass_thru(iommu->ecap) && (d->domain_id == 0) )
+    if ( iommu_passthrough && (d->domain_id == 0) )
         return 0;
 
     spin_lock(&hd->mapping_lock);
@@ -1504,8 +1502,7 @@ int intel_iommu_unmap_page(struct domain
     iommu = drhd->iommu;
 
     /* do nothing if dom0 and iommu supports pass thru */
-    if ( iommu_passthrough &&
-         ecap_pass_thru(iommu->ecap) && (d->domain_id == 0) )
+    if ( iommu_passthrough && (d->domain_id == 0) )
         return 0;
 
     dma_pte_clear_one(d, (paddr_t)gfn << PAGE_SHIFT_4K);
@@ -1682,20 +1679,32 @@ static int init_vtd_hw(void)
         flush->iotlb = flush_iotlb_reg;
     }
 
-    for_each_drhd_unit ( drhd )
-    {
-        iommu = drhd->iommu;
-        if ( qinval_setup(iommu) != 0 )
-            dprintk(XENLOG_INFO VTDPREFIX,
-                    "Queued Invalidation hardware not found\n");
-    }
-
-    for_each_drhd_unit ( drhd )
-    {
-        iommu = drhd->iommu;
-        if ( intremap_setup(iommu) != 0 )
-            dprintk(XENLOG_INFO VTDPREFIX,
-                    "Interrupt Remapping hardware not found\n");
+    if ( iommu_qinval )
+    {
+        for_each_drhd_unit ( drhd )
+        {
+            iommu = drhd->iommu;
+            if ( qinval_setup(iommu) != 0 )
+            {
+                dprintk(XENLOG_INFO VTDPREFIX,
+                        "Failed to enable Queued Invalidation!\n");
+                break;
+            }
+        }
+    }
+
+    if ( iommu_intremap )
+    {
+        for_each_drhd_unit ( drhd )
+        {
+            iommu = drhd->iommu;
+            if ( intremap_setup(iommu) != 0 )
+            {
+                dprintk(XENLOG_INFO VTDPREFIX,
+                        "Failed to enable Interrupt Remapping!\n");
+                break;
+            }
+        }
     }
 
     return 0;
@@ -1744,9 +1753,35 @@ int intel_vtd_setup(void)
     spin_lock_init(&domid_bitmap_lock);
     clflush_size = get_cache_line_size();
 
+    /* We enable the following features only if they are supported by all VT-d
+     * engines: Snoop Control, DMA passthrough, Queued Invalidation and
+     * Interrupt Remapping.
+     */
     for_each_drhd_unit ( drhd )
+    {
         if ( iommu_alloc(drhd) != 0 )
             goto error;
+
+        iommu = drhd->iommu;
+
+        if ( iommu_snoop && !ecap_snp_ctl(iommu->ecap) )
+            iommu_snoop = 0;
+
+        if ( iommu_passthrough && !ecap_pass_thru(iommu->ecap) )
+            iommu_passthrough = 0;
+
+        if ( iommu_qinval && !ecap_queued_inval(iommu->ecap) )
+            iommu_qinval = 0;
+
+        if ( iommu_intremap && !ecap_intr_remap(iommu->ecap) )
+            iommu_intremap = 0;
+    }
+#define P(p,s) printk("Intel VT-d %s %ssupported.\n", s, (p)? "" : "not ")
+    P(iommu_snoop, "Snoop Control");
+    P(iommu_passthrough, "DMA Passthrough");
+    P(iommu_qinval, "Queued Invalidation");
+    P(iommu_intremap, "Interrupt Remapping");
+#undef P
 
     /* Allocate IO page directory page for the domain. */
     drhd = list_entry(acpi_drhd_units.next, typeof(*drhd), list);
@@ -1764,23 +1799,6 @@ int intel_vtd_setup(void)
     if ( init_vtd_hw() )
         goto error;
 
-    /* Giving that all devices within guest use same io page table,
-     * enable snoop control only if all VT-d engines support it.
-     */
-
-    if ( iommu_snoop )
-    {
-        for_each_drhd_unit ( drhd )
-        {
-            iommu = drhd->iommu;
-            if ( !ecap_snp_ctl(iommu->ecap) ) {
-                iommu_snoop = 0;
-                break;
-            }
-        }
-    }
-    
-    printk("Intel VT-d snoop control %sabled\n", iommu_snoop ? "en" : "dis");
     register_keyhandler('V', dump_iommu_info, "dump iommu info");
 
     return 0;
@@ -1790,6 +1808,9 @@ int intel_vtd_setup(void)
         iommu_free(drhd);
     vtd_enabled = 0;
     iommu_snoop = 0;
+    iommu_passthrough = 0;
+    iommu_qinval = 0;
+    iommu_intremap = 0;
     return -ENOMEM;
 }
 
diff -r 33270c9a3d2f -r 6d65dc14d21b xen/include/xen/iommu.h
--- a/xen/include/xen/iommu.h   Wed Mar 18 11:37:59 2009 +0000
+++ b/xen/include/xen/iommu.h   Wed Mar 18 11:46:32 2009 +0000
@@ -32,6 +32,8 @@ extern int force_iommu;
 extern int force_iommu;
 extern int iommu_passthrough;
 extern int iommu_snoop;
+extern int iommu_qinval;
+extern int iommu_intremap;
 
 #define domain_hvm_iommu(d)     (&d->arch.hvm_domain.hvm_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®.