Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F104979922
D47819.id147082.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D47819.id147082.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D47819: ARM64 GICv3: Fix device table size calculation
Attached
Detach File
Event Timeline
Log In to Comment