The branch main has been updated by andrew:

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

commit ae16cbfdd2a1821f69d166c4fc4cdbb4b8d5ef62
Author:     Andrew Turner <and...@freebsd.org>
AuthorDate: 2023-05-25 08:22:03 +0000
Commit:     Andrew Turner <and...@freebsd.org>
CommitDate: 2023-05-31 14:10:41 +0000

    gicv3: Use an offset to find the redist registers
    
    To find the redistributor registers use the resource we have already
    found and add an offset. This removed the need to create a
    per-redistributor resource as it can now be a pointer to the resource
    found in attach.
    
    While here check the offset is within the bounds of the resource. Some
    ACPI tables list each redistributor as a separate memory range, even
    if they are physically contiguous. In this case we may not have each
    resource virtually contiguous with neighbouring resources. This can
    lead to a data abort when reading past the resource range.
    
    Reviewed by:    kevans
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D40263
---
 sys/arm64/arm64/gic_v3.c     | 41 ++++++++++++++++++++++++-----------------
 sys/arm64/arm64/gic_v3_var.h | 12 +++++++-----
 sys/arm64/arm64/gicv3_its.c  |  3 ++-
 3 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c
index e9754797d095..d108cabfe4d9 100644
--- a/sys/arm64/arm64/gic_v3.c
+++ b/sys/arm64/arm64/gic_v3.c
@@ -226,7 +226,8 @@ gic_r_read_4(device_t dev, bus_size_t offset)
        struct resource *rdist;
 
        sc = device_get_softc(dev);
-       rdist = &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res;
+       rdist = sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res;
+       offset += sc->gic_redists.pcpu[PCPU_GET(cpuid)]->offset;
        return (bus_read_4(rdist, offset));
 }
 
@@ -237,7 +238,8 @@ gic_r_read_8(device_t dev, bus_size_t offset)
        struct resource *rdist;
 
        sc = device_get_softc(dev);
-       rdist = &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res;
+       rdist = sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res;
+       offset += sc->gic_redists.pcpu[PCPU_GET(cpuid)]->offset;
        return (bus_read_8(rdist, offset));
 }
 
@@ -248,7 +250,8 @@ gic_r_write_4(device_t dev, bus_size_t offset, uint32_t val)
        struct resource *rdist;
 
        sc = device_get_softc(dev);
-       rdist = &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res;
+       rdist = sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res;
+       offset += sc->gic_redists.pcpu[PCPU_GET(cpuid)]->offset;
        bus_write_4(rdist, offset, val);
 }
 
@@ -259,7 +262,8 @@ gic_r_write_8(device_t dev, bus_size_t offset, uint64_t val)
        struct resource *rdist;
 
        sc = device_get_softc(dev);
-       rdist = &sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res;
+       rdist = sc->gic_redists.pcpu[PCPU_GET(cpuid)]->res;
+       offset += sc->gic_redists.pcpu[PCPU_GET(cpuid)]->offset;
        bus_write_8(rdist, offset, val);
 }
 
@@ -1215,6 +1219,7 @@ static void
 gic_v3_wait_for_rwp(struct gic_v3_softc *sc, enum gic_v3_xdist xdist)
 {
        struct resource *res;
+       bus_size_t offset;
        u_int cpuid;
        size_t us_left = 1000000;
 
@@ -1223,16 +1228,18 @@ gic_v3_wait_for_rwp(struct gic_v3_softc *sc, enum 
gic_v3_xdist xdist)
        switch (xdist) {
        case DIST:
                res = sc->gic_dist;
+               offset = 0;
                break;
        case REDIST:
-               res = &sc->gic_redists.pcpu[cpuid]->res;
+               res = sc->gic_redists.pcpu[cpuid]->res;
+               offset = sc->gic_redists.pcpu[PCPU_GET(cpuid)]->offset;
                break;
        default:
                KASSERT(0, ("%s: Attempt to wait for unknown RWP", __func__));
                return;
        }
 
-       while ((bus_read_4(res, GICD_CTLR) & GICD_CTLR_RWP) != 0) {
+       while ((bus_read_4(res, offset + GICD_CTLR) & GICD_CTLR_RWP) != 0) {
                DELAY(1);
                if (us_left-- == 0)
                        panic("GICD Register write pending for too long");
@@ -1377,8 +1384,8 @@ gic_v3_redist_alloc(struct gic_v3_softc *sc)
 static int
 gic_v3_redist_find(struct gic_v3_softc *sc)
 {
-       struct resource r_res;
-       bus_space_handle_t r_bsh;
+       struct resource *r_res;
+       bus_size_t offset;
        uint64_t aff;
        uint64_t typer;
        uint32_t pidr2;
@@ -1399,10 +1406,9 @@ gic_v3_redist_find(struct gic_v3_softc *sc)
        /* Iterate through Re-Distributor regions */
        for (i = 0; i < sc->gic_redists.nregions; i++) {
                /* Take a copy of the region's resource */
-               r_res = *sc->gic_redists.regions[i];
-               r_bsh = rman_get_bushandle(&r_res);
+               r_res = sc->gic_redists.regions[i];
 
-               pidr2 = bus_read_4(&r_res, GICR_PIDR2);
+               pidr2 = bus_read_4(r_res, GICR_PIDR2);
                switch (GICR_PIDR2_ARCH(pidr2)) {
                case GICR_PIDR2_ARCH_GICv3: /* fall through */
                case GICR_PIDR2_ARCH_GICv4:
@@ -1413,13 +1419,15 @@ gic_v3_redist_find(struct gic_v3_softc *sc)
                        return (ENODEV);
                }
 
+               offset = 0;
                do {
-                       typer = bus_read_8(&r_res, GICR_TYPER);
+                       typer = bus_read_8(r_res, offset + GICR_TYPER);
                        if ((typer >> GICR_TYPER_AFF_SHIFT) == aff) {
                                KASSERT(sc->gic_redists.pcpu[cpuid] != NULL,
                                    ("Invalid pointer to per-CPU 
redistributor"));
                                /* Copy res contents to its final destination */
                                sc->gic_redists.pcpu[cpuid]->res = r_res;
+                               sc->gic_redists.pcpu[cpuid]->offset = offset;
                                sc->gic_redists.pcpu[cpuid]->lpi_enabled = 
false;
                                if (bootverbose) {
                                        device_printf(sc->dev,
@@ -1429,14 +1437,13 @@ gic_v3_redist_find(struct gic_v3_softc *sc)
                                return (0);
                        }
 
-                       r_bsh += (GICR_RD_BASE_SIZE + GICR_SGI_BASE_SIZE);
+                       offset += (GICR_RD_BASE_SIZE + GICR_SGI_BASE_SIZE);
                        if ((typer & GICR_TYPER_VLPIS) != 0) {
-                               r_bsh +=
+                               offset +=
                                    (GICR_VLPI_BASE_SIZE + GICR_RESERVED_SIZE);
                        }
-
-                       rman_set_bushandle(&r_res, r_bsh);
-               } while ((typer & GICR_TYPER_LAST) == 0);
+               } while (offset < rman_get_size(r_res) &&
+                   (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_var.h b/sys/arm64/arm64/gic_v3_var.h
index 9fa8b82e16bc..47e73c1ab3b7 100644
--- a/sys/arm64/arm64/gic_v3_var.h
+++ b/sys/arm64/arm64/gic_v3_var.h
@@ -40,8 +40,9 @@ DECLARE_CLASS(gic_v3_driver);
 struct gic_v3_irqsrc;
 
 struct redist_pcpu {
-       struct resource         res;            /* mem resource for redist */
+       struct resource         *res;           /* mem resource for redist */
        vm_offset_t             pend_base;
+       bus_size_t              offset;
        bool                    lpi_enabled;    /* redist LPI configured? */
 };
 
@@ -137,8 +138,8 @@ void gic_r_write_8(device_t, bus_size_t, uint64_t var);
        u_int cpu = PCPU_GET(cpuid);            \
                                                \
        bus_read_##len(                         \
-           &(sc)->gic_redists.pcpu[cpu]->res,  \
-           (reg));                             \
+           (sc)->gic_redists.pcpu[cpu]->res,   \
+           (sc)->gic_redists.pcpu[cpu]->offset + (reg)); \
 })
 
 #define        gic_r_write(sc, len, reg, val)          \
@@ -146,8 +147,9 @@ void gic_r_write_8(device_t, bus_size_t, uint64_t var);
        u_int cpu = PCPU_GET(cpuid);            \
                                                \
        bus_write_##len(                        \
-           &(sc)->gic_redists.pcpu[cpu]->res,  \
-           (reg), (val));                      \
+           (sc)->gic_redists.pcpu[cpu]->res,   \
+           (sc)->gic_redists.pcpu[cpu]->offset + (reg), \
+           (val));                             \
 })
 
 #endif /* _GIC_V3_VAR_H_ */
diff --git a/sys/arm64/arm64/gicv3_its.c b/sys/arm64/arm64/gicv3_its.c
index 9c8f87e74f31..57351a7e76aa 100644
--- a/sys/arm64/arm64/gicv3_its.c
+++ b/sys/arm64/arm64/gicv3_its.c
@@ -723,7 +723,8 @@ its_init_cpu(device_t dev, struct gicv3_its_softc *sc)
 
        if ((gic_its_read_8(sc, GITS_TYPER) & GITS_TYPER_PTA) != 0) {
                /* This ITS wants the redistributor physical address */
-               target = vtophys(rman_get_virtual(&rpcpu->res));
+               target = vtophys((vm_offset_t)rman_get_virtual(rpcpu->res) +
+                   rpcpu->offset);
        } else {
                /* This ITS wants the unique processor number */
                target = GICR_TYPER_CPUNUM(gic_r_read_8(gicv3, GICR_TYPER)) <<

Reply via email to