Page MenuHomeFreeBSD

D47819.id147082.diff
No OneTemporary

D47819.id147082.diff

diff --git a/sys/arm64/arm64/gicv3_its.c b/sys/arm64/arm64/gicv3_its.c
--- a/sys/arm64/arm64/gicv3_its.c
+++ b/sys/arm64/arm64/gicv3_its.c
@@ -505,7 +505,7 @@
uint64_t cache, reg, share, tmp, type;
size_t its_tbl_size, nitspages, npages;
size_t l1_esize, l2_esize, l1_nidents, l2_nidents;
- int i, page_size;
+ int i, gic_page_size;
int devbits;
bool indirect;
@@ -531,7 +531,16 @@
devbits = 20;
cache = 0;
} else {
- devbits = GITS_TYPER_DEVB(gic_its_read_8(sc, GITS_TYPER));
+ /*
+ * ARM IHI 0069G page 12-835:
+ *
+ * Devbits, bits [17:13]
+ * The number of DeviceID bits implemented, minus one.
+ *
+ * A page break before "minus one" would have been a great
+ * homage to the Staff or Ra in Raiders of the lost Ark.
+ */
+ devbits = GITS_TYPER_DEVB(gic_its_read_8(sc, GITS_TYPER)) + 1;
cache = GITS_BASER_CACHE_WAWB;
}
sc->sc_devbits = devbits;
@@ -548,8 +557,8 @@
l1_esize = GITS_BASER_ESIZE(reg);
/* Find the tables page size */
- page_size = gicv3_its_table_page_size(sc, i);
- if (page_size == -1) {
+ gic_page_size = gicv3_its_table_page_size(sc, i);
+ if (gic_page_size == -1) {
device_printf(dev, "No valid page size for table %d\n",
i);
return (EINVAL);
@@ -565,30 +574,31 @@
"Warning: Multiple device tables found\n");
sc->sc_dev_table_idx = i;
- l1_nidents = (1 << devbits);
- if ((l1_esize * l1_nidents) > (page_size * 2)) {
- indirect =
- gicv3_its_table_supports_indirect(sc, i);
- if (indirect) {
- /*
- * Each l1 entry is 8 bytes and points
- * to an l2 table of size page_size.
- * Calculate how many entries this is
- * and use this to find how many
- * 8 byte l1 idents we need.
- */
- l2_esize = l1_esize;
- l2_nidents = page_size / l2_esize;
- l1_nidents = l1_nidents / l2_nidents;
- l1_esize = GITS_INDIRECT_L1_ESIZE;
- }
+
+ /* Total address space required */
+ tmp = l1_esize << devbits;
+
+ /*
+ * It is hard to imagine a system where the total
+ * size would come out to just one or two VM pages,
+ * but just in case...
+ */
+ if (howmany(tmp, PAGE_SIZE) > 2 &&
+ gicv3_its_table_supports_indirect(sc, i)) {
+ indirect = true;
+ l2_esize = l1_esize;
+ l2_nidents = gic_page_size / l2_esize;
+ l1_nidents = tmp / gic_page_size;
+ l1_esize = GITS_INDIRECT_L1_ESIZE;
+ } else {
+ l1_nidents = (1ULL << devbits);
}
its_tbl_size = l1_esize * l1_nidents;
- its_tbl_size = roundup2(its_tbl_size, page_size);
+ its_tbl_size = howmany(its_tbl_size, gic_page_size);
break;
case GITS_BASER_TYPE_PP: /* Undocumented? */
case GITS_BASER_TYPE_IC:
- its_tbl_size = page_size;
+ its_tbl_size = gic_page_size;
break;
case GITS_BASER_TYPE_VP:
/*
@@ -606,26 +616,26 @@
type);
continue;
}
- npages = howmany(its_tbl_size, PAGE_SIZE);
+ npages = howmany(its_tbl_size * gic_page_size, PAGE_SIZE);
/* Allocate the table */
table = contigmalloc_domainset(npages * PAGE_SIZE,
M_GICV3_ITS, sc->sc_ds, M_WAITOK | M_ZERO, 0,
- (1ul << 48) - 1, PAGE_SIZE_64K, 0);
+ (1ul << 48) - 1, gic_page_size, 0);
sc->sc_its_ptab[i].ptab_vaddr = table;
sc->sc_its_ptab[i].ptab_l1_size = its_tbl_size;
sc->sc_its_ptab[i].ptab_l1_nidents = l1_nidents;
- sc->sc_its_ptab[i].ptab_l2_size = page_size;
+ sc->sc_its_ptab[i].ptab_l2_size = gic_page_size;
sc->sc_its_ptab[i].ptab_l2_nidents = l2_nidents;
sc->sc_its_ptab[i].ptab_indirect = indirect;
- sc->sc_its_ptab[i].ptab_page_size = page_size;
+ sc->sc_its_ptab[i].ptab_page_size = gic_page_size;
paddr = vtophys(table);
while (1) {
- nitspages = howmany(its_tbl_size, page_size);
+ nitspages = howmany(its_tbl_size, gic_page_size);
/* Clear the fields we will be setting */
reg &= ~(GITS_BASER_VALID | GITS_BASER_INDIRECT |
@@ -641,7 +651,7 @@
paddr | (share << GITS_BASER_SHARE_SHIFT) |
(nitspages - 1);
- switch (page_size) {
+ switch (gic_page_size) {
case PAGE_SIZE_4K: /* 4KB */
reg |=
GITS_BASER_PSZ_4K << GITS_BASER_PSZ_SHIFT;
@@ -669,11 +679,12 @@
continue;
}
- if (tmp != reg) {
+ /* The cache bits may not be writable */
+ if ((tmp ^ reg) & ~GITS_BASER_CACHE_MASK) {
device_printf(dev, "GITS_BASER%d: "
- "unable to be updated: %lx != %lx\n",
- i, reg, tmp);
- return (ENXIO);
+ "unable to be updated: %lx != %lx (%lx %lx)\n",
+ i, reg, tmp, (tmp ^ reg), (tmp ^ reg) & ~GITS_BASER_CACHE_MASK);
+ // return (ENXIO);
}
sc->sc_its_ptab[i].ptab_share = share;

File Metadata

Mime Type
text/plain
Expires
Thu, Dec 12, 8:03 AM (4 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14914465
Default Alt Text
D47819.id147082.diff (4 KB)

Event Timeline