git: d00f1d6858a0 - stable/13 - gic_v3: Correctly handle GICC GIGR Base Address case
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 15 Dec 2025 18:18:44 UTC
The branch stable/13 has been updated by jrtc27:
URL: https://cgit.FreeBSD.org/src/commit/?id=d00f1d6858a0caca5c52f819da8381a6be11e3a9
commit d00f1d6858a0caca5c52f819da8381a6be11e3a9
Author: Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2024-12-09 21:55:06 +0000
Commit: Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2025-12-15 17:56:36 +0000
gic_v3: Correctly handle GICC GIGR Base Address case
When using the GICR Base Address field from each GICC structure instead
of GICR structures, the field gives the address of a single
redistributor page. However, that does not mean that they are not
contiguous, and so GICR_TYPER.Last could be clear on them. Thus we must
ignore GICR_TYPER.Last in this case and always treat each region as
having a single page. Normally we'd do that as a result of checking
against the rman's size (though that's a rather roundabout and iffy way
of achieving it), but for whatever reason this is bigger on the Qualcomm
Snapdragon X Elite (I assume the MADT reports GICv4 but TYPER doesn't
report VLPIS and so there is a mismatch between the rman size and the
stride used) and we end up walking off the region's mapping.
Reviewed by: andrew, phk
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D47560
(cherry picked from commit f8c90b704189c94275d22d7cc204d1d74e821d86)
---
sys/arm64/arm64/gic_v3.c | 3 ++-
sys/arm64/arm64/gic_v3_acpi.c | 1 +
sys/arm64/arm64/gic_v3_var.h | 6 ++++++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c
index c90edc3ba14c..5e77d2670217 100644
--- a/sys/arm64/arm64/gic_v3.c
+++ b/sys/arm64/arm64/gic_v3.c
@@ -1315,7 +1315,8 @@ gic_v3_redist_find(struct gic_v3_softc *sc)
}
rman_set_bushandle(&r_res, r_bsh);
- } while ((typer & GICR_TYPER_LAST) == 0);
+ } while (!sc->gic_redists.single &&
+ (typer & GICR_TYPER_LAST) == 0);
}
device_printf(sc->dev, "No Re-Distributor found for CPU%u\n", cpuid);
diff --git a/sys/arm64/arm64/gic_v3_acpi.c b/sys/arm64/arm64/gic_v3_acpi.c
index 45e5578ee647..287c8c2d99eb 100644
--- a/sys/arm64/arm64/gic_v3_acpi.c
+++ b/sys/arm64/arm64/gic_v3_acpi.c
@@ -290,6 +290,7 @@ gic_v3_acpi_count_regions(device_t dev)
acpi_walk_subtables(madt + 1,
(char *)madt + madt->Header.Length,
madt_count_gicc_redistrib, sc);
+ sc->gic_redists.single = true;
}
acpi_unmap_table(madt);
diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h
index 1a4112a4b0ea..c5ca77a46811 100644
--- a/sys/arm64/arm64/gic_v3_var.h
+++ b/sys/arm64/arm64/gic_v3_var.h
@@ -52,6 +52,12 @@ struct gic_redists {
struct resource ** regions;
/* Number of Re-Distributor regions */
u_int nregions;
+ /*
+ * Whether to treat each region as a single Re-Distributor page or a
+ * series of contiguous pages (i.e. from each ACPI MADT GICC's GICR
+ * Base Address field)
+ */
+ bool single;
/* Per-CPU Re-Distributor data */
struct redist_pcpu *pcpu[MAXCPU];
};