]> xenbits.xensource.com Git - xen.git/commitdiff
iommu: Map dom0 initial allocation in 'dom0-strict' iommu mode.
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 16 Jul 2010 15:19:51 +0000 (16:19 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 16 Jul 2010 15:19:51 +0000 (16:19 +0100)
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/ia64/xen/domain.c
xen/arch/x86/domain_build.c
xen/drivers/passthrough/amd/pci_amd_iommu.c
xen/drivers/passthrough/iommu.c
xen/drivers/passthrough/vtd/iommu.c
xen/include/xen/iommu.h

index a15f9405612e12452831fbaf10bee7573d15a272..ab896ae772bfdea56b1f10de2384a6f13e7f88d3 100644 (file)
@@ -2298,6 +2298,8 @@ int __init construct_dom0(struct domain *d,
 
        physdev_init_dom0(d);
 
+       iommu_dom0_init(d);
+
        return 0;
 }
 
index 3995897e5bc15e0d3bf2c37882af744b68b16001..75479ea4ec7eb18010b854e067fc9de4db3f8abd 100644 (file)
@@ -1142,6 +1142,8 @@ int __init construct_dom0(
 
     BUG_ON(rc != 0);
 
+    iommu_dom0_init(dom0);
+
     return 0;
 }
 
index d0247d33059ef969930d64ad9f560544215ba61c..dd5bc774b1524d8493173bb28a1b388a46201abe 100644 (file)
@@ -212,9 +212,9 @@ static int get_paging_mode(unsigned long entries)
     return level;
 }
 
-static int amd_iommu_domain_init(struct domain *domain)
+static int amd_iommu_domain_init(struct domain *d)
 {
-    struct hvm_iommu *hd = domain_hvm_iommu(domain);
+    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 domain *domain)
         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; 
+    hd->domain_id = d->domain_id;
 
-        if ( !iommu_passthrough && !need_iommu(domain) )
-        {
-            /* 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);
-        }
+    return 0;
+}
 
-        amd_iommu_setup_dom0_devices(domain);
-    }
+static void amd_iommu_dom0_init(struct domain *d)
+{
+    unsigned long i; 
 
-    hd->domain_id = domain->domain_id;
+    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);
+    }
 
-    return 0;
+    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 devfn)
 
 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,
index e755d6d59f518008135622d8e5b35a2146a5b902..c9c1835005135e256bb3674da8045c6de5817dad 100644 (file)
@@ -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);
@@ -97,12 +98,39 @@ int iommu_domain_init(struct domain *d)
     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(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)
 {
     struct hvm_iommu *hd;
index 1ed8f1f71b4b356f636e7b50a20df98c0e02e027..4cc90ac821cf9c895501ad625cde9368c78ae38e 100644 (file)
@@ -1171,30 +1171,33 @@ void __init iommu_free(struct acpi_drhd_unit *drhd)
 static int intel_iommu_domain_init(struct domain *d)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
-    struct iommu *iommu;
-    struct acpi_drhd_unit *drhd;
 
     hd->agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
 
-    if ( d->domain_id == 0 )
+    return 0;
+}
+
+static void intel_iommu_dom0_init(struct domain *d)
+{
+    struct iommu *iommu;
+    struct acpi_drhd_unit *drhd;
+
+    if ( !iommu_passthrough && !need_iommu(d) )
     {
         /* Set up 1:1 page table for dom0 */
-        if ( !need_iommu(d) )
-            iommu_set_dom0_mapping(d);
+        iommu_set_dom0_mapping(d);
+    }
 
-        setup_dom0_devices(d);
-        setup_dom0_rmrr(d);
+    setup_dom0_devices(d);
+    setup_dom0_rmrr(d);
 
-        iommu_flush_all();
+    iommu_flush_all();
 
-        for_each_drhd_unit ( drhd )
-        {
-            iommu = drhd->iommu;
-            iommu_enable_translation(iommu);
-        }
+    for_each_drhd_unit ( drhd )
+    {
+        iommu = drhd->iommu;
+        iommu_enable_translation(iommu);
     }
-
-    return 0;
 }
 
 static int domain_context_mapping_one(
@@ -2161,6 +2164,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,
index 98ead331a510474483a98931d99d4f837aa95bbc..a5ab59dddbeaa315d53f2eb02282eccd53a41766 100644 (file)
@@ -64,6 +64,7 @@ int intremap_enabled(void);
 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);
@@ -109,6 +110,7 @@ bool_t pt_irq_need_timer(uint32_t flags);
 
 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);