Skip to contentSkip to conversation

acpi: arm: Add IORT Support

PATCH RESEND In review [email protected] 2 participants 23 messages Mar 13, 2018 – Mar 28, 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 RESEND 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

Re: [PATCH resend 01/13] acpi: arm: API: Populate/query rid-devid rid-sid map.

Hi Manish,

Quoted 10 lines · On 03/13/2018 03:20 PM, [email protected] wrote:

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).

Quoted 7 lines

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.

Thank you for updating the commit message. However, you stil don't give an idea often those function will get called and whether unsorted list will be fine.

Quoted 41 lines
---
  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 +19 -0
new file mode 100644
index 0000000000..daa137f625
@@ -0,0 +1,126 @@
+/*
+ * xen/drivers/acpi/arm/ridmap.c
+ *
+ * This file implements rid-sid rid-devid mapping API
+ *
+ * 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.
+ */
+
+#include <asm/acpi/ridmap.h>

xen/arch/arm/acpi/ridmap.c line 29

Quoted 10 lines
xen/arch/arm/acpi/ridmap.c new file +10 -0
+#include <xen/iommu.h>
+#include <xen/kernel.h>
+#include <xen/list.h>
+#include <xen/pci.h>
+
+LIST_HEAD(rid_sid_list);
+LIST_HEAD(rid_devid_list);
+
+int add_rid_sid_map(struct acpi_iort_node *pcirc_node,
+                    struct acpi_iort_node *smmu_node,

Is there any one that will modify pcirc_node and smmu_node afterwards? If not, then they should be const.

xen/arch/arm/acpi/ridmap.c line 31

Quoted 2 lines
xen/arch/arm/acpi/ridmap.c new file +2 -0
+                    uint32_t input_base, uint32_t output_base,
+                    uint32_t id_count)

I suggested to put __init in front of that function. But you dismissed it saying it might not be valid and you will add rationale. I don't see any rationale in that patch nor an answer to my question on the previous version.

Quoted 10 lines
xen/arch/arm/acpi/ridmap.c new file +10 -0
+{
+    struct rid_sid_map *rid_map;
+
+    rid_map = xzalloc(struct rid_sid_map);
+    if ( !rid_map )
+        return -ENOMEM;
+
+    rid_map->idmap.input_base = input_base;
+    rid_map->idmap.output_base = output_base;
+    rid_map->idmap.id_count = id_count;

xen/arch/arm/acpi/ridmap.c line 51

Quoted 10 lines
xen/arch/arm/acpi/ridmap.c new file +10 -0
+    rid_map->pcirc_node = pcirc_node;
+    rid_map->smmu_node = smmu_node;
+
+    list_add_tail(&rid_map->entry, &rid_sid_list);
+
+    return 0;
+}
+
+int add_rid_devid_map(struct acpi_iort_node *pcirc_node,
+                      struct acpi_iort_node *its_node,

Same here about const.

xen/arch/arm/acpi/ridmap.c line 53

Quoted 2 lines
xen/arch/arm/acpi/ridmap.c new file +2 -0
+                      uint32_t input_base, uint32_t output_base,
+                      uint32_t id_count)

Same here about __init.

Quoted 101 lines
xen/arch/arm/acpi/ridmap.c new file +73 -0
+{
+    struct rid_devid_map *rid_map;
+
+    rid_map = xzalloc(struct rid_devid_map);
+    if ( !rid_map )
+        return -ENOMEM;
+
+    rid_map->idmap.input_base = input_base;
+    rid_map->idmap.output_base = output_base;
+    rid_map->idmap.id_count = id_count;
+    rid_map->pcirc_node = pcirc_node;
+    rid_map->its_node = its_node;
+
+    list_add_tail(&rid_map->entry, &rid_devid_list);
+
+    return 0;
+}
+
+bool query_sid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+               uint32_t *sid, struct acpi_iort_node **smmu_node)
+{
+    struct rid_sid_map *rmap;
+
+    list_for_each_entry(rmap, &rid_sid_list, entry)
+    {
+        if ( rmap->pcirc_node == pcirc_node )
+        {
+            if ( (rid >= rmap->idmap.input_base) &&
+                 (rid < rmap->idmap.input_base + rmap->idmap.id_count) )
+            {
+                *sid = rid - rmap->idmap.input_base +
+                       rmap->idmap.output_base;
+                *smmu_node = rmap->smmu_node;
+
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+bool query_devid(struct acpi_iort_node *pcirc_node,
+                uint32_t rid, uint32_t *devid)
+{
+    struct rid_devid_map *rmap;
+
+    list_for_each_entry(rmap, &rid_devid_list, entry)
+    {
+        if ( rmap->pcirc_node == pcirc_node )
+        {
+            if ( (rid >= rmap->idmap.input_base) &&
+                 (rid < rmap->idmap.input_base + rmap->idmap.id_count) )
+            {
+                *devid = rid - rmap->idmap.input_base +
+                         rmap->idmap.output_base;
+
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
xen/include/asm-arm/acpi/ridmap.h new file +22 -0
new file mode 100644
index 0000000000..5d12d86c3a
@@ -0,0 +1,112 @@
+/*
+ * xen/include/acpi/ridmap.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 __ASM_ACPI_RIDMAP_H__
+#define __ASM_ACPI_RIDMAP_H__
+
+#include <xen/acpi.h>
+
+/*

xen/include/asm-arm/acpi/ridmap.h line 32

Quoted 10 lines
xen/include/asm-arm/acpi/ridmap.h new file +10 -0
+ * List holds requesterid (rid) - streamid (sid) mapping entries.
+ */
+extern struct list_head rid_sid_list;
+/*
+ * List holds requesterid (rid) - deviceid (devid) mapping entries.
+ */
+extern struct list_head rid_devid_list;
+
+/*
+ * structure to hold mapping between requresterid and streamid.

requesterid.

Quoted 26 lines
xen/include/asm-arm/acpi/ridmap.h new file +26 -0
+ * Note: output_reference and flags members of acpi_iort_id_mapping
+ * are not used. This is done to avoid creating a new structure for
+ * same purpose.
+ *
+ * smmu node pointer is stored in this structure because, in some places
+ * smmu_node along with streamid is required based on rid and pcirc_node.
+ */
+struct rid_sid_map
+{
+    struct acpi_iort_node *pcirc_node;
+    struct acpi_iort_node *smmu_node;
+    struct acpi_iort_id_mapping idmap;
+    struct list_head entry;
+};
+
+/*
+ * API to add a rid-sid mapping
+ * This method should be called while parsing each entry in idmap array
+ * under the pcirc node in IORT.
+ */
+int add_rid_sid_map(struct acpi_iort_node *pcirc_node,
+                    struct acpi_iort_node *smmu_node,
+                    uint32_t input_base, uint32_t output_base,
+                    uint32_t id_count);
+/*
+ * API to query sid and smmu_node based on pcirc_node and rid.

xen/include/asm-arm/acpi/ridmap.h line 68

Quoted 10 lines
xen/include/asm-arm/acpi/ridmap.h new file +10 -0
+ *
+ * Example of usage:
+ *  int iort_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
+ *  {
+ *     struct iort_pci_alias_info *info = data;
+ *   ...
+ *      if ( query_sid(info->node, alias, &streamid, &smmu_node) )
+ *          return iort_iommu_xlate(info->dev, smmu_node, streamid);
+ *   ...
+ *   }

I don't see the benefits of the example usage. If the function is difficult to use, then it much better to describe each argument.

xen/include/asm-arm/acpi/ridmap.h line 75

Quoted 7 lines
xen/include/asm-arm/acpi/ridmap.h new file +7 -0
+ *
+ */
+bool query_sid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+               uint32_t *sid, struct acpi_iort_node **smmu_node);
+
+/*
+ * structure to hold a mapping between requresterid and deviceid.

requesterid

xen/include/asm-arm/acpi/ridmap.h line 86

Quoted 11 lines
xen/include/asm-arm/acpi/ridmap.h new file +11 -0
+ * Note: output_reference and flags members of acpi_iort_id_mapping
+ * are not used. This is done to avoid creating a new structure for
+ * same purpose.
+ */
+struct rid_devid_map
+{
+    struct acpi_iort_node *pcirc_node;
+    struct acpi_iort_node *its_node;
+    struct acpi_iort_id_mapping idmap;
+    struct list_head entry;
+};

You could probably merge this structure and rid_sid_map. The only difference is smmu_node, so you could use an union for that.

xen/include/asm-arm/acpi/ridmap.h line 99

Quoted 13 lines
xen/include/asm-arm/acpi/ridmap.h new file +13 -0
+
+/*
+ * API to add a rid-devid mapping
+ * This method should be called while parsing each entry in idmap array
+ * under the pcirc node in IORT.
+ */
+int add_rid_devid_map(struct acpi_iort_node *pcirc_node,
+                      struct acpi_iort_node *its_node,
+                      uint32_t input_base, uint32_t output_base,
+                      uint32_t id_count);
+
+/*
+ * API to query devid based on pcirc_node and rid */

Comment coding style.

Quoted 4 lines
xen/include/asm-arm/acpi/ridmap.h new file +3 -0
+bool query_devid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+                 uint32_t *devid);
+

xen/include/asm-arm/acpi/ridmap.h line 112

Quoted 10 lines
xen/include/asm-arm/acpi/ridmap.h new file +10 -0
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

Cheers,

Signature · 6 lines
Julien Grall

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

Re: [PATCH resend 01/13] acpi: arm: API: Populate/query rid-devid rid-sid map.

Quoted 1 line · Julien Grall

Hi Manish,

Hi Julien,

Quoted 16 lines · On 03/13/2018 03:20 PM, [email protected] wrote:
Quoted 14 lines

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.

Quoted 5 lines
Quoted 3 lines

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.

Thank you for updating the commit message. However, you stil don't give an idea often those function will get called and whether unsorted list will be fine.

I have added that in code comments.

Quoted 57 lines
Quoted 44 lines

---
  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 +0 -0
index 23963f8fa0..eb7e8ce4f7 100644
@@ -1,2 +1,3 @@

  obj-y += lib.o
  obj-y += boot.init.o

xen/arch/arm/acpi/Makefile +1 -0
+obj-y += ridmap.o
xen/arch/arm/acpi/ridmap.c new file +19 -0
new file mode 100644
index 0000000000..daa137f625
@@ -0,0 +1,126 @@
+/*
+ * xen/drivers/acpi/arm/ridmap.c
+ *
+ * This file implements rid-sid rid-devid mapping API
+ *
+ * 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.
+ */
+
+#include <asm/acpi/ridmap.h>

xen/arch/arm/acpi/ridmap.c line 29

Quoted 10 lines
xen/arch/arm/acpi/ridmap.c new file +10 -0
+#include <xen/iommu.h>
+#include <xen/kernel.h>
+#include <xen/list.h>
+#include <xen/pci.h>
+
+LIST_HEAD(rid_sid_list);
+LIST_HEAD(rid_devid_list);
+
+int add_rid_sid_map(struct acpi_iort_node *pcirc_node,
+                    struct acpi_iort_node *smmu_node,

Is there any one that will modify pcirc_node and smmu_node afterwards? If not, then they should be const.

Quoted 5 lines

xen/arch/arm/acpi/ridmap.c line 31

Quoted 2 lines
xen/arch/arm/acpi/ridmap.c new file +2 -0
+                    uint32_t input_base, uint32_t output_base,
+                    uint32_t id_count)

I suggested to put __init in front of that function. But you dismissed it saying it might not be valid and you will add rationale. I don't see any rationale in that patch nor an answer to my question on the previous version.

Should a public API function be __init ?

Quoted 177 lines
Quoted 10 lines
xen/arch/arm/acpi/ridmap.c new file +10 -0
+{
+    struct rid_sid_map *rid_map;
+
+    rid_map = xzalloc(struct rid_sid_map);
+    if ( !rid_map )
+        return -ENOMEM;
+
+    rid_map->idmap.input_base = input_base;
+    rid_map->idmap.output_base = output_base;
+    rid_map->idmap.id_count = id_count;

xen/arch/arm/acpi/ridmap.c line 51

Quoted 10 lines
xen/arch/arm/acpi/ridmap.c new file +10 -0
+    rid_map->pcirc_node = pcirc_node;
+    rid_map->smmu_node = smmu_node;
+
+    list_add_tail(&rid_map->entry, &rid_sid_list);
+
+    return 0;
+}
+
+int add_rid_devid_map(struct acpi_iort_node *pcirc_node,
+                      struct acpi_iort_node *its_node,

Same here about const.

xen/arch/arm/acpi/ridmap.c line 53

Quoted 2 lines
xen/arch/arm/acpi/ridmap.c new file +2 -0
+                      uint32_t input_base, uint32_t output_base,
+                      uint32_t id_count)

Same here about __init.

Quoted 103 lines
xen/arch/arm/acpi/ridmap.c new file +29 -0
+{
+    struct rid_devid_map *rid_map;
+
+    rid_map = xzalloc(struct rid_devid_map);
+    if ( !rid_map )
+        return -ENOMEM;
+
+    rid_map->idmap.input_base = input_base;
+    rid_map->idmap.output_base = output_base;
+    rid_map->idmap.id_count = id_count;
+    rid_map->pcirc_node = pcirc_node;
+    rid_map->its_node = its_node;
+
+    list_add_tail(&rid_map->entry, &rid_devid_list);
+
+    return 0;
+}
+
+bool query_sid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+               uint32_t *sid, struct acpi_iort_node **smmu_node)
+{
+    struct rid_sid_map *rmap;
+
+    list_for_each_entry(rmap, &rid_sid_list, entry)
+    {
+        if ( rmap->pcirc_node == pcirc_node )
+        {
+            if ( (rid >= rmap->idmap.input_base) &&
+                 (rid < rmap->idmap.input_base + 

rmap->idmap.id_count) )
+            {
+                *sid = rid - rmap->idmap.input_base + +                       rmap->idmap.output_base; +                *smmu_node = rmap->smmu_node;

xen/arch/arm/acpi/ridmap.c new file +20 -0
+
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+bool query_devid(struct acpi_iort_node *pcirc_node,
+                uint32_t rid, uint32_t *devid)
+{
+    struct rid_devid_map *rmap;
+
+    list_for_each_entry(rmap, &rid_devid_list, entry)
+    {
+        if ( rmap->pcirc_node == pcirc_node )
+        {
+            if ( (rid >= rmap->idmap.input_base) &&
+                 (rid < rmap->idmap.input_base + 

rmap->idmap.id_count) )
+            {
+                *devid = rid - rmap->idmap.input_base + +                         rmap->idmap.output_base;

xen/arch/arm/acpi/ridmap.c new file +17 -0
+
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
xen/include/asm-arm/acpi/ridmap.h new file +22 -0
new file mode 100644
index 0000000000..5d12d86c3a
@@ -0,0 +1,112 @@
+/*
+ * xen/include/acpi/ridmap.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 __ASM_ACPI_RIDMAP_H__
+#define __ASM_ACPI_RIDMAP_H__
+
+#include <xen/acpi.h>
+
+/*

xen/include/asm-arm/acpi/ridmap.h line 32

Quoted 10 lines
xen/include/asm-arm/acpi/ridmap.h new file +10 -0
+ * List holds requesterid (rid) - streamid (sid) mapping entries.
+ */
+extern struct list_head rid_sid_list;
+/*
+ * List holds requesterid (rid) - deviceid (devid) mapping entries.
+ */
+extern struct list_head rid_devid_list;
+
+/*
+ * structure to hold mapping between requresterid and streamid.

requesterid.

Quoted 33 lines
xen/include/asm-arm/acpi/ridmap.h new file +5 -0
+ * Note: output_reference and flags members of acpi_iort_id_mapping
+ * are not used. This is done to avoid creating a new structure for
+ * same purpose.
+ *
+ * smmu node pointer is stored in this structure because, in some 

places
+ * smmu_node along with streamid is required based on rid and pcirc_node.
+ */

xen/include/asm-arm/acpi/ridmap.h new file +22 -0
+struct rid_sid_map
+{
+    struct acpi_iort_node *pcirc_node;
+    struct acpi_iort_node *smmu_node;
+    struct acpi_iort_id_mapping idmap;
+    struct list_head entry;
+};
+
+/*
+ * API to add a rid-sid mapping
+ * This method should be called while parsing each entry in idmap array
+ * under the pcirc node in IORT.
+ */
+int add_rid_sid_map(struct acpi_iort_node *pcirc_node,
+                    struct acpi_iort_node *smmu_node,
+                    uint32_t input_base, uint32_t output_base,
+                    uint32_t id_count);
+/*
+ * API to query sid and smmu_node based on pcirc_node and rid.
+ *
+ * Example of usage:
+ *  int iort_pci_iommu_init(struct pci_dev *pdev, u16 alias, void 

*data)
+ *  {

Quoted 8 lines
Quoted 6 lines

+ *     struct iort_pci_alias_info *info = data;
+ *   ...
+ *      if ( query_sid(info->node, alias, &streamid, &smmu_node) )
+ *          return iort_iommu_xlate(info->dev, smmu_node, streamid);
+ *   ...
+ *   }

I don't see the benefits of the example usage. If the function is difficult to use, then it much better to describe each argument.

It is not difficult, I was citing an example usecase, as you requested in earlier comments, What is the best place to add it ? commit message / code comments.

Quoted 41 lines

xen/include/asm-arm/acpi/ridmap.h line 75

Quoted 8 lines

+ *
+ */

xen/include/asm-arm/acpi/ridmap.h new file +5 -0
+bool query_sid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+               uint32_t *sid, struct acpi_iort_node **smmu_node);
+
+/*
+ * structure to hold a mapping between requresterid and deviceid.

requesterid

xen/include/asm-arm/acpi/ridmap.h line 86

Quoted 11 lines

+ * Note: output_reference and flags members of acpi_iort_id_mapping
+ * are not used. This is done to avoid creating a new structure for
+ * same purpose.
+ */

xen/include/asm-arm/acpi/ridmap.h new file +7 -0
+struct rid_devid_map
+{
+    struct acpi_iort_node *pcirc_node;
+    struct acpi_iort_node *its_node;
+    struct acpi_iort_id_mapping idmap;
+    struct list_head entry;
+};

You could probably merge this structure and rid_sid_map. The only difference is smmu_node, so you could use an union for that.

xen/include/asm-arm/acpi/ridmap.h line 99

Quoted 13 lines
xen/include/asm-arm/acpi/ridmap.h new file +13 -0
+
+/*
+ * API to add a rid-devid mapping
+ * This method should be called while parsing each entry in idmap array
+ * under the pcirc node in IORT.
+ */
+int add_rid_devid_map(struct acpi_iort_node *pcirc_node,
+                      struct acpi_iort_node *its_node,
+                      uint32_t input_base, uint32_t output_base,
+                      uint32_t id_count);
+
+/*
+ * API to query devid based on pcirc_node and rid */

Comment coding style.

Quoted 17 lines
Quoted 4 lines
xen/include/asm-arm/acpi/ridmap.h new file +3 -0
+bool query_devid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+                 uint32_t *devid);
+

xen/include/asm-arm/acpi/ridmap.h line 112

Quoted 10 lines
xen/include/asm-arm/acpi/ridmap.h new file +10 -0
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

Cheers,

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

#4 lore raw

Re: [PATCH resend 01/13] acpi: arm: API: Populate/query rid-devid rid-sid map.

Hi,

Quoted 20 lines · Manish Jaggi
Quoted 1 line · Julien Grall

Hi Manish,

Hi Julien,

Quoted 16 lines · On 03/13/2018 03:20 PM, [email protected] wrote:
Quoted 14 lines

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.

Quoted 6 lines
Quoted 5 lines
Quoted 3 lines

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.

Thank you for updating the commit message. However, you stil don't give an idea often those function will get called and whether unsorted list will be fine.

I have added that in code comments.

Mind to show where?

[...]

Quoted 14 lines
Quoted 14 lines

xen/arch/arm/acpi/ridmap.c line 29

Quoted 11 lines
xen/arch/arm/acpi/ridmap.c new file +11 -0
+#include <asm/acpi/ridmap.h>
+#include <xen/iommu.h>
+#include <xen/kernel.h>
+#include <xen/list.h>
+#include <xen/pci.h>
+
+LIST_HEAD(rid_sid_list);
+LIST_HEAD(rid_devid_list);
+
+int add_rid_sid_map(struct acpi_iort_node *pcirc_node,
+                    struct acpi_iort_node *smmu_node,

Is there any one that will modify pcirc_node and smmu_node afterwards? If not, then they should be const.

Quoted 6 lines
Quoted 5 lines
Quoted 2 lines

+                    uint32_t input_base, uint32_t output_base, +                    uint32_t id_count)

I suggested to put __init in front of that function. But you dismissed it saying it might not be valid and you will add rationale. I don't see any rationale in that patch nor an answer to my question on the previous version.

Should a public API function be __init ?

The question is do you expect this function to be called after Xen has booted. Likely not, so this should be public to shrink down the size of Xen after boot.

[...]

Quoted 24 lines
Quoted 16 lines
Quoted 16 lines
xen/include/asm-arm/acpi/ridmap.h new file +14 -0
+/*
+ * API to add a rid-sid mapping
+ * This method should be called while parsing each entry in idmap array
+ * under the pcirc node in IORT.
+ */
+int add_rid_sid_map(struct acpi_iort_node *pcirc_node,
+                    struct acpi_iort_node *smmu_node,
+                    uint32_t input_base, uint32_t output_base,
+                    uint32_t id_count);
+/*
+ * API to query sid and smmu_node based on pcirc_node and rid.
+ *
+ * Example of usage:
+ *  int iort_pci_iommu_init(struct pci_dev *pdev, u16 alias, void 

*data)
+ *  {

Quoted 8 lines
Quoted 6 lines

+ *     struct iort_pci_alias_info *info = data;
+ *   ...
+ *      if ( query_sid(info->node, alias, &streamid, &smmu_node) )
+ *          return iort_iommu_xlate(info->dev, smmu_node, streamid);
+ *   ...
+ *   }

I don't see the benefits of the example usage. If the function is difficult to use, then it much better to describe each argument.

Quoted 2 lines

It is not difficult, I was citing an example usecase, as you requested in earlier comments, What is the best place to add it ? commit message / code comments.

Use case belongs to the commit message. The comment code should only describe the expected usage or a couple of words for the use case (but that usually part of the description of the function).

Cheers,

Signature · 6 lines
Julien Grall

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

Re: [PATCH resend 01/13] acpi: arm: API: Populate/query rid-devid rid-sid map.

In reply to [email protected]

Title: Please drop the full stop.

Quoted 284 lines · On 03/13/2018 03:20 PM, [email protected] wrote:

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
new file mode 100644
index 0000000000..daa137f625
@@ -0,0 +1,126 @@
+/*
+ * xen/drivers/acpi/arm/ridmap.c
+ *
+ * This file implements rid-sid rid-devid mapping API
+ *
+ * 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.
+ */
+
+#include <asm/acpi/ridmap.h>
+#include <xen/iommu.h>
+#include <xen/kernel.h>
+#include <xen/list.h>
+#include <xen/pci.h>
+
+LIST_HEAD(rid_sid_list);
+LIST_HEAD(rid_devid_list);
+
+int add_rid_sid_map(struct acpi_iort_node *pcirc_node,
+                    struct acpi_iort_node *smmu_node,
+                    uint32_t input_base, uint32_t output_base,
+                    uint32_t id_count)
+{
+    struct rid_sid_map *rid_map;
+
+    rid_map = xzalloc(struct rid_sid_map);
+    if ( !rid_map )
+        return -ENOMEM;
+
+    rid_map->idmap.input_base = input_base;
+    rid_map->idmap.output_base = output_base;
+    rid_map->idmap.id_count = id_count;
+    rid_map->pcirc_node = pcirc_node;
+    rid_map->smmu_node = smmu_node;
+
+    list_add_tail(&rid_map->entry, &rid_sid_list);
+
+    return 0;
+}
+
+int add_rid_devid_map(struct acpi_iort_node *pcirc_node,
+                      struct acpi_iort_node *its_node,
+                      uint32_t input_base, uint32_t output_base,
+                      uint32_t id_count)
+{
+    struct rid_devid_map *rid_map;
+
+    rid_map = xzalloc(struct rid_devid_map);
+    if ( !rid_map )
+        return -ENOMEM;
+
+    rid_map->idmap.input_base = input_base;
+    rid_map->idmap.output_base = output_base;
+    rid_map->idmap.id_count = id_count;
+    rid_map->pcirc_node = pcirc_node;
+    rid_map->its_node = its_node;
+
+    list_add_tail(&rid_map->entry, &rid_devid_list);
+
+    return 0;
+}
+
+bool query_sid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+               uint32_t *sid, struct acpi_iort_node **smmu_node)
+{
+    struct rid_sid_map *rmap;
+
+    list_for_each_entry(rmap, &rid_sid_list, entry)
+    {
+        if ( rmap->pcirc_node == pcirc_node )
+        {
+            if ( (rid >= rmap->idmap.input_base) &&
+                 (rid < rmap->idmap.input_base + rmap->idmap.id_count) )
+            {
+                *sid = rid - rmap->idmap.input_base +
+                       rmap->idmap.output_base;
+                *smmu_node = rmap->smmu_node;
+
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+bool query_devid(struct acpi_iort_node *pcirc_node,
+                uint32_t rid, uint32_t *devid)
+{
+    struct rid_devid_map *rmap;
+
+    list_for_each_entry(rmap, &rid_devid_list, entry)
+    {
+        if ( rmap->pcirc_node == pcirc_node )
+        {
+            if ( (rid >= rmap->idmap.input_base) &&
+                 (rid < rmap->idmap.input_base + rmap->idmap.id_count) )
+            {
+                *devid = rid - rmap->idmap.input_base +
+                         rmap->idmap.output_base;
+
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
xen/include/asm-arm/acpi/ridmap.h new file +112 -0
new file mode 100644
index 0000000000..5d12d86c3a
@@ -0,0 +1,112 @@
+/*
+ * xen/include/acpi/ridmap.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 __ASM_ACPI_RIDMAP_H__
+#define __ASM_ACPI_RIDMAP_H__
+
+#include <xen/acpi.h>
+
+/*
+ * List holds requesterid (rid) - streamid (sid) mapping entries.
+ */
+extern struct list_head rid_sid_list;
+/*
+ * List holds requesterid (rid) - deviceid (devid) mapping entries.
+ */
+extern struct list_head rid_devid_list;
+
+/*
+ * structure to hold mapping between requresterid and streamid.
+ * Note: output_reference and flags members of acpi_iort_id_mapping
+ * are not used. This is done to avoid creating a new structure for
+ * same purpose.
+ *
+ * smmu node pointer is stored in this structure because, in some places
+ * smmu_node along with streamid is required based on rid and pcirc_node.
+ */
+struct rid_sid_map
+{
+    struct acpi_iort_node *pcirc_node;
+    struct acpi_iort_node *smmu_node;
+    struct acpi_iort_id_mapping idmap;
+    struct list_head entry;
+};
+
+/*
+ * API to add a rid-sid mapping
+ * This method should be called while parsing each entry in idmap array
+ * under the pcirc node in IORT.
+ */
+int add_rid_sid_map(struct acpi_iort_node *pcirc_node,
+                    struct acpi_iort_node *smmu_node,
+                    uint32_t input_base, uint32_t output_base,
+                    uint32_t id_count);
+/*
+ * API to query sid and smmu_node based on pcirc_node and rid.
+ *
+ * Example of usage:
+ *  int iort_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
+ *  {
+ *     struct iort_pci_alias_info *info = data;
+ *   ...
+ *      if ( query_sid(info->node, alias, &streamid, &smmu_node) )
+ *          return iort_iommu_xlate(info->dev, smmu_node, streamid);
+ *   ...
+ *   }
+ *
+ */
+bool query_sid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+               uint32_t *sid, struct acpi_iort_node **smmu_node);
+
+/*
+ * structure to hold a mapping between requresterid and deviceid.
+ * Note: output_reference and flags members of acpi_iort_id_mapping
+ * are not used. This is done to avoid creating a new structure for
+ * same purpose.
+ */
+struct rid_devid_map
+{
+    struct acpi_iort_node *pcirc_node;
+    struct acpi_iort_node *its_node;
+    struct acpi_iort_id_mapping idmap;
+    struct list_head entry;
+};
+
+/*
+ * API to add a rid-devid mapping
+ * This method should be called while parsing each entry in idmap array
+ * under the pcirc node in IORT.
+ */
+int add_rid_devid_map(struct acpi_iort_node *pcirc_node,
+                      struct acpi_iort_node *its_node,
+                      uint32_t input_base, uint32_t output_base,
+                      uint32_t id_count);
+
+/*
+ * API to query devid based on pcirc_node and rid */
+bool query_devid(struct acpi_iort_node *pcirc_node, uint32_t rid,
+                 uint32_t *devid);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
Signature · 6 lines
Julien Grall

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

PATCH RESEND 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
#7 lore raw

Re: [PATCH resend 02/13] acpi: arm: query estimated size of hardware domain's IORT.

Title: Please drop the full stop.

Quoted 5 lines · On 03/13/2018 03:20 PM, [email protected] wrote:

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.

Please expand: "Xen code requires the size to be predeterminded".

Quoted 24 lines
---
  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 +0 -0
new file mode 100644
index 0000000000..687c4f18ee

xen/arch/arm/acpi/gen-iort.c line 5

Quoted 5 lines
xen/arch/arm/acpi/gen-iort.c new file +5 -0
@@ -0,0 +1,101 @@
+/*
+ * xen/arch/arm/acpi/gen-iort.c
+ *
+ * Code to generate IORT for hardware domain using the requesterId
+ * and deviceId map.

Here we go. You again mix upper case and lower case for the same name. To be honest, I would much prefer if you stick with deviceId. I.e first letter of the second word is uppercase.

xen/arch/arm/acpi/gen-iort.c line 7

Quoted 2 lines
xen/arch/arm/acpi/gen-iort.c new file +2 -0
+ *
+ * Manish Jaggi <[email protected]>

It is linaro.org.

Quoted 4 lines
xen/arch/arm/acpi/gen-iort.c new file +4 -0
+ * 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

xen/arch/arm/acpi/gen-iort.c line 21

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c new file +10 -0
+ * 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.
+ */
+
+#include <asm/acpi/ridmap.h>
+#include <xen/acpi.h>

I am a bit surprised that only those 2 headers are necessary.

xen/arch/arm/acpi/gen-iort.c line 28

Quoted 7 lines
xen/arch/arm/acpi/gen-iort.c new file +7 -0
+
+/*
+ * Size of hardware domains' IORT is calculated based on the number of
+ * mappings in the requesterid - deviceid mapping list.
+ * Return value 0: Success
+ */
+int estimate_iort_size(size_t *iort_size)

__init.

xen/arch/arm/acpi/gen-iort.c line 32

Quoted 4 lines
xen/arch/arm/acpi/gen-iort.c new file +4 -0
+{
+    int count = 0;
+    int pcirc_count = 0;
+    int itsg_count = 0;

All the 3 variables above should be unsigned int.

xen/arch/arm/acpi/gen-iort.c line 34

Quoted 2 lines
xen/arch/arm/acpi/gen-iort.c new file +2 -0
+    uint64_t *pcirc_array;
+    uint64_t *itsg_array;

Again, what is the rationale to store the address directly rather than "void *"? This would avoid the cast in the code.

xen/arch/arm/acpi/gen-iort.c line 35

Quoted 1 line
xen/arch/arm/acpi/gen-iort.c new file +1 -0
+    struct rid_devid_map *rmap;

I am sorry but I still don't see any comment about my comment on the previous version. For reminder:

"A bit more documention of this function would be appreciated. For instance, the rationale between browsing the list twice for allocation.

I actually do think this might be avoidable by storing a bit more information from the IORT. From the table you can easily deduced the number of root complex and ITS group. They could be store with the rest of information."

xen/arch/arm/acpi/gen-iort.c line 46

Quoted 11 lines
xen/arch/arm/acpi/gen-iort.c new file +11 -0
+
+    list_for_each_entry(rmap, &rid_devid_list, entry)
+        count++;
+
+    pcirc_array = xzalloc_bytes(sizeof(uint64_t)*count);
+    if ( !pcirc_array )
+        return -ENOMEM;
+
+    itsg_array = xzalloc_bytes(sizeof(uint64_t)*count);
+    if ( !itsg_array )
+        return -ENOMEM;

If the allocation fail, you will leak pcirc_array.

xen/arch/arm/acpi/gen-iort.c line 50

Quoted 4 lines
xen/arch/arm/acpi/gen-iort.c new file +4 -0
+
+    list_for_each_entry(rmap, &rid_devid_list, entry)
+    {
+        int i = 0;

unsigned.

Quoted 17 lines
xen/arch/arm/acpi/gen-iort.c new file +17 -0
+
+        for ( i = 0; i <= pcirc_count; i++ )
+        {
+            if ( pcirc_array[i] == (uint64_t) rmap->pcirc_node )
+                break;
+            if ( i == pcirc_count )
+            {
+                pcirc_array[i] = (uint64_t) rmap->pcirc_node;
+                pcirc_count++;
+                break;
+            }
+        }
+
+        for ( i = 0; i <= itsg_count; i++ )
+        {
+            if ( itsg_array[i] == (uint64_t) rmap->its_node )
+                break;

xen/arch/arm/acpi/gen-iort.c line 77

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c new file +10 -0
+            if ( i == itsg_count )
+            {
+                itsg_array[i] = (uint64_t) rmap->its_node;
+                itsg_count++;
+                break;
+            }
+        }
+    }
+
+    /* Size of IORT

Coding style.

xen/arch/arm/acpi/gen-iort.c line 87

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c new file +10 -0
+     * = Size of IORT Table Header + Size of PCIRC Header Nodes +
+     *   Size of PCIRC nodes + Size of ITS Header nodes + Size of ITS Nodes
+     *   + Size of idmap nodes
+     */
+    *iort_size = sizeof(struct acpi_table_iort) +
+                 pcirc_count*( (sizeof(struct acpi_iort_node) -1) +
+                               sizeof(struct acpi_iort_root_complex) ) +
+                 itsg_count*( (sizeof(struct acpi_iort_node) -1) +
+                               sizeof(struct acpi_iort_its_group) ) +
+                 count*( sizeof(struct acpi_iort_id_mapping) );

Coding style in general:
- No space needed after ( in that cases
- Space before and after +*-

Quoted 27 lines
xen/arch/arm/acpi/gen-iort.c new file +14 -0
+
+    xfree(itsg_array);
+    xfree(pcirc_array);
+
+    return 0;
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
xen/arch/arm/domain_build.c +1 -0
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>

xen/arch/arm/domain_build.c static int acpi_create_fadt(struct domain *d, struct membank tbl_add[]) · line 1805

Quoted 5 lines
xen/arch/arm/domain_build.c +1 -1
@@ -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;

I am ok if you keep the renaming in that patch. But you should at least mention it in the commit message.

xen/include/asm-arm/acpi/gen-iort.h

Quoted 35 lines
xen/arch/arm/domain_build.c +11 -2
      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 +0 -0
new file mode 100644
index 0000000000..3b2af1e871

Is it worth it to have a separate header for gen-iort? How about using acpi.h?

Quoted 25 lines
xen/include/asm-arm/acpi/gen-iort.h new file +23 -0
@@ -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);

xen/include/asm-arm/acpi/gen-iort.h line 33

Quoted 10 lines
xen/include/asm-arm/acpi/gen-iort.h new file +10 -0
+
+#endif
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

Cheers,

Signature · 6 lines
Julien Grall

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

Re: [PATCH resend 02/13] acpi: arm: query estimated size of hardware domain's IORT.

Hi Julien,

Quoted 5 lines · Julien Grall

Title: Please drop the full stop.

On 03/13/2018 03:20 PM, [email protected] wrote:
...

Quoted 7 lines
Quoted 1 line

+    struct rid_devid_map *rmap;

I am sorry but I still don't see any comment about my comment on the previous version. For reminder:

"A bit more documention of this function would be appreciated. For instance, the rationale between browsing the list twice for allocation.

I actually do think this might be avoidable by storing a bit more information from the IORT. From the table you can easily deduced the number of root complex and ITS group.

That will still require parsing of all IORT nodes.
I am add one more api to return total mappings, which would basically return a counter which is updated when add_rid_deviceid_map is called. This would replace

+    list_for_each_entry(rmap, &rid_devid_list, entry) +        count++;
+

Sounds good?

Quoted 2 lines

They could be store with the rest of information."

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

#9 lore raw

PATCH RESEND 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
#10 lore raw

Re: [PATCH resend 03/13] acpi: arm: Code to generate Hardware Domains IORT

Hi Manish,

Quoted 74 lines · On 03/13/2018 03:20 PM, [email protected] wrote:

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 +14 -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]

xen/arch/arm/acpi/gen-iort.c line 45

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+ * [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

s/challanges/challenges/

Quoted 21 lines
xen/arch/arm/acpi/gen-iort.c +21 -0
+ * 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

xen/arch/arm/acpi/gen-iort.c line 76

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+ * 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);

As said in the previous version, I think this should be static.

xen/arch/arm/acpi/gen-iort.c line 82

Quoted 6 lines
xen/arch/arm/acpi/gen-iort.c +6 -0
+
+/*
+ * is_uniq_fwits_node
+ *
+ * returns 1 - if fwits_node is not already in the its_map_list
+ *         0 - if it is present already

It also returns -ENOMEM when you can't allocate memory.

xen/arch/arm/acpi/gen-iort.c line 88

Quoted 6 lines
xen/arch/arm/acpi/gen-iort.c +6 -0
+ *
+ * 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,

The name is a bit odd given that you add the ITS node. On the previous version, I requested to document that behavior...

But you likely want to rename the function to add_fwits_node(...) or something similar.

xen/arch/arm/acpi/gen-iort.c line 99

Quoted 11 lines
xen/arch/arm/acpi/gen-iort.c +11 -0
+                              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);

Where this memory is going to be freed?

Quoted 19 lines
xen/arch/arm/acpi/gen-iort.c +19 -0
+    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)

xen/arch/arm/acpi/gen-iort.c line 128

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+{
+    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;

0 could never be a valid offset, right?

xen/arch/arm/acpi/gen-iort.c line 131

Quoted 3 lines
xen/arch/arm/acpi/gen-iort.c +3 -0
+}
+
+static void write_hwits_nodes(u8 *iort, unsigned int *offset,

Please avoid using u* and use uint_* instead. I expect that you fix all of for the next version.

Here, I think you want to use void *.

xen/arch/arm/acpi/gen-iort.c line 135

Quoted 4 lines
xen/arch/arm/acpi/gen-iort.c +4 -0
+                              unsigned int *num_nodes)
+{
+    struct rid_devid_map *rmap;
+    unsigned int of = *offset;

Please name it off. This is clearer that it is an offset. But as I said on the previous version, why can't you just re-use offset?

Quoted 5 lines
xen/arch/arm/acpi/gen-iort.c +5 -0
+    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

xen/arch/arm/acpi/gen-iort.c line 150

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+     * 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 )

If the function is returning -ENOMEM, then you will ignore the node without a warning. That's going to be a real pain to find out a ITS node is not present if that happen.

Here, you should propagate error if something wrong is going.

xen/arch/arm/acpi/gen-iort.c line 158

Quoted 8 lines
xen/arch/arm/acpi/gen-iort.c +8 -0
+        {
+            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);

While the substraction is good, this is odd enough to warrant a comment. But likely But likely you want to provide macros for defining the length. This will clean a lot the code.

xen/arch/arm/acpi/gen-iort.c line 160

Quoted 2 lines
xen/arch/arm/acpi/gen-iort.c +2 -0
+
+            node->revision = rmap->its_node->revision;

I am not sure this is right. You rewrite the IORT based on a given revision. Imagine the host IORT get updated to a newer spec but not Xen. Then you would end up to have the wrong revision number here.

xen/arch/arm/acpi/gen-iort.c line 169

Quoted 9 lines
xen/arch/arm/acpi/gen-iort.c +9 -0
+            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];

Hmmm, here you will only copy the first identifier. What if you have multiple one?

It would also be good that somewhere (maybe at the top of the file) that you rely on the number of ITS and identifiers for the hwdom is the same as the host.

Quoted 16 lines
xen/arch/arm/acpi/gen-iort.c +16 -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;

xen/arch/arm/acpi/gen-iort.c line 195

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+    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;

This should be bool.

I am going to stop the review here because I feel I am just repeating all my comments from the first version and new ones. So please go through *all* my e-mails from the previous version, answer to my question, and respin it.

Cheers,

Signature · 6 lines
Julien Grall

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

Re: [PATCH resend 03/13] acpi: arm: Code to generate Hardware Domains IORT

Quoted 135 lines · Julien Grall

Hi Manish,

Quoted 81 lines · On 03/13/2018 03:20 PM, [email protected] wrote:

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 +21 -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 
Quoted 4 lines

parsing IORT
+ * is used to generate hwdom IORT.
+ *
+ * One of the challanges is to fixup node offset of ITS Group Nodes

s/challanges/challenges/

Quoted 22 lines

+ * 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.
+ *
+ */

xen/arch/arm/acpi/gen-iort.c +4 -0
+
+/*
+ * Stores the mapping between firmware tables its group node
+ * to the offset of the equivalent its node to be stored in

xen/arch/arm/acpi/gen-iort.c line 76

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+ * 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);

As said in the previous version, I think this should be static.

xen/arch/arm/acpi/gen-iort.c line 82

Quoted 6 lines
xen/arch/arm/acpi/gen-iort.c +6 -0
+
+/*
+ * is_uniq_fwits_node
+ *
+ * returns 1 - if fwits_node is not already in the its_map_list
+ *         0 - if it is present already

It also returns -ENOMEM when you can't allocate memory.

Quoted 8 lines
Quoted 6 lines

+ *
+ * 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,

The name is a bit odd given that you add the ITS node. On the previous version, I requested to document that behavior...

I think the name is quite appropriate. Also in this patch I have added description of the flow so this should be fairly intuitive. Could you please let me know the specific point you dont understand, I can explain that.

Quoted 2 lines

But you likely want to rename the function to add_fwits_node(...) or something similar.

I think name is quite appropriate.

Quoted 15 lines

xen/arch/arm/acpi/gen-iort.c line 99

Quoted 12 lines

+                              unsigned int offset)

xen/arch/arm/acpi/gen-iort.c +10 -0
+{
+    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);

Where this memory is going to be freed?

Since this list can be used multiple times even after creation of IORT for dom0, say thinking ahead for domUs.

Quoted 24 lines
Quoted 24 lines

+    if ( !map )
+        return -ENOMEM;

xen/arch/arm/acpi/gen-iort.c +17 -0
+
+    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)

xen/arch/arm/acpi/gen-iort.c +4 -0
+{
+    struct fwits_hwits_map *map;
+
+    list_for_each_entry(map, &fwits_hwits_list, entry)
Quoted 8 lines
Quoted 6 lines

+    {
+        if ( map->fwits_node == fwits_node )
+            return map->hwitsnode_offset;
+    }
+
+    return 0;

0 could never be a valid offset, right?

Yes
See a bug_on when it is used.

Quoted 7 lines

xen/arch/arm/acpi/gen-iort.c line 131

Quoted 4 lines
xen/arch/arm/acpi/gen-iort.c +3 -0
+}
+
+static void write_hwits_nodes(u8 *iort, unsigned int *offset,

Please avoid using u* and use uint_* instead. I expect that you fix all of for the next version.

Quoted 8 lines

Here, I think you want to use void *.

Quoted 4 lines

+                              unsigned int *num_nodes) +{
+    struct rid_devid_map *rmap;
+    unsigned int of = *offset;

Please name it off. This is clearer that it is an offset. But as I said on the previous version, why can't you just re-use offset?

I will change it to off, will not break anything.

Quoted 19 lines
Quoted 6 lines

+    int n = 0;

xen/arch/arm/acpi/gen-iort.c +4 -0
+
+    /*
+     * rid_devid_list is iterated to get unique its group nodes
+     * Each unique ITS group node is written in hardware domains IORT

xen/arch/arm/acpi/gen-iort.c line 150

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+     * 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 )

If the function is returning -ENOMEM, then you will ignore the node without a warning. That's going to be a real pain to find out a ITS node is not present if that happen.

Quoted 1 line

Here, you should propagate error if something wrong is going.

ok.

Quoted 10 lines
Quoted 9 lines

+        {
+            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);

Quoted 6 lines

While the substraction is good, this is odd enough to warrant a comment. But likely But likely you want to provide macros for defining the length. This will clean a lot the code.

Quoted 2 lines

+
+            node->revision = rmap->its_node->revision;

I am not sure this is right. You rewrite the IORT based on a given revision. Imagine the host IORT get updated to a newer spec but not Xen.

Not sure if I follow your comment here.
Xen gets host IORT from firmware, how will it get updated?

Quoted 16 lines

Then you would end up to have the wrong revision number here.

Quoted 11 lines

+            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];

Hmmm, here you will only copy the first identifier. What if you have multiple one?

Quoted 2 lines

It would also be good that somewhere (maybe at the top of the file) that you rely on the number of ITS and identifiers for the hwdom is the same as the host.

ok

Quoted 29 lines
Quoted 16 lines
xen/arch/arm/acpi/gen-iort.c +16 -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;

xen/arch/arm/acpi/gen-iort.c line 195

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+    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;

This should be bool.

Quoted 2 lines

I am going to stop the review here because I feel I am just repeating all my comments from the first version and new ones. So please go through *all* my e-mails from the previous version, answer to my question, and respin it.

Could you please have a look at other patches and if there is functionality related change that I need to make, i can add that in my next rev.

Quoted 2 lines

Cheers,

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

#12 lore raw

Re: [PATCH resend 03/13] acpi: arm: Code to generate Hardware Domains IORT

Hi,

Quoted 9 lines · Manish Jaggi
Quoted 8 lines · Julien Grall
Quoted 6 lines · On 03/13/2018 03:20 PM, [email protected] wrote:

+ *
+ * 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,

Quoted 3 lines
Quoted 1 line

The name is a bit odd given that you add the ITS node. On the previous version, I requested to document that behavior...

I think the name is quite appropriate. Also in this patch I have added description of the flow so this should be fairly intuitive. Could you please let me know the specific point you dont understand, I can explain that.

The fact that a function calling is_* will add the element to the list. An is_* function should only check the element is in the list.

So yes, it is not intuitive for me.

Quoted 3 lines
Quoted 2 lines

But you likely want to rename the function to add_fwits_node(...) or something similar.

I think name is quite appropriate.

See above.

Quoted 15 lines
Quoted 15 lines

xen/arch/arm/acpi/gen-iort.c line 99

Quoted 12 lines

+                              unsigned int offset)

xen/arch/arm/acpi/gen-iort.c +10 -0
+{
+    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);

Where this memory is going to be freed?

Quoted 1 line

Since this list can be used multiple times even after creation of IORT for dom0, say thinking ahead for domUs.

IORT for DomU will not rely on the host firmware and will be created by the toolstack. It does not make sense to keep that around.

Quoted 32 lines
Quoted 24 lines
Quoted 24 lines

+    if ( !map )
+        return -ENOMEM;

xen/arch/arm/acpi/gen-iort.c +17 -0
+
+    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)

xen/arch/arm/acpi/gen-iort.c +4 -0
+{
+    struct fwits_hwits_map *map;
+
+    list_for_each_entry(map, &fwits_hwits_list, entry)
Quoted 8 lines
Quoted 6 lines

+    {
+        if ( map->fwits_node == fwits_node )
+            return map->hwitsnode_offset;
+    }
+
+    return 0;

0 could never be a valid offset, right?

Quoted 2 lines

Yes
See a bug_on when it is used.

I don't much care about the BUG_ON()... I was only checking what the spec says here.

But... you document the return really well on the previous function and here it is seems to be forgotten.

Quoted 9 lines
Quoted 9 lines

xen/arch/arm/acpi/gen-iort.c line 131

Quoted 4 lines
xen/arch/arm/acpi/gen-iort.c +3 -0
+}
+
+static void write_hwits_nodes(u8 *iort, unsigned int *offset,

Please avoid using u* and use uint_* instead. I expect that you fix all of for the next version.

Here, I think you want to use void *.

Quoted 7 lines
Quoted 6 lines
Quoted 4 lines

+                              unsigned int *num_nodes) +{
+    struct rid_devid_map *rmap;
+    unsigned int of = *offset;

Please name it off. This is clearer that it is an offset. But as I said on the previous version, why can't you just re-use offset?

I will change it to off, will not break anything.

It does not answer my question.

Quoted 31 lines
Quoted 19 lines
Quoted 6 lines

+    int n = 0;

xen/arch/arm/acpi/gen-iort.c +4 -0
+
+    /*
+     * rid_devid_list is iterated to get unique its group nodes
+     * Each unique ITS group node is written in hardware domains IORT

xen/arch/arm/acpi/gen-iort.c line 150

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+     * 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 )

If the function is returning -ENOMEM, then you will ignore the node without a warning. That's going to be a real pain to find out a ITS node is not present if that happen.

Quoted 1 line

Here, you should propagate error if something wrong is going.

ok.

Quoted 10 lines
Quoted 9 lines

+        {
+            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);

Quoted 8 lines
Quoted 6 lines

While the substraction is good, this is odd enough to warrant a comment. But likely But likely you want to provide macros for defining the length. This will clean a lot the code.

Quoted 2 lines

+
+            node->revision = rmap->its_node->revision;

I am not sure this is right. You rewrite the IORT based on a given revision. Imagine the host IORT get updated to a newer spec but not Xen.

Not sure if I follow your comment here.
Xen gets host IORT from firmware, how will it get updated?

The host IORT will be built on top of a revision X. For the hwdom IORT, at the moment, you are always building on top of revision 0.

While today X == 0, this may change in the future and will prevent proper booting.

Quoted 29 lines
Quoted 29 lines
Quoted 16 lines
xen/arch/arm/acpi/gen-iort.c +16 -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;

xen/arch/arm/acpi/gen-iort.c line 195

Quoted 10 lines
xen/arch/arm/acpi/gen-iort.c +10 -0
+    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;

This should be bool.

Quoted 3 lines
Quoted 2 lines

I am going to stop the review here because I feel I am just repeating all my comments from the first version and new ones. So please go through *all* my e-mails from the previous version, answer to my question, and respin it.

Could you please have a look at other patches and if there is functionality related change that I need to make, i can add that in my next rev.

I am afraid I am not going to have time reviewing for the next couple of weeks.

Cheers,

Signature · 6 lines
Julien Grall

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

PATCH RESEND 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
#14 lore raw

PATCH RESEND 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
#15 lore raw

PATCH RESEND 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
#16 lore raw

PATCH RESEND 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
#17 lore raw

PATCH RESEND 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
#18 lore raw

PATCH RESEND 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
#19 lore raw

PATCH RESEND 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
#20 lore raw

PATCH RESEND 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
#21 lore raw

PATCH RESEND 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
#22 lore raw

PATCH RESEND 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