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

[Xen-changelog] [xen-4.0-testing] iommu: New options iommu=dom-strict and iommu=dom0-passthrough



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1279699827 -3600
# Node ID 7ab7cdbb7a3f501e2e6049455cd52ea653f3997f
# Parent  007ec1eea2552515246683e1092652148d958a8d
iommu: New options iommu=dom-strict and iommu=dom0-passthrough

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@xxxxxxxxxx>
xen-unstable changeset:   21771:42ccccfe1a6a
xen-unstable date:        Fri Jul 09 16:45:42 2010 +0100

iommu: Map dom0 initial allocation in 'dom0-strict' iommu mode.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   21812:e382656e4dcc
xen-unstable date:        Fri Jul 16 16:19:51 2010 +0100
---
 xen/arch/ia64/xen/domain.c                  |    2 
 xen/arch/x86/domain_build.c                 |    2 
 xen/arch/x86/x86_64/mm.c                    |   22 +++++-----
 xen/drivers/passthrough/amd/pci_amd_iommu.c |   44 ++++++++++----------
 xen/drivers/passthrough/iommu.c             |   59 ++++++++++++++++++++++++----
 xen/drivers/passthrough/vtd/iommu.c         |   39 ++++++++++--------
 xen/include/xen/iommu.h                     |    2 
 7 files changed, 113 insertions(+), 57 deletions(-)

diff -r 007ec1eea255 -r 7ab7cdbb7a3f xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Wed Jul 21 09:08:45 2010 +0100
+++ b/xen/arch/ia64/xen/domain.c        Wed Jul 21 09:10:27 2010 +0100
@@ -2296,6 +2296,8 @@ int __init construct_dom0(struct domain 
 
        physdev_init_dom0(d);
 
+       iommu_dom0_init(d);
+
        return 0;
 }
 
diff -r 007ec1eea255 -r 7ab7cdbb7a3f xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Wed Jul 21 09:08:45 2010 +0100
+++ b/xen/arch/x86/domain_build.c       Wed Jul 21 09:10:27 2010 +0100
@@ -1134,6 +1134,8 @@ int __init construct_dom0(
 
     BUG_ON(rc != 0);
 
+    iommu_dom0_init(dom0);
+
     return 0;
 }
 
diff -r 007ec1eea255 -r 7ab7cdbb7a3f xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Wed Jul 21 09:08:45 2010 +0100
+++ b/xen/arch/x86/x86_64/mm.c  Wed Jul 21 09:10:27 2010 +0100
@@ -1460,12 +1460,18 @@ int memory_add(unsigned long spfn, unsig
     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);
@@ -1473,10 +1479,6 @@ int memory_add(unsigned long spfn, unsig
     share_hotadd_m2p_table(&info);
 
     return 0;
-
-destroy_iommu:
-    while (i-- > old_max)
-        iommu_unmap_page(dom0, i);
 
 destroy_m2p:
     destroy_m2p_mapping(&info);
diff -r 007ec1eea255 -r 7ab7cdbb7a3f xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c       Wed Jul 21 09:08:45 
2010 +0100
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c       Wed Jul 21 09:10:27 
2010 +0100
@@ -212,9 +212,9 @@ static int get_paging_mode(unsigned long
     return level;
 }
 
-static int amd_iommu_domain_init(struct domain *domain)
-{
-    struct hvm_iommu *hd = domain_hvm_iommu(domain);
+static int amd_iommu_domain_init(struct domain *d)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
 
     /* allocate page directroy */
     if ( allocate_domain_resources(hd) != 0 )
@@ -224,27 +224,26 @@ static int amd_iommu_domain_init(struct 
         return -ENOMEM;
     }
 
-    hd->paging_mode = is_hvm_domain(domain)?
+    hd->paging_mode = is_hvm_domain(d) ?
         IOMMU_PAGE_TABLE_LEVEL_4 : get_paging_mode(max_page);
 
-    if ( domain->domain_id == 0 )
-    {
-        unsigned long i; 
-
-        if ( !iommu_passthrough )
-        {
-            /* setup 1:1 page table for dom0 */
-            for ( i = 0; i < max_page; i++ )
-                amd_iommu_map_page(domain, i, i,
-                                   IOMMUF_readable|IOMMUF_writable);
-        }
-
-        amd_iommu_setup_dom0_devices(domain);
-    }
-
-    hd->domain_id = domain->domain_id;
-
-    return 0;
+    hd->domain_id = d->domain_id;
+
+    return 0;
+}
+
+static void amd_iommu_dom0_init(struct domain *d)
+{
+    unsigned long i; 
+
+    if ( !iommu_passthrough && !need_iommu(d) )
+    {
+        /* Set up 1:1 page table for dom0 */
+        for ( i = 0; i < max_page; i++ )
+            amd_iommu_map_page(d, i, i, IOMMUF_readable|IOMMUF_writable);
+    }
+
+    amd_iommu_setup_dom0_devices(d);
 }
 
 static void amd_iommu_disable_domain_device(
@@ -433,6 +432,7 @@ static int amd_iommu_group_id(u8 bus, u8
 
 const struct iommu_ops amd_iommu_ops = {
     .init = amd_iommu_domain_init,
+    .dom0_init = amd_iommu_dom0_init,
     .add_device = amd_iommu_add_device,
     .remove_device = amd_iommu_remove_device,
     .assign_device  = amd_iommu_assign_device,
diff -r 007ec1eea255 -r 7ab7cdbb7a3f xen/drivers/passthrough/iommu.c
--- a/xen/drivers/passthrough/iommu.c   Wed Jul 21 09:08:45 2010 +0100
+++ b/xen/drivers/passthrough/iommu.c   Wed Jul 21 09:10:27 2010 +0100
@@ -18,6 +18,7 @@
 #include <asm/hvm/iommu.h>
 #include <xen/paging.h>
 #include <xen/guest_access.h>
+#include <xen/softirq.h>
 
 static void parse_iommu_param(char *s);
 static int iommu_populate_page_table(struct domain *d);
@@ -30,8 +31,8 @@ static int iommu_populate_page_table(str
  *   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 +40,7 @@ custom_param("iommu", parse_iommu_param)
 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 +66,6 @@ static void __init parse_iommu_param(cha
             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 +78,18 @@ static void __init parse_iommu_param(cha
             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)
-{
-    struct hvm_iommu *hd = domain_hvm_iommu(domain);
+int iommu_domain_init(struct domain *d)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
 
     spin_lock_init(&hd->mapping_lock);
     INIT_LIST_HEAD(&hd->g2m_ioport_list);
@@ -95,7 +99,36 @@ int iommu_domain_init(struct domain *dom
         return 0;
 
     hd->platform_ops = iommu_get_ops();
-    return hd->platform_ops->init(domain);
+    return hd->platform_ops->init(d);
+}
+
+void iommu_dom0_init(struct domain *d)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+    if ( !iommu_enabled )
+        return;
+
+    d->need_iommu = !!iommu_dom0_strict;
+    if ( need_iommu(d) )
+    {
+        struct page_info *page;
+        unsigned int i = 0;
+        page_list_for_each ( page, &d->page_list )
+        {
+            unsigned long mfn = page_to_mfn(page);
+            unsigned int mapping = IOMMUF_readable;
+            if ( ((page->u.inuse.type_info & PGT_count_mask) == 0) ||
+                 ((page->u.inuse.type_info & PGT_type_mask)
+                  == PGT_writable_page) )
+                mapping |= IOMMUF_writable;
+            hd->platform_ops->map_page(d, mfn, mfn, mapping);
+            if ( !(i++ & 0xfffff) )
+                process_pending_softirqs();
+        }
+    }
+
+    return hd->platform_ops->dom0_init(d);
 }
 
 int iommu_add_device(struct pci_dev *pdev)
@@ -276,6 +309,9 @@ int iommu_setup(void)
 {
     int rc = -ENODEV;
 
+    if ( iommu_dom0_strict )
+        iommu_passthrough = 0;
+
     if ( iommu_enabled )
     {
         rc = iommu_hardware_setup();
@@ -290,8 +326,15 @@ int 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;
 }
 
diff -r 007ec1eea255 -r 7ab7cdbb7a3f xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Wed Jul 21 09:08:45 2010 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c       Wed Jul 21 09:10:27 2010 +0100
@@ -1170,29 +1170,33 @@ static int intel_iommu_domain_init(struc
 static int intel_iommu_domain_init(struct domain *d)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+    hd->agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
+
+    return 0;
+}
+
+static void intel_iommu_dom0_init(struct domain *d)
+{
     struct iommu *iommu;
     struct acpi_drhd_unit *drhd;
 
-    hd->agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
-
-    if ( d->domain_id == 0 )
+    if ( !iommu_passthrough && !need_iommu(d) )
     {
         /* Set up 1:1 page table for dom0 */
         iommu_set_dom0_mapping(d);
-
-        setup_dom0_devices(d);
-        setup_dom0_rmrr(d);
-
-        iommu_flush_all();
-
-        for_each_drhd_unit ( drhd )
-        {
-            iommu = drhd->iommu;
-            iommu_enable_translation(iommu);
-        }
-    }
-
-    return 0;
+    }
+
+    setup_dom0_devices(d);
+    setup_dom0_rmrr(d);
+
+    iommu_flush_all();
+
+    for_each_drhd_unit ( drhd )
+    {
+        iommu = drhd->iommu;
+        iommu_enable_translation(iommu);
+    }
 }
 
 static int domain_context_mapping_one(
@@ -2155,6 +2159,7 @@ static void vtd_resume(void)
 
 const struct iommu_ops intel_iommu_ops = {
     .init = intel_iommu_domain_init,
+    .dom0_init = intel_iommu_dom0_init,
     .add_device = intel_iommu_add_device,
     .remove_device = intel_iommu_remove_device,
     .assign_device  = intel_iommu_assign_device,
diff -r 007ec1eea255 -r 7ab7cdbb7a3f xen/include/xen/iommu.h
--- a/xen/include/xen/iommu.h   Wed Jul 21 09:08:45 2010 +0100
+++ b/xen/include/xen/iommu.h   Wed Jul 21 09:10:27 2010 +0100
@@ -64,6 +64,7 @@ int iommu_add_device(struct pci_dev *pde
 int iommu_add_device(struct pci_dev *pdev);
 int iommu_remove_device(struct pci_dev *pdev);
 int iommu_domain_init(struct domain *d);
+void iommu_dom0_init(struct domain *d);
 void iommu_domain_destroy(struct domain *d);
 int device_assigned(u8 bus, u8 devfn);
 int assign_device(struct domain *d, u8 bus, u8 devfn);
@@ -108,6 +109,7 @@ void free_hvm_irq_dpci(struct hvm_irq_dp
 
 struct iommu_ops {
     int (*init)(struct domain *d);
+    void (*dom0_init)(struct domain *d);
     int (*add_device)(struct pci_dev *pdev);
     int (*remove_device)(struct pci_dev *pdev);
     int (*assign_device)(struct domain *d, u8 bus, u8 devfn);

_______________________________________________
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®.