iommu: New options iommu=dom-strict and iommu=dom0-passthrough
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 9 Jul 2010 15:45:42 +0000 (16:45 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 9 Jul 2010 15:45:42 +0000 (16:45 +0100)
The former strips dom0 of its usual 1:1 mapping of all memory, and
only provides it with mappings of its own memory, like any other
domain. The latter is a new consistent name for iommu=passthrough.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/x86_64/mm.c
xen/drivers/passthrough/amd/pci_amd_iommu.c
xen/drivers/passthrough/iommu.c
xen/drivers/passthrough/vtd/iommu.c

index f1f28b76599b4ee85ce1438310cee17f0bf3e913..271cea5ef3b66621c35fce6446ec6084cc6de6d7 100644 (file)
@@ -1462,12 +1462,18 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
     if ( ret )
         goto destroy_m2p;
 
-    for ( i = spfn; i < epfn; i++ )
-        if ( iommu_map_page(dom0, i, i, IOMMUF_readable|IOMMUF_writable) )
-            break;
-
-    if ( i != epfn )
-        goto destroy_iommu;
+    if ( !need_iommu(dom0) )
+    {
+        for ( i = spfn; i < epfn; i++ )
+            if ( iommu_map_page(dom0, i, i, IOMMUF_readable|IOMMUF_writable) )
+                break;
+        if ( i != epfn )
+        {
+            while (i-- > old_max)
+                iommu_unmap_page(dom0, i);
+            goto destroy_m2p;
+        }
+    }
 
     /* We can't revert any more */
     transfer_pages_to_heap(&info);
@@ -1476,10 +1482,6 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
 
     return 0;
 
-destroy_iommu:
-    while (i-- > old_max)
-        iommu_unmap_page(dom0, i);
-
 destroy_m2p:
     destroy_m2p_mapping(&info);
     max_page = old_max;
index d1c97e3ae3b544843f9e1d6b99e8d4f32c29b426..d0247d33059ef969930d64ad9f560544215ba61c 100644 (file)
@@ -231,7 +231,7 @@ static int amd_iommu_domain_init(struct domain *domain)
     {
         unsigned long i; 
 
-        if ( !iommu_passthrough )
+        if ( !iommu_passthrough && !need_iommu(domain) )
         {
             /* setup 1:1 page table for dom0 */
             for ( i = 0; i < max_page; i++ )
index b592800a19e9b1868c3535b5e9f3e5c739e51f85..e755d6d59f518008135622d8e5b35a2146a5b902 100644 (file)
@@ -30,8 +30,8 @@ static int iommu_populate_page_table(struct domain *d);
  *   force|required             Don't boot unless IOMMU is enabled
  *   workaround_bios_bug        Workaround some bios issue to still enable
                                 VT-d, don't guarantee security
- *   passthrough                Enable VT-d DMA passthrough (no DMA
- *                              translation for Dom0)
+ *   dom0-passthrough           No DMA translation at all for Dom0
+ *   dom0-strict                No 1:1 memory mapping for Dom0
  *   no-snoop                   Disable VT-d Snoop Control
  *   no-qinval                  Disable VT-d Queued Invalidation
  *   no-intremap                Disable VT-d Interrupt Remapping
@@ -39,6 +39,7 @@ static int iommu_populate_page_table(struct domain *d);
 custom_param("iommu", parse_iommu_param);
 bool_t __read_mostly iommu_enabled = 1;
 bool_t __read_mostly force_iommu;
+bool_t __read_mostly iommu_dom0_strict;
 bool_t __read_mostly iommu_verbose;
 bool_t __read_mostly iommu_workaround_bios_bug;
 bool_t __read_mostly iommu_passthrough;
@@ -64,8 +65,6 @@ static void __init parse_iommu_param(char *s)
             force_iommu = 1;
         else if ( !strcmp(s, "workaround_bios_bug") )
             iommu_workaround_bios_bug = 1;
-        else if ( !strcmp(s, "passthrough") )
-            iommu_passthrough = 1;
         else if ( !strcmp(s, "verbose") )
             iommu_verbose = 1;
         else if ( !strcmp(s, "no-snoop") )
@@ -78,14 +77,18 @@ static void __init parse_iommu_param(char *s)
             amd_iommu_debug = 1;
         else if ( !strcmp(s, "amd-iommu-perdev-intremap") )
             amd_iommu_perdev_intremap = 1;
+        else if ( !strcmp(s, "dom0-passthrough") )
+            iommu_passthrough = 1;
+        else if ( !strcmp(s, "dom0-strict") )
+            iommu_dom0_strict = 1;
 
         s = ss + 1;
     } while ( ss );
 }
 
-int iommu_domain_init(struct domain *domain)
+int iommu_domain_init(struct domain *d)
 {
-    struct hvm_iommu *hd = domain_hvm_iommu(domain);
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
 
     spin_lock_init(&hd->mapping_lock);
     INIT_LIST_HEAD(&hd->g2m_ioport_list);
@@ -94,8 +97,10 @@ int iommu_domain_init(struct domain *domain)
     if ( !iommu_enabled )
         return 0;
 
+    d->need_iommu = ((d->domain_id == 0) && iommu_dom0_strict);
+
     hd->platform_ops = iommu_get_ops();
-    return hd->platform_ops->init(domain);
+    return hd->platform_ops->init(d);
 }
 
 int iommu_add_device(struct pci_dev *pdev)
@@ -276,6 +281,9 @@ int __init iommu_setup(void)
 {
     int rc = -ENODEV;
 
+    if ( iommu_dom0_strict )
+        iommu_passthrough = 0;
+
     if ( iommu_enabled )
     {
         rc = iommu_hardware_setup();
@@ -290,8 +298,15 @@ int __init iommu_setup(void)
         iommu_snoop = 0;
         iommu_qinval = 0;
         iommu_intremap = 0;
+        iommu_passthrough = 0;
+        iommu_dom0_strict = 0;
     }
     printk("I/O virtualisation %sabled\n", iommu_enabled ? "en" : "dis");
+    if ( iommu_enabled )
+        printk(" - Dom0 mode: %s\n",
+               iommu_passthrough ? "Passthrough" :
+               iommu_dom0_strict ? "Strict" : "Relaxed");
+
     return rc;
 }
 
index b8684141bbcc5e0b780975bab6f05e861035b6ee..1ed8f1f71b4b356f636e7b50a20df98c0e02e027 100644 (file)
@@ -1179,7 +1179,8 @@ static int intel_iommu_domain_init(struct domain *d)
     if ( d->domain_id == 0 )
     {
         /* Set up 1:1 page table for dom0 */
-        iommu_set_dom0_mapping(d);
+        if ( !need_iommu(d) )
+            iommu_set_dom0_mapping(d);
 
         setup_dom0_devices(d);
         setup_dom0_rmrr(d);