Skip to contentSkip to conversation

acpi: arm: Add IORT Support

PATCH Superseded [email protected] 2 participants 16 messages Mar 12, 2018 – Mar 13, 2018

lore
Share & tools
lore
#0 lore raw

cover acpi: arm: Add IORT Support

From: Manish Jaggi <[email protected]>

This patch aims to add the support of IORT in Xen. Below is the list of major components which this patchset provides.
a. Add support for parsing the IORT
b. Provides API to populate/query requesterid - streamID mappings and
reuqesterid - deviceid mappings
c. The requesterid - deviceid mappings is used to create the IORT for
hardware domain (which hides smmu nodes from IORT)
d. iort.c fwnode.h fwspec code is imported from linux and modified.

Changes since RFC
- Added more documentation
- Moved code to arch/arm/acpi/ folder
- Lot of fixes for review comments

This patch works with [1] but few modifiations were made
(a) path of acpi_iort.h has changed so fixed to asm/acpi/acpi_iort.h
(b) Macro #define alloc_io_pgtable_ops(f, c, o) in Patch 5 of [1] results in -ENOMEM and need to be fixed.

-[1] https://lists.xenproject.org/archives/html/xen-devel/2018-02/msg00713.html

Manish Jaggi (13):
acpi: arm: API: Populate/query rid-devid rid-sid map.
acpi: arm: query estimated size of hardware domain's IORT.
acpi: arm: Code to generate Hardware Domains IORT
acpi: arm: Copy fwnode / iommu_fwspec code from Linux 4.14
acpi: arm: Import acpi_iort.h verbatim from linux 4.14
acpi: arm: Update acpi_iort.h with xen specific changes
arm: Adding ACPI_IORT in arm Kconfig
asm: arm: pci: Fix the #include label in asm-arm/pci.h
asm: arm: to_pci_dev
asm: arm: add dev_is_pci
asm: arm: add pci_domain_nr
acpi: arm: Provide support for iort iommu configuration hooks
acpi: arm: Add code to parse IORT and prepare rid maps.

 xen/arch/arm/Kconfig                 |   4 +
 xen/arch/arm/acpi/Makefile           |   3 +
 xen/arch/arm/acpi/gen-iort.c         | 400 +++++++++++++++++++++++
 xen/arch/arm/acpi/iort.c             | 608 +++++++++++++++++++++++++++++++++++
 xen/arch/arm/acpi/ridmap.c           | 126 ++++++++
 xen/arch/arm/domain_build.c          |  51 ++-
 xen/drivers/passthrough/arm/iommu.c  |  85 +++++
 xen/drivers/passthrough/arm/smmu.c   |   3 +-
 xen/include/asm-arm/acpi.h           |   1 +
 xen/include/asm-arm/acpi/acpi_iort.h |  51 +++
 xen/include/asm-arm/acpi/gen-iort.h  |  44 +++
 xen/include/asm-arm/acpi/ridmap.h    | 112 +++++++
 xen/include/asm-arm/device.h         |  17 +-
 xen/include/asm-arm/fwnode.h         | 128 ++++++++
 xen/include/asm-arm/fwspec.h         |  38 +++
 xen/include/asm-arm/pci.h            |  12 +-
 xen/include/xen/pci.h                |   2 +
 17 files changed, 1675 insertions(+), 10 deletions(-)
 create mode 100644 xen/arch/arm/acpi/gen-iort.c
 create mode 100644 xen/arch/arm/acpi/iort.c
 create mode 100644 xen/arch/arm/acpi/ridmap.c
 create mode 100644 xen/include/asm-arm/acpi/acpi_iort.h
 create mode 100644 xen/include/asm-arm/acpi/gen-iort.h
 create mode 100644 xen/include/asm-arm/acpi/ridmap.h
 create mode 100644 xen/include/asm-arm/fwnode.h
 create mode 100644 xen/include/asm-arm/fwspec.h
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#1 lore raw

PATCH 1/13 acpi: arm: API: Populate/query rid-devid rid-sid map.

From: Manish Jaggi <[email protected]>

IORT has a hierarchical structure containing PCIRC nodes, IORT nodes and SMMU nodes. Each node has with it an array of ids and a mapping which maps a range of ids to another node's ids. PCIRC(requesterid)->SMMU(streamid)->ITS(devid) or PCIRC->ITS

IORT is parsed multiple times when streamid(sid) / deviceid(devid) is queried from requesterid (rid).

Xen needs to prepare IORT for hardware domain which might again require parsing. Thus it is prudent to parse IORT once and save mapping information into individual maps namely rid-sid rid-devid.

This patch provides API to add a new mapping and query sid/devid based on rid. Two lists are created rid-sid list, rid-devid list. rid-devid list forms the basis of hardware domains' IORT.

---
 xen/arch/arm/acpi/Makefile        |   1 +
 xen/arch/arm/acpi/ridmap.c        | 126 ++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/acpi/ridmap.h | 112 +++++++++++++++++++++++++++++++++
 3 files changed, 239 insertions(+)
xen/arch/arm/acpi/Makefile +1 -0
index 23963f8fa0..eb7e8ce4f7 100644
@@ -1,2 +1,3 @@
 obj-y += lib.o
 obj-y += boot.init.o
+obj-y += ridmap.o
xen/arch/arm/acpi/ridmap.c new file +126 -0

126 lines not on this page · raw message

xen/include/asm-arm/acpi/ridmap.h new file +112 -0

112 lines not on this page · raw message

Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#2 lore raw

PATCH 2/13 acpi: arm: query estimated size of hardware domain's IORT.

In reply to [email protected]

From: Manish Jaggi <[email protected]>

Code to query estimated IORT size for hardware domain. IORT for hardware domain is generated using the requesterid and deviceid map. Xen code requires the size to be predeterminded.

---
 xen/arch/arm/acpi/Makefile          |   1 +
 xen/arch/arm/acpi/gen-iort.c        | 101 ++++++++++++++++++++++++++++++++++++
 xen/arch/arm/domain_build.c         |  16 ++++--
 xen/include/asm-arm/acpi/gen-iort.h |  33 ++++++++++++
 4 files changed, 148 insertions(+), 3 deletions(-)
xen/arch/arm/acpi/Makefile +1 -0
index eb7e8ce4f7..073339603c 100644
@@ -1,3 +1,4 @@
 obj-y += lib.o
 obj-y += boot.init.o
 obj-y += ridmap.o
+obj-y += gen-iort.o
xen/arch/arm/acpi/gen-iort.c new file +101 -0

101 lines not on this page · raw message

xen/arch/arm/domain_build.c +13 -3
index 155c952349..33a46cab1e 100644
@@ -14,6 +14,7 @@
 #include <xen/acpi.h>
 #include <xen/warning.h>
 #include <acpi/actables.h>
+#include <asm/acpi/gen-iort.h>
 #include <asm/device.h>
 #include <asm/setup.h>
 #include <asm/platform.h>
@@ -1801,7 +1802,7 @@ static int acpi_create_fadt(struct domain *d, struct membank tbl_add[])
 
 static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo)
 {
-    size_t efi_size, acpi_size, madt_size;
+    size_t efi_size, acpi_size, table_size;
     u64 addr;
     struct acpi_table_rsdp *rsdp_tbl;
     struct acpi_table_header *table;
@@ -1811,8 +1812,8 @@ static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo)
     acpi_size = ROUNDUP(sizeof(struct acpi_table_fadt), 8);
     acpi_size += ROUNDUP(sizeof(struct acpi_table_stao), 8);
 
-    madt_size = gic_get_hwdom_madt_size(d);
-    acpi_size += ROUNDUP(madt_size, 8);
+    table_size = gic_get_hwdom_madt_size(d);
+    acpi_size += ROUNDUP(table_size, 8);
 
     addr = acpi_os_get_root_pointer();
     if ( !addr )
@@ -1842,6 +1843,15 @@ static int estimate_acpi_efi_size(struct domain *d, struct kernel_info *kinfo)
     acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
 
     acpi_size += ROUNDUP(sizeof(struct acpi_table_rsdp), 8);
+
+    if ( estimate_iort_size(&table_size) )
+    {
+        printk("Unable to get hwdom iort size\n");
+        return -EINVAL;
+    }
+
+    acpi_size += ROUNDUP(table_size, 8);
+
     d->arch.efi_acpi_len = PAGE_ALIGN(ROUNDUP(efi_size, 8)
                                       + ROUNDUP(acpi_size, 8));
 
xen/include/asm-arm/acpi/gen-iort.h new file +33 -0
new file mode 100644
index 0000000000..3b2af1e871
@@ -0,0 +1,33 @@
+/*
+ * xen/include/asm-arm/acpi/gen-iort.h
+ *
+ * Manish Jaggi <[email protected]>
+ * Copyright (c) 2018 Linaro.
+ *
+ * Ths program is free software; you can redistribute it and/or
+ * modify it under the terms and conditions of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ACPI_GEN_IORT_H
+#define _ACPI_GEN_IORT_H
+
+/*
+ * Returns the size of hardware domains IORT
+ */
+int estimate_iort_size(size_t *iort_size);
+
+#endif
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#3 lore raw

PATCH 3/13 acpi: arm: Code to generate Hardware Domains IORT

In reply to [email protected]

From: Manish Jaggi <[email protected]>

Structure of Hardware domain's (hwdom) IORT

hwdom's IORT will only have PCIRC nodes and ITS group nodes in the following order. SMMU nodes as they are hidden from hardware domain.

[IORT Header]
[ITS Group 1 ]
...
[ITS Group n ]
[PCIRC Node 1]
[PCIRC IDMAP entry 1]
...
[PCIRC IDMAP entry m]
...
[PCIRC Node p]
[PCIRC IDMAP entry 1]
...
[PCIRC IDMAP entry q]
...
*n,m,p are variable.

requesterid-deviceid mapping list (rid_devid_list) populated by parsing IORT is used to generate hwdom IORT.

As the rid_devid_list is populated from firmware IORT, IDMAP entry would have output references offsets based on firmware's IORT. It is required to fixup node offset of ITS Group Nodes in the PCIRC idmap (output_reference)

First write all the ITS group nodes in the hwdom's IORT. For this write_hwits_nodes is called, which parses the rid_devid_list and for each unique its_node in firmware IORT create a its_node in hwdom's IORT and also creates and entry in fwits_hwits_map.

fwits_hwits_map is a mapping between firmware IORT's its node and the node offset of the corresponding its_node stored in the hwdom's IORT.

This map can later be used to set output reference value in hwdom's pcirc node's idmap entries.

---
 xen/arch/arm/acpi/gen-iort.c        | 299 ++++++++++++++++++++++++++++++++++++
 xen/arch/arm/domain_build.c         |  35 +++++
 xen/include/asm-arm/acpi.h          |   1 +
 xen/include/asm-arm/acpi/gen-iort.h |  11 ++
 4 files changed, 346 insertions(+)
xen/arch/arm/acpi/gen-iort.c +299 -0
index 687c4f18ee..251a9771e3 100644
@@ -19,6 +19,305 @@
 
 #include <asm/acpi/ridmap.h>
 #include <xen/acpi.h>
+#include <acpi/actables.h>
+
+/*
+ * Structure of Hardware domain's (hwdom) IORT
+ * -----------------------------------
+ *
+ * hwdom's IORT will only have PCIRC nodes and ITS group nodes
+ * in the following order.
+ *
+ * [IORT Header]
+ * [ITS Group 1 ]
+ * ...
+ * [ITS Group N ]
+ * [PCIRC Node 1]
+ * [PCIRC IDMAP entry 1]
+ * ...
+ * [PCIRC IDMAP entry N]
+ * ...
+ * [PCIRC Node N]
+ *
+ * requesterid-deviceid mapping list (rid_devid_list) populated by parsing IORT
+ * is used to generate hwdom IORT.
+ *
+ * One of the challanges is to fixup node offset of ITS Group Nodes
+ * in the PCIRC idmap (output_reference)
+ *
+ * In rid_devid_map firmware IORT's ITS group node pointer in stored.
+ *
+ * We first write all the ITS group nodes in the hwdom's IORT. For this
+ * write_hwits_nodes is called, which parses the rid_devid_list and for
+ * each unique its_node in firmware IORT create a its_node in hwdom's IORT
+ * and also creates and entry in fwits_hwits_map.
+ *
+ * fwits_hwits_map is a mapping between firmware IORT's its node
+ * and the node offset of the corresponding its_node stored in the
+ * hwdom's IORT.
+ *
+ * This map can be later used to set output reference value in hwdom's
+ * pcirc node's idmap entries.
+ *
+ */
+
+/*
+ * Stores the mapping between firmware tables its group node
+ * to the offset of the equivalent its node to be stored in
+ * hwdom's IORT.
+ */
+struct fwits_hwits_map
+{
+    struct acpi_iort_node *fwits_node;
+    unsigned int hwitsnode_offset;
+    struct list_head entry;
+};
+
+LIST_HEAD(fwits_hwits_list);
+
+/*
+ * is_uniq_fwits_node
+ *
+ * returns 1 - if fwits_node is not already in the its_map_list
+ *         0 - if it is present already
+ *
+ * fwits_node - ITS Node pointer in Firmware IORT
+ * offset     - offset of the equivalent its node to be stored in
+ *              hwdom's IORT
+ */
+static int is_uniq_fwits_node(struct acpi_iort_node *fwits_node,
+                              unsigned int offset)
+{
+    struct fwits_hwits_map *map;
+
+    list_for_each_entry(map, &fwits_hwits_list, entry)
+    {
+        if ( map->fwits_node == fwits_node )
+            return 0;
+    }
+
+    map = xzalloc(struct fwits_hwits_map);
+    if ( !map )
+        return -ENOMEM;
+
+    map->fwits_node = fwits_node;
+    map->hwitsnode_offset = offset;
+    list_add_tail(&map->entry, &fwits_hwits_list);
+
+    return 1;
+}
+
+/*
+ * Returns the offset of corresponding its node to fwits_node
+ * written in hwdom's IORT.
+ *
+ * This function would be used when write hwdoms pcirc nodes' idmap
+ * entries.
+ */
+static
+unsigned int hwitsnode_offset_from_map(struct acpi_iort_node *fwits_node)
+{
+    struct fwits_hwits_map *map;
+
+    list_for_each_entry(map, &fwits_hwits_list, entry)
+    {
+        if ( map->fwits_node == fwits_node )
+            return map->hwitsnode_offset;
+    }
+
+    return 0;
+}
+
+static void write_hwits_nodes(u8 *iort, unsigned int *offset,
+                              unsigned int *num_nodes)
+{
+    struct rid_devid_map *rmap;
+    unsigned int of = *offset;
+    int n = 0;
+
+    /*
+     * rid_devid_list is iterated to get unique its group nodes
+     * Each unique ITS group node is written in hardware domains IORT
+     * by using some values from the firmware ITS group node.
+     */
+    list_for_each_entry(rmap, &rid_devid_list, entry)
+    {
+        struct acpi_iort_node *node;
+        struct acpi_iort_its_group *grp;
+        struct acpi_iort_its_group *fw_grp;
+
+        /* save its_node_offset_map in a list uniquely */
+        if ( is_uniq_fwits_node(rmap->its_node, of) == 1 )
+        {
+            node = (struct acpi_iort_node *) &iort[of];
+            grp = (struct acpi_iort_its_group *)(&node->node_data);
+
+            node->type = ACPI_IORT_NODE_ITS_GROUP;
+            node->length = sizeof(struct acpi_iort_node) +
+                           sizeof(struct acpi_iort_its_group) -
+                           sizeof(node->node_data);
+
+            node->revision = rmap->its_node->revision;
+            node->reserved = 0;
+            node->mapping_count = 0;
+            node->mapping_offset= 0;
+
+            fw_grp = (struct acpi_iort_its_group *)(&rmap->its_node->node_data);
+
+            /* Copy its_count and identifiers from firmware iort's its_node */
+            grp->its_count = fw_grp->its_count;
+            grp->identifiers[0] = fw_grp->identifiers[0];
+
+            of += node->length;
+            n++;
+        }
+    }
+    *offset = of;
+    *num_nodes = n;
+}
+
+static void write_hwpcirc_nodes(u8 *iort, unsigned int *pos,
+                                unsigned int *num_nodes)
+{
+    struct acpi_iort_node *opcirc_node, *pcirc_node;
+    struct acpi_iort_node *hwdom_pcirc_node = NULL;
+    struct rid_devid_map *rmap;
+    struct acpi_iort_id_mapping *idmap;
+    int num_idmap = 0, n = 0;
+    unsigned int old_pos = *pos;
+
+    opcirc_node = NULL;
+    /* Iterate rid_map_devid list */
+    list_for_each_entry(rmap, &rid_devid_list, entry)
+    {
+        struct acpi_iort_root_complex *rc;
+        struct acpi_iort_root_complex *rc_fw;
+        int add_node = 0;
+
+        pcirc_node = rmap->pcirc_node;
+
+        if ( opcirc_node == NULL ) /* First entry */
+        {
+            add_node = 1;
+        }
+        else if ( opcirc_node != pcirc_node ) /* another pci_rc_node found*/
+        {
+            /* All the idmaps of a pcirc are written, now update node info*/
+            hwdom_pcirc_node->length = num_idmap *
+                                       sizeof(struct acpi_iort_id_mapping) +
+                                       sizeof(struct acpi_iort_node) +
+                                       sizeof(struct acpi_iort_root_complex) -
+                                       sizeof(pcirc_node->node_data);
+
+            hwdom_pcirc_node->mapping_count = num_idmap;
+            hwdom_pcirc_node->mapping_offset = sizeof(struct acpi_iort_node) +
+                                               sizeof(struct acpi_iort_root_complex) -
+                                               sizeof(pcirc_node->node_data);
+            old_pos += hwdom_pcirc_node->length;
+            add_node = 1;
+        }
+
+        if ( add_node ) /* create the pcirc node */
+        {
+            opcirc_node = pcirc_node;
+            hwdom_pcirc_node = (struct acpi_iort_node *)&iort[old_pos];
+            hwdom_pcirc_node->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
+            hwdom_pcirc_node->mapping_offset = sizeof(struct acpi_iort_node) +
+                                               sizeof(struct acpi_iort_root_complex) -
+                                               sizeof(hwdom_pcirc_node->node_data);
+
+            rc = (struct acpi_iort_root_complex *)
+                  &hwdom_pcirc_node->node_data;
+
+            rc_fw = (struct acpi_iort_root_complex *)
+                     &pcirc_node->node_data;
+
+            rc->pci_segment_number = rc_fw->pci_segment_number;
+            rc->ats_attribute = rc_fw->ats_attribute;
+            rc->memory_properties = rc_fw->memory_properties;
+
+            idmap = ACPI_ADD_PTR(struct acpi_iort_id_mapping,
+                                 hwdom_pcirc_node,
+                                 hwdom_pcirc_node->mapping_offset);
+            n++;
+            num_idmap = 0;
+        }
+
+        idmap->input_base = rmap->idmap.input_base;
+        idmap->id_count = rmap->idmap.id_count;
+        idmap->output_base = rmap->idmap.output_base;
+        idmap->output_reference = hwitsnode_offset_from_map(rmap->its_node);
+        BUG_ON(!idmap->output_reference);
+
+        idmap->flags = 0;
+        idmap++;
+        num_idmap++;
+    }
+
+    if ( hwdom_pcirc_node ) /* if no further PCIRC nodes found */
+    {
+        /* All the idmaps of a pcirc are written, now update node info*/
+        hwdom_pcirc_node->length = num_idmap *
+                                   sizeof(struct acpi_iort_id_mapping) +
+                                   sizeof(struct acpi_iort_node) +
+                                   sizeof(struct acpi_iort_root_complex) -1;
+
+        hwdom_pcirc_node->mapping_count = num_idmap;
+        old_pos += hwdom_pcirc_node->length;
+    }
+
+    *pos = old_pos;
+    *num_nodes = n;
+}
+
+bool is_iort_available(void)
+{
+    struct acpi_table_iort *iort;
+
+    if ( acpi_get_table(ACPI_SIG_IORT, 0,
+         (struct acpi_table_header **)&iort) )
+        return 0;
+
+    return 1;
+}
+
+int prepare_hwdom_iort(struct acpi_table_iort *hwdom_iort, unsigned int *iort_size)
+{
+    struct acpi_table_iort *fw_iort;
+    unsigned int num_nodes = 0;
+    unsigned int pos;
+
+    pos = sizeof(struct acpi_table_iort);
+
+    if ( acpi_get_table(ACPI_SIG_IORT, 0,
+         (struct acpi_table_header **)&fw_iort) )
+    {
+        printk("Failed to get IORT table\n");
+        return -ENODEV;
+    }
+
+    /* Write IORT header */
+    ACPI_MEMCPY(hwdom_iort, fw_iort, sizeof(struct acpi_table_iort));
+    hwdom_iort->node_offset = pos;
+    hwdom_iort->node_count = 0;
+
+    /* Write its group nodes */
+    write_hwits_nodes((u8*)hwdom_iort, &pos, &num_nodes);
+    hwdom_iort->node_count = num_nodes;
+
+    /* Write pcirc_nodes */
+    write_hwpcirc_nodes((u8*)hwdom_iort, &pos, &num_nodes);
+
+    /* Update IORT Size in IORT header */
+    hwdom_iort->node_count += num_nodes;
+    hwdom_iort->header.length = pos;
+    hwdom_iort->header.checksum =  acpi_tb_checksum(
+                                    ACPI_CAST_PTR(u8, hwdom_iort),
+                                    pos);
+    *iort_size = hwdom_iort->header.length;
+
+    return 0;
+}
 
 /*
  * Size of hardware domains' IORT is calculated based on the number of
xen/arch/arm/domain_build.c +35 -0
index 33a46cab1e..6c6dfad38c 100644
@@ -1656,6 +1656,8 @@ static int acpi_create_xsdt(struct domain *d, struct membank tbl_add[])
                            ACPI_SIG_FADT, tbl_add[TBL_FADT].start);
     acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
                            ACPI_SIG_MADT, tbl_add[TBL_MADT].start);
+    acpi_xsdt_modify_entry(xsdt->table_offset_entry, entry_count,
+                           ACPI_SIG_IORT, tbl_add[TBL_IORT].start);
     xsdt->table_offset_entry[entry_count] = tbl_add[TBL_STAO].start;
 
     xsdt->header.length = table_size;
@@ -1706,6 +1708,35 @@ 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 *hwdom_table;
+    unsigned int size = 0;
+
+    if ( is_iort_available() )
+    {
+        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_hwdom_iort(hwdom_table, &size) )
+        {
+           printk("Failed to write IORT table\n");
+           return -EINVAL;
+        }
+
+        tbl_add[TBL_IORT].size = size;
+    }
+    else
+    {
+        tbl_add[TBL_IORT].start = 0;
+        tbl_add[TBL_IORT].size = 0;
+    }
+
+    return 0;
+}
+
 static int acpi_create_madt(struct domain *d, struct membank tbl_add[])
 {
     struct acpi_table_header *table = NULL;
@@ -1901,6 +1932,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;
xen/include/asm-arm/acpi.h +1 -0
index c183b6bb6e..f8b5254621 100644
@@ -36,6 +36,7 @@ typedef enum {
     TBL_FADT,
     TBL_MADT,
     TBL_STAO,
+    TBL_IORT,
     TBL_XSDT,
     TBL_RSDP,
     TBL_EFIT,
xen/include/asm-arm/acpi/gen-iort.h +11 -0
index 3b2af1e871..52974f6052 100644
@@ -22,6 +22,17 @@
  */ 
 int estimate_iort_size(size_t *iort_size);
 
+/*
+ * Checks if IORT is present in ACPI tables.
+ */
+bool is_iort_available(void);
+
+/*
+ * Prepares IORT in buffer hwdom_iort and updates iort_size
+ */
+int prepare_hwdom_iort(struct acpi_table_iort *hwdom_iort,
+                       unsigned int *iort_size);
+
 #endif
 /*
  * Local variables:
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#4 lore raw

PATCH 4/13 acpi: arm: Copy fwnode / iommu_fwspec code from Linux 4.14

In reply to [email protected]

From: Manish Jaggi <[email protected]>

fwnode is firmware device node object handle type definition. This can be used either for device tree node or ACPI table node. However in the context of this patchset it is used mainly for ACPI nodes.

iommu_fwspec defines set of opeations associated with fwnode.

This patch does not directly imports the code files from linux, rahter copies only the relavant parts of code required for Xen.

---
 xen/drivers/passthrough/arm/iommu.c |  85 ++++++++++++++++++++++++
 xen/include/asm-arm/device.h        |   1 +
 xen/include/asm-arm/fwnode.h        | 128 ++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/fwspec.h        |  38 +++++++++++
 4 files changed, 252 insertions(+)
xen/drivers/passthrough/arm/iommu.c +85 -0
index 95b1abb972..6e3960e4af 100644
@@ -19,6 +19,8 @@
 #include <xen/iommu.h>
 #include <xen/device_tree.h>
 #include <asm/device.h>
+#include <asm/fwnode.h>
+#include <asm/fwspec.h>
 
 static const struct iommu_ops *iommu_ops;
 
@@ -73,3 +75,86 @@ int arch_iommu_populate_page_table(struct domain *d)
     /* The IOMMU shares the p2m with the CPU */
     return -ENOSYS;
 }
+
+/**
+ * fwnode_handle_put - Drop reference to a device node
+ * @fwnode: Pointer to the device node to drop the reference to.
+ *
+ * To be used when terminating device_for_each_child_node() iteration with
+ * break / return to prevent stale device node references being left behind
+ */
+void fwnode_handle_put(struct fwnode_handle *fwnode)
+{
+    fwnode_call_void_op(fwnode, put);
+}
+
+const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode)
+{
+    return iommu_get_ops();
+}
+
+int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
+                      const struct iommu_ops *ops)
+{
+    struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+
+    if ( fwspec )
+       return ops == fwspec->ops ? 0 : -EINVAL;
+
+    fwspec = xzalloc_bytes(sizeof(*fwspec));
+    if ( !fwspec )
+        return -ENOMEM;
+#if 0
+       of_node_get(to_of_node(iommu_fwnode)); /* TODO */
+#endif
+    fwspec->iommu_fwnode = iommu_fwnode;
+    fwspec->ops = ops;
+    dev->iommu_fwspec = fwspec;
+
+    return 0;
+}
+
+void iommu_fwspec_free(struct device *dev)
+{
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+
+    if ( fwspec )
+    {
+        fwnode_handle_put(fwspec->iommu_fwnode);
+        xfree(fwspec);
+        dev->iommu_fwspec = NULL;
+    }
+}
+
+int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
+{
+    struct iommu_fwspec *fwspec_n;
+    struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+    size_t size, size_n;
+    int i;
+
+    if ( !fwspec )
+        return -EINVAL;
+
+    size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids]);
+    size_n = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + num_ids]);
+    if ( size_n > size )
+    {
+        fwspec_n = _xzalloc(size_n, sizeof(void*));
+        if ( !fwspec_n )
+             return -ENOMEM;
+
+        memcpy(fwspec_n, fwspec, size);
+        xfree(fwspec);
+        fwspec = fwspec_n;
+    }
+
+    for ( i = 0; i < num_ids; i++ )
+        fwspec->ids[fwspec->num_ids + i] = ids[i];
+
+    fwspec->num_ids += num_ids;
+    dev->iommu_fwspec = fwspec;
+
+    return 0;
+}
+
xen/include/asm-arm/device.h +1 -0
index 6734ae8efd..7f2d8d367e 100644
@@ -20,6 +20,7 @@ struct device
     struct dt_device_node *of_node; /* Used by drivers imported from Linux */
 #endif
     struct dev_archdata archdata;
+    struct iommu_fwspec *iommu_fwspec;
 };
 
 typedef struct device device_t;
xen/include/asm-arm/fwnode.h new file +128 -0

128 lines not on this page · raw message

xen/include/asm-arm/fwspec.h new file +38 -0
new file mode 100644
index 0000000000..e67d2bb678
@@ -0,0 +1,38 @@
+/*
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Author: Rafael J. Wysocki <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Xen Modifications: Manish Jaggi
+ */
+
+#ifndef _ASM_FWSPEC_H
+#define _ASM_FWSPEC_H
+
+/**
+ * struct iommu_fwspec - per-device IOMMU instance data
+ * @ops: ops for this device's IOMMU
+ * @iommu_fwnode: firmware handle for this device's IOMMU
+ * @iommu_priv: IOMMU driver private data for this device
+ * @num_ids: number of associated device IDs
+ * @ids: IDs which this device may present to the IOMMU
+ */
+struct iommu_fwspec {
+        const struct iommu_ops  *ops;
+        struct fwnode_handle    *iommu_fwnode;
+        void                    *iommu_priv;
+        unsigned int            num_ids;
+        u32                     ids[1];
+};
+
+int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
+                      const struct iommu_ops *ops);
+void iommu_fwspec_free(struct device *dev);
+int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode);
+
+#endif
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#5 lore raw

PATCH 5/13 acpi: arm: Import acpi_iort.h verbatim from linux 4.14

In reply to [email protected]

From: Manish Jaggi <[email protected]>

Import acpi_iort.h verbatim from linux 4.14

---
 xen/include/asm-arm/acpi/acpi_iort.h | 57 ++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)
xen/include/asm-arm/acpi/acpi_iort.h new file +57 -0
new file mode 100644
index 0000000000..8d3f0bf803
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016, Semihalf
+ *	Author: Tomasz Nowicki <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef __ACPI_IORT_H__
+#define __ACPI_IORT_H__
+
+#include <linux/acpi.h>
+#include <linux/fwnode.h>
+#include <linux/irqdomain.h>
+
+#define IORT_IRQ_MASK(irq)		(irq & 0xffffffffULL)
+#define IORT_IRQ_TRIGGER_MASK(irq)	((irq >> 32) & 0xffffffffULL)
+
+int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
+void iort_deregister_domain_token(int trans_id);
+struct fwnode_handle *iort_find_domain_token(int trans_id);
+#ifdef CONFIG_ACPI_IORT
+void acpi_iort_init(void);
+u32 iort_msi_map_rid(struct device *dev, u32 req_id);
+struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+void acpi_configure_pmsi_domain(struct device *dev);
+int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
+/* IOMMU interface */
+void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
+const struct iommu_ops *iort_iommu_configure(struct device *dev);
+#else
+static inline void acpi_iort_init(void) { }
+static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
+{ return req_id; }
+static inline struct irq_domain *iort_get_device_domain(struct device *dev,
+							u32 req_id)
+{ return NULL; }
+static inline void acpi_configure_pmsi_domain(struct device *dev) { }
+/* IOMMU interface */
+static inline void iort_dma_setup(struct device *dev, u64 *dma_addr,
+				  u64 *size) { }
+static inline
+const struct iommu_ops *iort_iommu_configure(struct device *dev)
+{ return NULL; }
+#endif
+
+#endif /* __ACPI_IORT_H__ */
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#6 lore raw

PATCH 6/13 acpi: arm: Update acpi_iort.h with xen specific changes

In reply to [email protected]

From: Manish Jaggi <[email protected]>

Remove the parts of acpi_iort.h which are not required for Xen.

---
 xen/include/asm-arm/acpi/acpi_iort.h | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)
xen/include/asm-arm/acpi/acpi_iort.h +2 -8
index 8d3f0bf803..dcffb23773 100644
@@ -19,18 +19,13 @@
 #ifndef __ACPI_IORT_H__
 #define __ACPI_IORT_H__
 
-#include <linux/acpi.h>
-#include <linux/fwnode.h>
-#include <linux/irqdomain.h>
+#include <asm/device.h>
+#include <xen/acpi.h>
 
 #define IORT_IRQ_MASK(irq)		(irq & 0xffffffffULL)
 #define IORT_IRQ_TRIGGER_MASK(irq)	((irq >> 32) & 0xffffffffULL)
 
-int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node);
-void iort_deregister_domain_token(int trans_id);
-struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_ACPI_IORT
-void acpi_iort_init(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
 void acpi_configure_pmsi_domain(struct device *dev);
@@ -39,7 +34,6 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
 const struct iommu_ops *iort_iommu_configure(struct device *dev);
 #else
-static inline void acpi_iort_init(void) { }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
 static inline struct irq_domain *iort_get_device_domain(struct device *dev,
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#7 lore raw

PATCH 7/13 arm: Adding ACPI_IORT in arm Kconfig

In reply to [email protected]

From: Manish Jaggi <[email protected]>

---
 xen/arch/arm/Kconfig | 4 ++++
 1 file changed, 4 insertions(+)
xen/arch/arm/Kconfig +4 -0
index 2782ee6589..d3fbcbcc6f 100644
@@ -59,6 +59,10 @@ config SBSA_VUART_CONSOLE
 
 endmenu
 
+config ACPI_IORT
+        depends on ACPI
+        def_bool y
+
 menu "ARM errata workaround via the alternative framework"
 	depends on HAS_ALTERNATIVE
 
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#8 lore raw

PATCH 8/13 asm: arm: pci: Fix the #include label in asm-arm/pci.h

In reply to [email protected]

From: Manish Jaggi <[email protected]>

asm-arm/pci.h has an incorrect #ifndef label.
Fixing it to ARM

---
 xen/include/asm-arm/pci.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
xen/include/asm-arm/pci.h +3 -3
index de13359f65..3145ed505c 100644
@@ -1,7 +1,7 @@
-#ifndef __X86_PCI_H__
-#define __X86_PCI_H__
+#ifndef __ASM_ARM_PCI_H__
+#define __ASM_ARM_PCI_H__
 
 struct arch_pci_dev {
 };
 
-#endif /* __X86_PCI_H__ */
+#endif /* __ASM_ARM_PCI_H__ */
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#9 lore raw

PATCH 9/13 asm: arm: to_pci_dev

In reply to [email protected]

From: Manish Jaggi <[email protected]>

to_pci_dev for ARM was todo till now.
Provide definition for this macro.

---
 xen/drivers/passthrough/arm/smmu.c | 3 ++-
 xen/include/asm-arm/pci.h          | 6 ++++++
 2 files changed, 8 insertions(+), 1 deletion(-)
xen/drivers/passthrough/arm/smmu.c +2 -1
index 74c09b0991..81629a695c 100644
@@ -46,10 +46,12 @@
 #include <xen/rbtree.h>
 #include <xen/sched.h>
 #include <xen/sizes.h>
+#include <xen/pci.h>
 #include <asm/atomic.h>
 #include <asm/device.h>
 #include <asm/io.h>
 #include <asm/platform.h>
+#include <asm/pci.h>
 
 /* Xen: The below defines are redefined within the file. Undef it */
 #undef SCTLR_AFE
@@ -181,7 +183,6 @@ static void __iomem *devm_ioremap_resource(struct device *dev,
  * Xen: PCI functions
  * TODO: It should be implemented when PCI will be supported
  */
-#define to_pci_dev(dev)	(NULL)
 static inline int pci_for_each_dma_alias(struct pci_dev *pdev,
 					 int (*fn) (struct pci_dev *pdev,
 						    u16 alias, void *data),
xen/include/asm-arm/pci.h +6 -0
index 3145ed505c..d3de409927 100644
@@ -2,6 +2,12 @@
 #define __ASM_ARM_PCI_H__
 
 struct arch_pci_dev {
+    struct device dev;
 };
 
+#define to_pci_dev(d) container_of( \
+                                   container_of(d, struct arch_pci_dev, dev), \
+                                   struct pci_dev,\
+                                   arch\
+                                  )
 #endif /* __ASM_ARM_PCI_H__ */
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#10 lore raw

PATCH 10/13 asm: arm: add dev_is_pci

In reply to [email protected]

From: Manish Jaggi <[email protected]>

dev_is_pci for ARM was todo till now.
Provide definition for this macro.

---
 xen/include/asm-arm/device.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
xen/include/asm-arm/device.h +2 -2
index 7f2d8d367e..b75d79b793 100644
@@ -6,6 +6,7 @@
 enum device_type
 {
     DEV_DT,
+    DEV_PCI,
 };
 
 struct dev_archdata {
@@ -27,8 +28,7 @@ typedef struct device device_t;
 
 #include <xen/device_tree.h>
 
-/* TODO: Correctly implement dev_is_pci when PCI is supported on ARM */
-#define dev_is_pci(dev) ((void)(dev), 0)
+#define dev_is_pci(dev) ((dev->type == DEV_PCI))
 #define dev_is_dt(dev)  ((dev->type == DEV_DT)
 
 enum device_class
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#11 lore raw

PATCH 11/13 asm: arm: add pci_domain_nr

In reply to [email protected]

From: Manish Jaggi <[email protected]>

Provide definition for this macro.

---
 xen/include/xen/pci.h | 2 ++
 1 file changed, 2 insertions(+)
xen/include/xen/pci.h +2 -0
index dd5ec43a70..ee1d4dbf93 100644
@@ -114,6 +114,8 @@ struct pci_dev {
     u64 vf_rlen[6];
 };
 
+#define pci_domain_nr(pdev) pdev->seg
+
 #define for_each_pdev(domain, pdev) \
     list_for_each_entry(pdev, &(domain->arch.pdev_list), domain_list)
 
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#12 lore raw

PATCH 12/13 acpi: arm: Provide support for iort iommu configuration hooks

In reply to [email protected]

From: Manish Jaggi <[email protected]>

This patch copies the basic code from linux (iort.c) required to parse IORT and
hooks for iommu configuration and initializes smmu device.

Provides a top level initcall acpi_iort_init which would call parse_iort (next patch) to parse and prepare the rid-devid and rid-sid maps.

This patch is dependent on next patch. The code is cleanly split into two patches

---
 xen/arch/arm/acpi/Makefile   |   1 +
 xen/arch/arm/acpi/iort.c     | 401 +++++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/device.h |  12 +-
 3 files changed, 413 insertions(+), 1 deletion(-)
xen/arch/arm/acpi/Makefile +1 -0
index 073339603c..a596559205 100644
@@ -2,3 +2,4 @@ obj-y += lib.o
 obj-y += boot.init.o
 obj-y += ridmap.o
 obj-y += gen-iort.o
+obj-y += iort.o
xen/arch/arm/acpi/iort.c new file +401 -0

401 lines not on this page · raw message

xen/include/asm-arm/device.h +11 -1
index b75d79b793..19a76f59d6 100644
@@ -7,6 +7,7 @@ enum device_type
 {
     DEV_DT,
     DEV_PCI,
+    DEV_ACPI,
 };
 
 struct dev_archdata {
@@ -18,9 +19,18 @@ struct device
 {
     enum device_type type;
 #ifdef CONFIG_HAS_DEVICE_TREE
-    struct dt_device_node *of_node; /* Used by drivers imported from Linux */
+    /*
+     * TODO: of_node is redundant by addition of fwnode.
+     * Will be cleaned in future, kept here for compatability
+     * with smmuv2 driver
+     */
+    struct dt_device_node *of_node;
+#endif
+#ifdef CONFIG_ACPI
+    void *acpi_node;
 #endif
     struct dev_archdata archdata;
+    struct fwnode_handle *fwnode;
     struct iommu_fwspec *iommu_fwspec;
 };
 
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#13 lore raw

PATCH 13/13 Add code to parse IORT and prepare rid maps.

In reply to [email protected]

From: Manish Jaggi <[email protected]>

This patch adds code to parse the pci_rc, idmaps and smmu nodes to
- prepare idmaps (rid-sid rid-devid)

While resolving the ipmap from pcirc->smmu->its some fixup is required this is done by fixup_rid_devid_map.

---
 xen/arch/arm/acpi/iort.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 207 insertions(+)
xen/arch/arm/acpi/iort.c +207 -0
index 4238611ef7..e7a7c027e5 100644
@@ -379,6 +379,212 @@ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
     return fwnode;
 }
 
+static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
+{
+    return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr);
+}
+
+static inline bool is_acpi_static_node(const struct fwnode_handle *fwnode)
+{
+    return !IS_ERR_OR_NULL(fwnode) &&
+        fwnode->ops == &acpi_static_fwnode_ops;
+}
+
+static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode)
+{
+    if (WARN_ON(!is_acpi_static_node(fwnode)))
+        return;
+
+    xfree(fwnode);
+}
+
+int fixup_rid_devid_map(struct acpi_iort_node *inode,
+                           struct acpi_iort_id_mapping *pci_idmap,
+                           struct acpi_iort_node *smmu_node)
+{
+
+    unsigned int p_input_base, p_output_base, p_id_count;
+    unsigned int s_input_base, s_output_base, s_id_count;
+    unsigned int delta, i;
+    int ret = 0;
+    struct acpi_iort_id_mapping *smmu_idmap = NULL;
+    struct acpi_iort_node *its_node;
+    struct acpi_table_iort *iort;
+
+    iort = (struct acpi_table_iort*) iort_table;
+
+    p_input_base = pci_idmap->input_base;
+    p_output_base = pci_idmap->output_base;
+    p_id_count = pci_idmap->id_count;
+
+    smmu_idmap = (struct acpi_iort_id_mapping*) ((u8*) smmu_node +
+                  smmu_node->mapping_offset);
+
+    for ( i = 0; i < smmu_node->mapping_count; i++, smmu_idmap++ )
+    {
+        s_input_base = smmu_idmap->input_base;
+        s_output_base = smmu_idmap->output_base;
+        s_id_count = smmu_idmap->id_count;
+        its_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+                        smmu_idmap->output_reference);
+
+        if (s_input_base <= p_output_base)
+    {
+            int count;
+            if (s_input_base + s_id_count < p_output_base)
+                continue;
+
+            delta = p_output_base - s_input_base;
+            count = s_input_base + s_id_count <= p_output_base +
+                p_id_count ? s_id_count - delta : p_id_count;
+
+            ret = add_rid_devid_map (inode, its_node,
+                            p_input_base,
+                            s_output_base + delta,
+                            count);
+            if (ret)
+                return ret;
+        }
+    else
+    {
+            int count;
+            if ( p_output_base + p_id_count < s_input_base )
+                continue;
+
+            delta = s_input_base - p_output_base;
+            count = s_input_base + s_id_count < p_output_base +
+                p_id_count ? s_id_count : p_id_count - delta;
+
+            ret = add_rid_devid_map (inode, its_node,
+                            p_input_base + delta,
+                            s_output_base, count);
+
+            if ( ret )
+                return ret;
+        }
+    }
+
+    return ret;
+}
+
+void parse_pcirc_node(struct acpi_iort_node *iort_node)
+{
+    int j, ret;
+    struct acpi_iort_id_mapping *idmap;
+    struct acpi_iort_node *onode;
+    struct acpi_table_iort *iort;
+
+    iort = (struct acpi_table_iort*) iort_table;
+    idmap = ACPI_ADD_PTR(struct acpi_iort_id_mapping, iort_node,
+                 iort_node->mapping_offset);
+
+    /* iterate over idmap */
+    for ( j = 0; j < iort_node->mapping_count; j++ )
+    {
+        struct acpi_iort_node *its_node;
+        struct acpi_iort_node *smmu_node;
+        onode = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+                     idmap->output_reference);
+
+        switch (onode->type)
+        {
+        case ACPI_IORT_NODE_ITS_GROUP:
+
+            its_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+                                    idmap->output_reference);
+
+            ret = add_rid_devid_map(iort_node, its_node,
+                                    idmap->input_base,
+                                    idmap->output_base,
+                                    idmap->id_count);
+            if ( ret )
+            {
+                printk("%s: add_rid_devid_map"
+                       "failed with ret=%d \r\n",
+                         __func__, ret);
+                break;
+            }
+        break;
+
+        case ACPI_IORT_NODE_SMMU:
+        case ACPI_IORT_NODE_SMMU_V3:
+
+            smmu_node = ACPI_ADD_PTR(struct acpi_iort_node,
+                                     iort_table,
+                                     idmap->output_reference);
+
+            ret = add_rid_sid_map(iort_node,
+                                  smmu_node,
+                                  idmap->input_base,
+                                  idmap->output_base,
+                                  idmap->id_count);
+            if ( ret )
+            {
+                printk("%s: add_rid_sid_map"
+                       "failed with ret=%d \r\n",
+                        __func__, ret);
+                break;
+            }
+
+            ret = fixup_rid_devid_map(iort_node, idmap, onode);
+            if ( ret )
+            {
+                printk("%s: fixup_rid_devid_map"
+                       "failed with ret=%d \r\n",
+                       __func__, ret);
+                break;
+            }
+            break;
+        }
+        idmap++;
+    }
+}
+
+void parse_smmu_node(struct acpi_iort_node *iort_node)
+{
+    int ret;
+    struct fwnode_handle *fwnode;
+    fwnode = acpi_alloc_fwnode_static();
+    if ( !fwnode )
+        return;
+
+    iort_set_fwnode(iort_node, fwnode);
+    ret = iort_add_smmu_platform_device(iort_node);
+    if ( ret )
+        acpi_free_fwnode_static(fwnode);
+}
+
+void parse_iort(void)
+{
+    struct acpi_iort_node *iort_node, *iort_end;
+    struct acpi_table_iort *iort;
+    int i;
+
+    iort = (struct acpi_table_iort*) iort_table;
+    iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+            iort->node_offset);
+    iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+            iort->header.length);
+
+    for (i = 0; i < iort->node_count; i++)
+    {
+        if ( iort_node >= iort_end )
+        {
+            printk("iort node pointer overflows, bad table\n");
+            return;
+        }
+
+        if ( iort_node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX )
+            parse_pcirc_node(iort_node);
+        else if ( (iort_node->type == ACPI_IORT_NODE_SMMU ||
+                 iort_node->type == ACPI_IORT_NODE_SMMU_V3) )
+            parse_smmu_node(iort_node);
+
+        iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+                iort_node->length);
+    }
+}
+
 int __init acpi_iort_init(void)
 {
     acpi_status status;
@@ -396,6 +602,7 @@ int __init acpi_iort_init(void)
         return -1;
     }
 
+    parse_iort();
     return 0;
 }
 __initcall(acpi_iort_init);
Signature · 7 lines
2.14.1


_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#14 lore raw
In reply to [email protected]

Hi,

I got duplicated e-mails on my inbox for this series. Each version have a different series and all in the same threading.

I have no idea which emails to answer properly. So please do a proper resend of this series and this time with my correct e-mail address.

Cheers,

Quoted 65 lines · On 12/03/18 07:49, [email protected] wrote:

From: Manish Jaggi <[email protected]>

This patch aims to add the support of IORT in Xen. Below is the list of major components which this patchset provides.
a. Add support for parsing the IORT
b. Provides API to populate/query requesterid - streamID mappings and
reuqesterid - deviceid mappings
c. The requesterid - deviceid mappings is used to create the IORT for
hardware domain (which hides smmu nodes from IORT)
d. iort.c fwnode.h fwspec code is imported from linux and modified.

Changes since RFC
- Added more documentation
- Moved code to arch/arm/acpi/ folder
- Lot of fixes for review comments

This patch works with [1] but few modifiations were made
(a) path of acpi_iort.h has changed so fixed to asm/acpi/acpi_iort.h
(b) Macro #define alloc_io_pgtable_ops(f, c, o) in Patch 5 of [1] results in -ENOMEM and need to be fixed.

-[1] https://lists.xenproject.org/archives/html/xen-devel/2018-02/msg00713.html

Manish Jaggi (13):
acpi: arm: API: Populate/query rid-devid rid-sid map.
acpi: arm: query estimated size of hardware domain's IORT.
acpi: arm: Code to generate Hardware Domains IORT
acpi: arm: Copy fwnode / iommu_fwspec code from Linux 4.14
acpi: arm: Import acpi_iort.h verbatim from linux 4.14
acpi: arm: Update acpi_iort.h with xen specific changes
arm: Adding ACPI_IORT in arm Kconfig
asm: arm: pci: Fix the #include label in asm-arm/pci.h
asm: arm: to_pci_dev
asm: arm: add dev_is_pci
asm: arm: add pci_domain_nr
acpi: arm: Provide support for iort iommu configuration hooks
acpi: arm: Add code to parse IORT and prepare rid maps.

  xen/arch/arm/Kconfig                 |   4 +
  xen/arch/arm/acpi/Makefile           |   3 +
  xen/arch/arm/acpi/gen-iort.c         | 400 +++++++++++++++++++++++
  xen/arch/arm/acpi/iort.c             | 608 +++++++++++++++++++++++++++++++++++
  xen/arch/arm/acpi/ridmap.c           | 126 ++++++++
  xen/arch/arm/domain_build.c          |  51 ++-
  xen/drivers/passthrough/arm/iommu.c  |  85 +++++
  xen/drivers/passthrough/arm/smmu.c   |   3 +-
  xen/include/asm-arm/acpi.h           |   1 +
  xen/include/asm-arm/acpi/acpi_iort.h |  51 +++
  xen/include/asm-arm/acpi/gen-iort.h  |  44 +++
  xen/include/asm-arm/acpi/ridmap.h    | 112 +++++++
  xen/include/asm-arm/device.h         |  17 +-
  xen/include/asm-arm/fwnode.h         | 128 ++++++++
  xen/include/asm-arm/fwspec.h         |  38 +++
  xen/include/asm-arm/pci.h            |  12 +-
  xen/include/xen/pci.h                |   2 +
  17 files changed, 1675 insertions(+), 10 deletions(-)

create mode 100644 xen/arch/arm/acpi/gen-iort.c create mode 100644 xen/arch/arm/acpi/iort.c create mode 100644 xen/arch/arm/acpi/ridmap.c create mode 100644 xen/include/asm-arm/acpi/acpi_iort.h create mode 100644 xen/include/asm-arm/acpi/gen-iort.h create mode 100644 xen/include/asm-arm/acpi/ridmap.h create mode 100644 xen/include/asm-arm/fwnode.h create mode 100644 xen/include/asm-arm/fwspec.h

Signature · 6 lines
Julien Grall

_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
#15 lore raw
Quoted 6 lines · Julien Grall

Hi,

I got duplicated e-mails on my inbox for this series. Each version have a different series and all in the same threading.

I have no idea which emails to answer properly. So please do a proper resend of this series and this time with my correct e-mail address.

sent to Julien Grall <[email protected]> this time.

Quoted 71 lines

Cheers,

Quoted 67 lines · On 12/03/18 07:49, [email protected] wrote:

From: Manish Jaggi <[email protected]>

This patch aims to add the support of IORT in Xen. Below is the list of major components which this patchset provides.
a. Add support for parsing the IORT
b. Provides API to populate/query requesterid - streamID mappings and reuqesterid - deviceid mappings
c. The requesterid - deviceid mappings is used to create the IORT for hardware domain (which hides smmu nodes from IORT)
d. iort.c fwnode.h fwspec code is imported from linux and modified.

Changes since RFC
- Added more documentation
- Moved code to arch/arm/acpi/ folder
- Lot of fixes for review comments

This patch works with [1] but few modifiations were made
(a) path of acpi_iort.h has changed so fixed to asm/acpi/acpi_iort.h
(b) Macro #define alloc_io_pgtable_ops(f, c, o) in Patch 5 of [1] results in -ENOMEM and need to be fixed.

-[1]
https://lists.xenproject.org/archives/html/xen-devel/2018-02/msg00713.html

Manish Jaggi (13):
   acpi: arm: API: Populate/query rid-devid rid-sid map.
   acpi: arm: query estimated size of hardware domain's IORT.
   acpi: arm: Code to generate Hardware Domains IORT
   acpi: arm: Copy fwnode / iommu_fwspec code from Linux 4.14
   acpi: arm: Import acpi_iort.h verbatim from linux 4.14
   acpi: arm: Update acpi_iort.h with xen specific changes
   arm: Adding ACPI_IORT in arm Kconfig
   asm: arm: pci: Fix the #include label in asm-arm/pci.h
   asm: arm: to_pci_dev
   asm: arm: add dev_is_pci
   asm: arm: add pci_domain_nr
   acpi: arm: Provide support for iort iommu configuration hooks
   acpi: arm: Add code to parse IORT and prepare rid maps.

  xen/arch/arm/Kconfig                 |   4 + xen/arch/arm/acpi/Makefile           |   3 + xen/arch/arm/acpi/gen-iort.c         | 400 +++++++++++++++++++++++ xen/arch/arm/acpi/iort.c             | 608
+++++++++++++++++++++++++++++++++++
  xen/arch/arm/acpi/ridmap.c           | 126 ++++++++ xen/arch/arm/domain_build.c          |  51 ++- xen/drivers/passthrough/arm/iommu.c  |  85 +++++ xen/drivers/passthrough/arm/smmu.c   |   3 +- xen/include/asm-arm/acpi.h           |   1 + xen/include/asm-arm/acpi/acpi_iort.h |  51 +++ xen/include/asm-arm/acpi/gen-iort.h  |  44 +++ xen/include/asm-arm/acpi/ridmap.h    | 112 +++++++

  xen/include/asm-arm/device.h         |  17 +-
  xen/include/asm-arm/fwnode.h         | 128 ++++++++
  xen/include/asm-arm/fwspec.h         |  38 +++
  xen/include/asm-arm/pci.h            |  12 +-
  xen/include/xen/pci.h                |   2 +
  17 files changed, 1675 insertions(+), 10 deletions(-)

  create mode 100644 xen/arch/arm/acpi/gen-iort.c create mode 100644 xen/arch/arm/acpi/iort.c create mode 100644 xen/arch/arm/acpi/ridmap.c create mode 100644 xen/include/asm-arm/acpi/acpi_iort.h create mode 100644 xen/include/asm-arm/acpi/gen-iort.h create mode 100644 xen/include/asm-arm/acpi/ridmap.h create mode 100644 xen/include/asm-arm/fwnode.h create mode 100644 xen/include/asm-arm/fwspec.h

_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel