git: 90ab0c7356b6 - stable/13 - gicv3: Split out finding the page size
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 25 Sep 2023 11:01:13 UTC
The branch stable/13 has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=90ab0c7356b648584303a26b75b3ee793c27436f
commit 90ab0c7356b648584303a26b75b3ee793c27436f
Author: Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2023-08-22 10:51:26 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2023-09-25 10:50:14 +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
(cherry picked from commit 3fc4f7c88085dc94c88348839074b8db6f19fae1)
---
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 677e40877ac9..2747bf7f4ce3 100644
--- a/sys/arm64/arm64/gicv3_its.c
+++ b/sys/arm64/arm64/gicv3_its.c
@@ -421,6 +421,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)
{
@@ -457,20 +503,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? */
@@ -537,18 +593,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",