diff --git a/xen/arch/arm/acpi/iort.c b/xen/arch/arm/acpi/iort.c
index 01914cb..d506adb 100644
--- a/xen/arch/arm/acpi/iort.c
+++ b/xen/arch/arm/acpi/iort.c
@@ -240,3 +240,175 @@ int estimate_iort_size(size_t *iort_size)
 err:
     return -EINVAL;
 }
+
+void write_itsgroup_nodes (struct acpi_table_iort *hwdom_iort,
+        struct acpi_table_iort *fw_iort,
+        uint64_t *ofstmap, unsigned int *pos)
+{
+    int i;
+    struct acpi_iort_node *node = NULL;
+    /* Iterate over all its groups in firmware IORT table
+     * and copy them in hwdom iort table.
+     */
+
+    /* First Node */
+    node = (struct acpi_iort_node *)((u8*)fw_iort + fw_iort->node_offset);
+    for ( i = 0; i < fw_iort->node_count; i++ )
+    {
+        if ( node->type == ACPI_IORT_NODE_ITS_GROUP )
+        {
+            u32 l,u;
+            /* Copy ITS group node into dom0 IORT Table */
+            ACPI_MEMCPY((u8*)hwdom_iort + *pos, node, node->length);
+
+            /* keep the new and old offsets, this would resolve smmu idarray's
+             * output ref offsets to the new offsets in hwdom iort table */
+            l = (uint32_t)((u8*)node - (u8*)fw_iort);
+            u = *pos ;
+            *ofstmap = ((uint64_t)(u) << 32)| l;
+
+            hwdom_iort->node_count++;
+            *pos += node->length;
+            ofstmap++;
+        }
+        node = (struct acpi_iort_node *)((u8*)node + node->length);
+    }
+}
+
+unsigned int write_single_pcirc_node(u8 *hwdom_iort, unsigned int pos,
+        struct acpi_iort_node *node,
+        struct list_head *new_idmap_list)
+{
+    unsigned int sz;
+    struct acpi_iort_node *local;
+    struct pcirc_idmap *pidmap;
+    local = (struct acpi_iort_node *)(hwdom_iort + pos);
+
+    /* write the pci_rc node */
+    sz = sizeof(struct acpi_iort_node) -1 +
+    /* -1 as acpi_iort_node has an extra char */
+        sizeof (struct acpi_iort_root_complex) ;
+    ACPI_MEMCPY(hwdom_iort + pos, node, sz);
+
+    pos += sz;
+    local->mapping_offset = sz;
+    local->mapping_count = 0;
+    local->length = sz;
+
+    list_for_each_entry(pidmap, new_idmap_list, entry)
+    {
+        ACPI_MEMCPY(hwdom_iort + pos, &pidmap->idmap,
+                sizeof(struct acpi_iort_id_mapping));
+        pos += sizeof(struct acpi_iort_id_mapping);
+        local->mapping_count++;
+        local->length += sizeof(struct acpi_iort_id_mapping);
+    }
+
+    return pos;
+}
+
+int write_pcirc_nodes(struct acpi_table_iort *hwdom_iort,
+        struct acpi_table_iort *fw_iort,
+        uint64_t  *its_ofstmap, unsigned int *pos)
+{
+    int i, j, ret;
+    struct acpi_iort_node *node = NULL;
+
+    /* Iterate over all PCI_Nodes */
+    /* First Node */
+    node = (struct acpi_iort_node *)((u8*)fw_iort + fw_iort->node_offset);
+    for ( i = 0; i < fw_iort->node_count; i++ )
+    {
+        if ( node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX )
+        {
+            struct pcirc_idmap *pidmap;
+            struct list_head new_idmap_list;
+            INIT_LIST_HEAD(&new_idmap_list);
+
+            /* hide smmu nodes and update new_idmap_list with output
+             * refrence of pci idarray as its group
+             */
+            ret = scan_idarray((u8*)fw_iort, node, &new_idmap_list, 0, NULL);
+            if ( ret ) {
+                printk("%s: scan_idarry Failed \r\n", __func__);
+                goto end;
+            }
+
+            /* fixup its_group offsets as per new iort table */
+            list_for_each_entry(pidmap, &new_idmap_list, entry)
+            {
+                /* search output reference offset in its_ofmap
+                 * and replace with new offset
+                 */
+                for (j =0; j < fw_iort->node_count; j++)
+                {
+                    if( !its_ofstmap[j] )
+                        break;
+
+                    if(pidmap->idmap.output_reference
+                            == (its_ofstmap[j] & 0xffffffff))
+                    {
+                        pidmap->idmap.output_reference = its_ofstmap[j] >> 32;
+                        break;
+                    }
+
+                }
+            }
+
+            *pos = write_single_pcirc_node((u8*)hwdom_iort, *pos, node,
+                    &new_idmap_list);
+            hwdom_iort->node_count++;
+
+            /* free new_idmap_list */
+            list_for_each_entry(pidmap, &new_idmap_list, entry)
+                xfree(pidmap);
+        }
+        /* Next Node */
+        node = (struct acpi_iort_node *)((u8*)node + node->length);
+    }
+    return 0;
+end:
+    return -EINVAL;
+}
+
+/*
+ *   Prepares IORT table for hardware domain, removing all the smmu nodes.
+ *  IORT table for hardware domain will have the following structure.
+ *  [IORT Header]
+ *  [ITS Group Nodes]
+ *  [PCI RC Node -N]
+ */
+int prepare_iort(struct acpi_table_iort *fw_iort,
+        struct acpi_table_iort *hwdom_iort,
+        unsigned int *iort_size)
+{
+    unsigned int pos; /* offset into local iort table */
+    uint64_t *its_ofstmap;
+
+    pos = sizeof(struct acpi_table_iort);
+
+    its_ofstmap = xzalloc_array(uint64_t, fw_iort->node_count);
+    if (!its_ofstmap)
+        goto end;
+
+    /* Copy FW iort header, node_count and node_offset updated later */
+    ACPI_MEMCPY(hwdom_iort, fw_iort, sizeof(struct acpi_table_iort));
+    hwdom_iort->node_offset = pos;
+    hwdom_iort->node_count = 0;
+
+    write_itsgroup_nodes(hwdom_iort, fw_iort, its_ofstmap, &pos);
+
+    if( write_pcirc_nodes(hwdom_iort, fw_iort, its_ofstmap, &pos) )
+    {
+        printk("Error in write_pcirc_nodes \r\n");
+        goto end;
+    }
+
+    hwdom_iort->header.length = pos;
+
+    xfree(its_ofstmap);
+    *iort_size = pos;
+    return 0;
+end:
+    return -EINVAL;
+}
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 0328926..0fcc206 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1653,6 +1653,9 @@ static int acpi_create_xsdt(struct domain *d, struct membank tbl_add[])
                            ACPI_SIG_MADT, tbl_add[TBL_MADT].start);
     xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start;
 
+    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
+                           ACPI_SIG_IORT, tbl_add[TBL_IORT].start);
+
     xsdt->header.length = table_size;
     checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, xsdt), table_size);
     xsdt->header.checksum -= checksum;
@@ -1701,6 +1704,37 @@ static int acpi_create_stao(struct domain *d, struct membank tbl_add[])
     return 0;
 }
 
+static int acpi_create_iort(struct domain *d, struct membank tbl_add[])
+{
+    struct acpi_table_iort *fw_table;
+    struct acpi_table_iort *hwdom_table;
+    acpi_status status;
+    u32 size;
+
+    status = acpi_get_table(ACPI_SIG_IORT, 0,
+                            (struct acpi_table_header **)&fw_table);
+    if ( ACPI_FAILURE(status) )
+    {
+        printk("Failed to get IORT table\n");
+        return -EINVAL;
+    }
+
+    tbl_add[TBL_IORT].start = d->arch.efi_acpi_gpa
+                              + acpi_get_table_offset(tbl_add, TBL_IORT);
+    hwdom_table = d->arch.efi_acpi_table
+                              + acpi_get_table_offset(tbl_add, TBL_IORT);
+
+    if ( prepare_iort(fw_table, hwdom_table, &size) )
+    {
+        printk("Failed to write IORT table\n");
+        return -EINVAL;
+    }
+    tbl_add[TBL_IORT].size = size;
+
+    return 0;
+}
+
+
 static int acpi_create_madt(struct domain *d, struct membank tbl_add[])
 {
     struct acpi_table_header *table = NULL;
@@ -1895,6 +1929,10 @@ static int prepare_acpi(struct domain *d, struct kernel_info *kinfo)
     if ( rc != 0 )
         return rc;
 
+    rc = acpi_create_iort(d, tbl_add);
+    if ( rc != 0 )
+        return rc;
+
     rc = acpi_create_xsdt(d, tbl_add);
     if ( rc != 0 )
         return rc;
diff --git a/xen/include/asm-arm/acpi.h b/xen/include/asm-arm/acpi.h
index 9f954d3..1cc0167 100644
--- a/xen/include/asm-arm/acpi.h
+++ b/xen/include/asm-arm/acpi.h
@@ -36,6 +36,7 @@ typedef enum {
     TBL_FADT,
     TBL_MADT,
     TBL_STAO,
+    TBL_IORT,
     TBL_XSDT,
     TBL_RSDP,
     TBL_EFIT,
diff --git a/xen/include/asm-arm/iort.h b/xen/include/asm-arm/iort.h
index 3b4cd7b..229fe7b 100644
--- a/xen/include/asm-arm/iort.h
+++ b/xen/include/asm-arm/iort.h
@@ -3,6 +3,9 @@
 
 int estimate_iort_size(size_t *iort_size);
 
+int prepare_iort(struct acpi_table_iort *fw_iort_table,
+                struct acpi_table_iort *hwdom_table, u32 *iort_size);
+
 #endif /* _XEN_ASM_IORT_H */
 /*
  * Local variables:
