[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 3/4] xen/arm: its: refactor ITS quirk matching



From: Mykola Kvach <mykola_kvach@xxxxxxxx>

ITS quirks are currently matched only by IIDR and mask fields stored in
each table entry. That is too coarse for integrations where the same GIC
IP block can appear in several platforms but the workaround is only valid
for a subset of boards.

Replace the fixed IIDR fields with a generic match(hw_its, data) callback
and an opaque data pointer. Add an IIDR matcher as a reusable building
block and use it from the R-Car Gen4 matcher after checking the Renesas
machine compatibles. The R-Car Gen4 platform refinement is DT-only;
ACPI-discovered ITSes do not match it.

Keep first-match semantics explicit. Assert that non-sentinel entries
provide a matcher and that IIDR matching receives match data, but keep
runtime guards so a malformed table entry does not become a NULL function
call or NULL data dereference in non-debug builds. The matched entry still
supplies separate ITS and LPI flags; this patch only changes how the entry
is selected.

Signed-off-by: Mykola Kvach <mykola_kvach@xxxxxxxx>
---
Changes in v2:
- Replace v1's optional platform callback plus fixed IIDR/mask fields with
  a single generic match(hw_its, data) selector.
- Add a reusable IIDR matcher and use it after the R-Car Gen4
  machine-compatible checks.
- Document that the R-Car Gen4 quirk remains DT-only.
- Keep the split ITS and host LPI quirk scopes when applying the matched
  entry.
- Document first-match ordering in the lookup path and guard against
  entries without a match callback or IIDR match data.
---
 xen/arch/arm/gic-v3-its.c | 67 +++++++++++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index dc48a84789..e055914763 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -53,8 +53,8 @@ struct its_device {
 
 struct its_quirk {
     const char *desc;
-    uint32_t iidr;
-    uint32_t mask;
+    bool (*match)(const struct host_its *hw_its, const void *data);
+    const void *data;
     uint32_t its_flags;
     /*
      * lpi_flags are ORed into the global host LPI policy and must only
@@ -64,11 +64,48 @@ struct its_quirk {
     uint32_t lpi_flags;
 };
 
+struct its_quirk_match_iidr {
+    uint32_t iidr;
+    uint32_t mask;
+};
+
+static bool __init gicv3_its_match_iidr(const struct host_its *hw_its,
+                                        const void *data)
+{
+    const struct its_quirk_match_iidr *match;
+    uint32_t iidr;
+
+    ASSERT(data);
+
+    match = data;
+    iidr = readl_relaxed(hw_its->its_base + GITS_IIDR);
+
+    return (iidr & match->mask) == match->iidr;
+}
+
+static bool __init gicv3_its_match_quirk_gen4(const struct host_its *hw_its,
+                                              const void *data)
+{
+    if ( !hw_its->dt_node )
+        return false;
+
+    if ( !dt_machine_is_compatible("renesas,r8a779f0") &&
+         !dt_machine_is_compatible("renesas,r8a779g0") )
+        return false;
+
+    return gicv3_its_match_iidr(hw_its, data);
+}
+
+static const struct its_quirk_match_iidr rcar_gen4_iidr = {
+    .iidr = 0x0201743b,
+    .mask = 0xffffffffU,
+};
+
 static const struct its_quirk its_quirks[] = {
     {
-        .desc  = "R-Car Gen4",
-        .iidr  = 0x0201743b,
-        .mask  = 0xffffffffU,
+        .desc = "R-Car Gen4",
+        .match = gicv3_its_match_quirk_gen4,
+        .data = &rcar_gen4_iidr,
         .its_flags = GICV3_QUIRK_MEM_NC_NS | GICV3_QUIRK_MEM_32BIT_ADDR,
         .lpi_flags = GICV3_QUIRK_MEM_NC_NS | GICV3_QUIRK_MEM_32BIT_ADDR,
     },
@@ -77,18 +114,21 @@ static const struct its_quirk its_quirks[] = {
     }
 };
 
-static const struct its_quirk *__init gicv3_its_find_quirk(uint32_t iidr)
+static const struct its_quirk *__init gicv3_its_find_quirk(
+    const struct host_its *hw_its)
 {
-    const struct its_quirk *quirks = its_quirks;
+    const struct its_quirk *quirk;
 
     /*
-     * The first matching quirk wins. More specific quirks must be listed
-     * before broader IIDR-only entries.
+     * The first matching quirk wins. Entries that match a specific platform
+     * must be listed before broader IIDR-only entries.
      */
-    for ( ; quirks->desc; quirks++ )
+    for ( quirk = its_quirks; quirk->desc; quirk++ )
     {
-        if ( quirks->iidr == (quirks->mask & iidr) )
-            return quirks;
+        ASSERT(quirk->match);
+
+        if ( quirk->match && quirk->match(hw_its, quirk->data) )
+            return quirk;
     }
 
     return NULL;
@@ -96,8 +136,7 @@ static const struct its_quirk *__init 
gicv3_its_find_quirk(uint32_t iidr)
 
 static void __init gicv3_its_collect_quirks(struct host_its *hw_its)
 {
-    uint32_t iidr = readl_relaxed(hw_its->its_base + GITS_IIDR);
-    const struct its_quirk *quirk = gicv3_its_find_quirk(iidr);
+    const struct its_quirk *quirk = gicv3_its_find_quirk(hw_its);
 
     if ( quirk )
     {
-- 
2.43.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.