diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 08d6d238e3..a461816345 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1699,6 +1699,88 @@ static int __init make_vpl011_uart_node(struct kernel_info *kinfo)
 }
 #endif
 
+/*
+ * Scan device tree properties for passthrough specific information.
+ * Returns -ENOENT when no passthrough properties are found
+ *         < 0 on error
+ *         0 on success
+ */
+static int __init handle_passthrough_prop(struct kernel_info *kinfo,
+                                          const struct fdt_property *prop,
+                                          const char *name,
+                                          uint32_t address_cells, uint32_t size_cells)
+{
+    const __be32 *cell;
+    unsigned int i, len;
+    struct dt_device_node *node;
+    int res;
+
+    /* xen,reg specifies where to map the MMIO region */
+    if ( dt_prop_cmp("xen,reg", name) == 0 )
+    {
+        paddr_t mstart, size, gstart;
+        cell = (const __be32 *)prop->data;
+        len = fdt32_to_cpu(prop->len) /
+            ((address_cells * 2 + size_cells) * sizeof(uint32_t));
+
+        for ( i = 0; i < len; i++ )
+        {
+            device_tree_get_reg(&cell, address_cells, size_cells,
+                    &mstart, &size);
+            gstart = dt_next_cell(address_cells, &cell);
+
+            if ( gstart & ~PAGE_MASK || mstart & ~PAGE_MASK || size & ~PAGE_MASK )
+            {
+                printk(XENLOG_ERR
+                       "DomU passthrough config has not page aligned addresses/sizes\n");
+                return -EINVAL;
+            }
+
+            res = map_regions_p2mt(kinfo->d,
+                                   gaddr_to_gfn(gstart),
+                                   PFN_DOWN(size),
+                                   maddr_to_mfn(mstart),
+                                   p2m_mmio_direct_dev);
+            if ( res < 0 )
+            {
+                printk(XENLOG_ERR
+                       "Failed to map %"PRIpaddr" to the guest at%"PRIpaddr"\n",
+                       mstart, gstart);
+                return -EFAULT;
+            }
+        }
+
+        return 0;
+    }
+    /*
+     * xen,path specifies the corresponding node in the host DT.
+     * Both interrupt mappings and IOMMU settings are based on it,
+     * as they are done based on the corresponding host DT node.
+     */
+    else if ( dt_prop_cmp("xen,path", name) == 0 )
+    {
+        node = dt_find_node_by_path(prop->data);
+        if ( node == NULL )
+        {
+            printk(XENLOG_ERR "Couldn't find node %s in host_dt!\n",
+                   (char *)prop->data);
+            return -EINVAL;
+        }
+
+        res = iommu_assign_dt_device(kinfo->d, node);
+        if ( res < 0 )
+            return res;
+
+        res = handle_device_interrupts(kinfo->d, node, true);
+        if ( res < 0 )
+            return res;
+
+        return 0;
+    }
+
+    return -ENOENT;
+}
+
 static int __init handle_prop_pfdt(struct kernel_info *kinfo,
                                    const void *pfdt, int nodeoff,
                                    uint32_t address_cells, uint32_t size_cells,
@@ -1707,6 +1789,7 @@ static int __init handle_prop_pfdt(struct kernel_info *kinfo,
     void *fdt = kinfo->fdt;
     int propoff, nameoff, res;
     const struct fdt_property *prop;
+    const char *name;
 
     for ( propoff = fdt_first_property_offset(pfdt, nodeoff);
           propoff >= 0;
@@ -1715,11 +1798,23 @@ static int __init handle_prop_pfdt(struct kernel_info *kinfo,
         if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) )
             return -FDT_ERR_INTERNAL;
 
+        res = 0;
         nameoff = fdt32_to_cpu(prop->nameoff);
-        res = fdt_property(fdt, fdt_string(pfdt, nameoff),
-                           prop->data, fdt32_to_cpu(prop->len));
-        if ( res )
+        name = fdt_string(pfdt, nameoff);
+
+        if ( scan_passthrough_prop )
+            res = handle_passthrough_prop(kinfo, prop, name,
+                                          address_cells, size_cells);
+        if ( res < 0 && res != -ENOENT )
             return res;
+
+        /* copy all other properties */
+        if ( !scan_passthrough_prop || res == -ENOENT )
+        {
+            res = fdt_property(fdt, name, prop->data, fdt32_to_cpu(prop->len));
+            if ( res )
+                return res;
+        }
     }
 
     /* FDT_ERR_NOTFOUND => There is no more properties for this node */
@@ -2277,6 +2372,9 @@ void __init create_domUs(void)
             panic("Missing property 'cpus' for domain %s\n",
                   dt_node_name(node));
 
+        if ( dt_find_compatible_node(node, NULL, "multiboot,device-tree") )
+            d_cfg.flags |= XEN_DOMCTL_CDF_iommu;
+
         d = domain_create(++max_init_domid, &d_cfg, false);
         if ( IS_ERR(d) )
             panic("Error creating domain %s\n", dt_node_name(node));
