The branch main has been updated by andrew:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e8aebac4645348b520e7d00c3eed59f1de228b87

commit e8aebac4645348b520e7d00c3eed59f1de228b87
Author:     Sarah Walker <[email protected]>
AuthorDate: 2026-08-04 12:33:46 +0000
Commit:     Andrew Turner <[email protected]>
CommitDate: 2026-09-08 03:05:28 +0000

    sys: arm64: acpica: Add support for GICv5 ITS & IWB nodes
    
    Reviewed by:    andrew
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D59168
---
 sys/arm64/acpica/acpi_iort.c | 142 ++++++++++++++++++++++++++++++++++++++-----
 sys/dev/acpica/acpivar.h     |   2 +
 2 files changed, 130 insertions(+), 14 deletions(-)

diff --git a/sys/arm64/acpica/acpi_iort.c b/sys/arm64/acpica/acpi_iort.c
index a180dc1a2a2c..eef2575fe432 100644
--- a/sys/arm64/acpica/acpi_iort.c
+++ b/sys/arm64/acpica/acpi_iort.c
@@ -33,6 +33,7 @@
 #include <sys/bus.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/sbuf.h>
 
 #include <machine/intr.h>
 
@@ -82,6 +83,15 @@ struct iort_named_component
        char                    DeviceName[32]; /* Path of namespace object */
 };
 
+struct iort_iwb
+{
+    UINT64 BaseAddress;
+    /* Unique IWB identifier matching with the IWB GSI namespace. */
+    UINT16 IwbIndex;
+    /* Path of the IWB namespace object */
+    char   DeviceName[32];
+};
+
 /*
  * IORT node. Each node has some device specific data depending on the
  * type of the node. The node can also have a set of mappings, OR in
@@ -104,6 +114,7 @@ struct iort_node {
                ACPI_IORT_SMMU                  smmu;
                ACPI_IORT_SMMU_V3               smmu_v3;
                struct iort_named_component     named_comp;
+               struct iort_iwb                 iwb;
        } data;
 };
 
@@ -112,6 +123,7 @@ static TAILQ_HEAD(, iort_node) pci_nodes = 
TAILQ_HEAD_INITIALIZER(pci_nodes);
 static TAILQ_HEAD(, iort_node) smmu_nodes = TAILQ_HEAD_INITIALIZER(smmu_nodes);
 static TAILQ_HEAD(, iort_node) its_groups = TAILQ_HEAD_INITIALIZER(its_groups);
 static TAILQ_HEAD(, iort_node) named_nodes = 
TAILQ_HEAD_INITIALIZER(named_nodes);
+static TAILQ_HEAD(, iort_node) iwb_nodes = TAILQ_HEAD_INITIALIZER(iwb_nodes);
 
 static int
 iort_entry_get_id_mapping_index(struct iort_node *node)
@@ -325,6 +337,7 @@ iort_add_nodes(ACPI_IORT_NODE *node_entry, u_int 
node_offset)
        ACPI_IORT_SMMU_V3 *smmu_v3;
        ACPI_IORT_NAMED_COMPONENT *named_comp;
        struct iort_node *node;
+       ACPI_IORT_IWB *iwb;
 
        node = malloc(sizeof(*node), M_DEVBUF, M_WAITOK | M_ZERO);
        node->type =  node_entry->Type;
@@ -368,6 +381,19 @@ iort_add_nodes(ACPI_IORT_NODE *node_entry, u_int 
node_offset)
                iort_copy_data(node, node_entry);
                TAILQ_INSERT_TAIL(&named_nodes, node, next);
                break;
+       case ACPI_IORT_NODE_IWB:
+               iwb = (ACPI_IORT_IWB *)node_entry->NodeData;
+               memcpy(&node->data.iwb, iwb, sizeof(*iwb));
+
+               /* Copy name of the node separately. */
+               strncpy(node->data.iwb.DeviceName,
+                   iwb->DeviceName,
+                   sizeof(node->data.iwb.DeviceName));
+               node->data.iwb.DeviceName[31] = 0;
+
+               iort_copy_data(node, node_entry);
+               TAILQ_INSERT_TAIL(&iwb_nodes, node, next);
+               break;
        default:
                printf("ACPI: IORT: Dropping unhandled type %u\n",
                    node_entry->Type);
@@ -429,6 +455,9 @@ iort_post_process_mappings(void)
        TAILQ_FOREACH(node, &named_nodes, next)
                for (i = 0; i < node->nentries; i++)
                        iort_resolve_node(&node->entries.mappings[i], TRUE);
+       TAILQ_FOREACH(node, &iwb_nodes, next)
+               for (i = 0; i < node->nentries; i++)
+                       iort_resolve_node(&node->entries.mappings[i], FALSE);
 }
 
 /*
@@ -438,29 +467,50 @@ static void
 madt_resolve_its_xref(ACPI_SUBTABLE_HEADER *entry, void *arg)
 {
        ACPI_MADT_GENERIC_TRANSLATOR *gict;
+       ACPI_MADT_GICv5_ITS *gicv5_its;
        struct iort_node *its_node;
        struct iort_its_entry *its_entry;
        u_int xref;
        int i, matches;
 
-        if (entry->Type != ACPI_MADT_TYPE_GENERIC_TRANSLATOR)
-               return;
+       switch (entry->Type) {
+       case ACPI_MADT_TYPE_GENERIC_TRANSLATOR:
+               gict = (ACPI_MADT_GENERIC_TRANSLATOR *)entry;
+               matches = 0;
+               xref = acpi_its_xref++;
+               TAILQ_FOREACH(its_node, &its_groups, next) {
+                       its_entry = its_node->entries.its;
+                       for (i = 0; i < its_node->nentries; i++, its_entry++) {
+                               if (its_entry->its_id == gict->TranslationId) {
+                                       its_entry->xref = xref;
+                                       matches++;
+                               }
+                       }
+               }
+               if (matches == 0)
+                       printf("ACPI: IORT: Unused ITS block, ID %u\n",
+                           gict->TranslationId);
+               break;
 
-       gict = (ACPI_MADT_GENERIC_TRANSLATOR *)entry;
-       matches = 0;
-       xref = acpi_its_xref++;
-       TAILQ_FOREACH(its_node, &its_groups, next) {
-               its_entry = its_node->entries.its;
-               for (i = 0; i < its_node->nentries; i++, its_entry++) {
-                       if (its_entry->its_id == gict->TranslationId) {
-                               its_entry->xref = xref;
-                               matches++;
+       case ACPI_MADT_TYPE_GICV5_ITS:
+               gicv5_its = (ACPI_MADT_GICv5_ITS *)entry;
+               matches = 0;
+               xref = acpi_its_xref++;
+               TAILQ_FOREACH(its_node, &its_groups, next) {
+                       its_entry = its_node->entries.its;
+                       for (i = 0; i < its_node->nentries; i++, its_entry++) {
+                               if (its_entry->its_id ==
+                                   gicv5_its->TranslatorId) {
+                                       its_entry->xref = xref;
+                                       matches++;
+                               }
                        }
                }
+               if (matches == 0)
+                       printf("ACPI: IORT: Unused ITSv5 block, ID %u\n",
+                           gicv5_its->TranslatorId);
+               break;
        }
-       if (matches == 0)
-               printf("ACPI: IORT: Unused ITS block, ID %u\n",
-                   gict->TranslationId);
 }
 
 /*
@@ -690,3 +740,67 @@ acpi_iort_map_named_smmuv3(const char *devname, u_int rid, 
uint64_t *xref,
 
        return (0);
 }
+
+static struct iort_node *
+acpi_iort_lookup_iwb_node(device_t bus, device_t child)
+{
+       struct iort_node *node;
+       struct sbuf *sb = sbuf_new_auto();
+
+       if (acpi_get_acpi_device_path(bus, child, BUS_LOCATOR_ACPI, sb))
+               return (NULL);
+
+       sbuf_finish(sb);
+
+       TAILQ_FOREACH(node, &iwb_nodes, next) {
+               if (!strcmp(sbuf_data(sb), node->data.iwb.DeviceName)) {
+                       sbuf_delete(sb);
+                       return (node);
+               }
+       }
+
+       sbuf_delete(sb);
+       return (NULL);
+}
+
+int
+acpi_iort_lookup_its_from_iwb(device_t dev, int *its_id)
+{
+       struct iort_node *node;
+       struct iort_node *out_node;
+       device_t bus = device_get_parent(dev);
+       int i;
+
+       node = acpi_iort_lookup_iwb_node(bus, dev);
+       if (!node)
+               return (ENODEV);
+
+       for (i = 0; i < node->nentries; i++) {
+               out_node = node->entries.mappings[i].out_node;
+               if (out_node->type == ACPI_IORT_NODE_ITS_GROUP) {
+                       *its_id = out_node->entries.its[0].its_id;
+                       return (0);
+               }
+       }
+
+       return (ENODEV);
+}
+
+device_t
+acpi_iort_get_iwb_dev(int iwb_id)
+{
+       struct iort_node *node;
+       ACPI_HANDLE iwb_handle;
+
+       TAILQ_FOREACH(node, &iwb_nodes, next) {
+               if (node->data.iwb.IwbIndex == iwb_id) {
+                       if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT,
+                           node->data.iwb.DeviceName, &iwb_handle)))
+                               panic("Can't get IWB ACPI handle\n");
+
+                       return (acpi_get_device(iwb_handle));
+               }
+       }
+
+       return (NULL);
+}
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index 028b39637a45..05d581b77fb9 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -640,6 +640,8 @@ int acpi_iort_map_named_msi(const char *devname, u_int rid, 
u_int *xref,
            u_int *devid);
 int    acpi_iort_map_named_smmuv3(const char *devname, u_int rid,
            uint64_t *xref, u_int *devid);
+int    acpi_iort_lookup_its_from_iwb(device_t dev, int *its_id);
+device_t       acpi_iort_get_iwb_dev(int iwb_id);
 #endif
 #endif /* _KERNEL */
 #endif /* !_ACPIVAR_H_ */

Reply via email to