Skip to content

Commit eb6c976

Browse files
rmurphy-armwilldeacon
authored andcommitted
iommu/arm-smmu-v3: Avoid constructing invalid range commands
Although io-pgtable's non-leaf invalidations are always for full tables, I missed that SVA also uses non-leaf invalidations, while being at the mercy of whatever range the MMU notifier throws at it. This means it definitely wants the previous TTL fix as well, since it also doesn't know exactly which leaf level(s) may need invalidating, but it can also give us less-aligned ranges wherein certain corners may lead to building an invalid command where TTL, Num and Scale are all 0. It should be fine to handle this by over-invalidating an extra page, since falling back to a non-range command opens up a whole can of errata-flavoured worms. Fixes: 6833b8f ("iommu/arm-smmu-v3: Set TTL invalidation hint better") Reported-by: Rui Zhu <zhurui3@huawei.com> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/b99cfe71af2bd93a8a2930f20967fb2a4f7748dd.1694432734.git.robin.murphy@arm.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 0bb80ec commit eb6c976

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,18 +1895,23 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
18951895
/* Get the leaf page size */
18961896
tg = __ffs(smmu_domain->domain.pgsize_bitmap);
18971897

1898+
num_pages = size >> tg;
1899+
18981900
/* Convert page size of 12,14,16 (log2) to 1,2,3 */
18991901
cmd->tlbi.tg = (tg - 10) / 2;
19001902

19011903
/*
1902-
* Determine what level the granule is at. For non-leaf, io-pgtable
1903-
* assumes .tlb_flush_walk can invalidate multiple levels at once,
1904-
* so ignore the nominal last-level granule and leave TTL=0.
1904+
* Determine what level the granule is at. For non-leaf, both
1905+
* io-pgtable and SVA pass a nominal last-level granule because
1906+
* they don't know what level(s) actually apply, so ignore that
1907+
* and leave TTL=0. However for various errata reasons we still
1908+
* want to use a range command, so avoid the SVA corner case
1909+
* where both scale and num could be 0 as well.
19051910
*/
19061911
if (cmd->tlbi.leaf)
19071912
cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));
1908-
1909-
num_pages = size >> tg;
1913+
else if ((num_pages & CMDQ_TLBI_RANGE_NUM_MAX) == 1)
1914+
num_pages++;
19101915
}
19111916

19121917
cmds.num = 0;

0 commit comments

Comments
 (0)