The branch main has been updated by andrew:

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

commit 3fc4f7c88085dc94c88348839074b8db6f19fae1
Author:     Andrew Turner <and...@freebsd.org>
AuthorDate: 2023-08-22 10:51:26 +0000
Commit:     Andrew Turner <and...@freebsd.org>
CommitDate: 2023-08-23 14:29:34 +0000

    gicv3: Split out finding the page size
    
    When adding indirect (2 level) tabled we will need to know the page
    size to calculate the size of the level 1 table. To allow for this find
    the page size before entering the loop to calculate the final register
    value.
    
    Reviewed by:    gallatin, imp
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D41551
---
 sys/arm64/arm64/gicv3_its.c | 72 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 58 insertions(+), 14 deletions(-)

diff --git a/sys/arm64/arm64/gicv3_its.c b/sys/arm64/arm64/gicv3_its.c
index 0e2ccb5037ce..d67b19e7d345 100644
--- a/sys/arm64/arm64/gicv3_its.c
+++ b/sys/arm64/arm64/gicv3_its.c
@@ -424,6 +424,52 @@ gicv3_its_cmdq_init(struct gicv3_its_softc *sc)
        gic_its_write_8(sc, GITS_CWRITER, 0x0);
 }
 
+static int
+gicv3_its_table_page_size(struct gicv3_its_softc *sc, int table)
+{
+       uint64_t reg, tmp;
+       int page_size;
+
+       page_size = PAGE_SIZE_64K;
+       reg = gic_its_read_8(sc, GITS_BASER(table));
+
+       while (1) {
+               reg &= GITS_BASER_PSZ_MASK;
+               switch (page_size) {
+               case PAGE_SIZE_4K:      /* 4KB */
+                       reg |= GITS_BASER_PSZ_4K << GITS_BASER_PSZ_SHIFT;
+                       break;
+               case PAGE_SIZE_16K:     /* 16KB */
+                       reg |= GITS_BASER_PSZ_16K << GITS_BASER_PSZ_SHIFT;
+                       break;
+               case PAGE_SIZE_64K:     /* 64KB */
+                       reg |= GITS_BASER_PSZ_64K << GITS_BASER_PSZ_SHIFT;
+                       break;
+               }
+
+               /* Write the new page size */
+               gic_its_write_8(sc, GITS_BASER(table), reg);
+
+               /* Read back to check */
+               tmp = gic_its_read_8(sc, GITS_BASER(table));
+
+               /* The page size is correct */
+               if ((tmp & GITS_BASER_PSZ_MASK) == (reg & GITS_BASER_PSZ_MASK))
+                       return (page_size);
+
+               switch (page_size) {
+               default:
+                       return (-1);
+               case PAGE_SIZE_16K:
+                       page_size = PAGE_SIZE_4K;
+                       break;
+               case PAGE_SIZE_64K:
+                       page_size = PAGE_SIZE_16K;
+                       break;
+               }
+       }
+}
+
 static int
 gicv3_its_table_init(device_t dev, struct gicv3_its_softc *sc)
 {
@@ -460,20 +506,30 @@ gicv3_its_table_init(device_t dev, struct gicv3_its_softc 
*sc)
                cache = GITS_BASER_CACHE_WAWB;
        }
        share = GITS_BASER_SHARE_IS;
-       page_size = PAGE_SIZE_64K;
 
        for (i = 0; i < GITS_BASER_NUM; i++) {
                reg = gic_its_read_8(sc, GITS_BASER(i));
                /* The type of table */
                type = GITS_BASER_TYPE(reg);
+               if (type == GITS_BASER_TYPE_UNIMPL)
+                       continue;
+
                /* The table entry size */
                esize = GITS_BASER_ESIZE(reg);
 
+               /* Find the tables page size */
+               page_size = gicv3_its_table_page_size(sc, i);
+               if (page_size == -1) {
+                       device_printf(dev, "No valid page size for table %d\n",
+                           i);
+                       return (EINVAL);
+               }
+
                switch(type) {
                case GITS_BASER_TYPE_DEV:
                        nidents = (1 << devbits);
                        its_tbl_size = esize * nidents;
-                       its_tbl_size = roundup2(its_tbl_size, PAGE_SIZE_64K);
+                       its_tbl_size = roundup2(its_tbl_size, page_size);
                        break;
                case GITS_BASER_TYPE_VP:
                case GITS_BASER_TYPE_PP: /* Undocumented? */
@@ -540,18 +596,6 @@ gicv3_its_table_init(device_t dev, struct gicv3_its_softc 
*sc)
                                continue;
                        }
 
-                       if ((tmp & GITS_BASER_PSZ_MASK) !=
-                           (reg & GITS_BASER_PSZ_MASK)) {
-                               switch (page_size) {
-                               case PAGE_SIZE_16K:
-                                       page_size = PAGE_SIZE_4K;
-                                       continue;
-                               case PAGE_SIZE_64K:
-                                       page_size = PAGE_SIZE_16K;
-                                       continue;
-                               }
-                       }
-
                        if (tmp != reg) {
                                device_printf(dev, "GITS_BASER%d: "
                                    "unable to be updated: %lx != %lx\n",

Reply via email to