Skip to content

Commit e7d6fff

Browse files
willdeaconjoergroedel
authored andcommitted
iommu: Use bitmap to calculate page size in iommu_pgsize()
Avoid the potential for shifting values by amounts greater than the width of their type by using a bitmap to compute page size in iommu_pgsize(). Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Isaac J. Manjarres <[email protected]> Signed-off-by: Georgi Djakov <[email protected]> Reviewed-by: Lu Baolu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 910c440 commit e7d6fff

File tree

1 file changed

+12
-19
lines changed

1 file changed

+12
-19
lines changed

drivers/iommu/iommu.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <linux/device.h>
1010
#include <linux/kernel.h>
11+
#include <linux/bits.h>
1112
#include <linux/bug.h>
1213
#include <linux/types.h>
1314
#include <linux/init.h>
@@ -2378,30 +2379,22 @@ static size_t iommu_pgsize(struct iommu_domain *domain,
23782379
unsigned long addr_merge, size_t size)
23792380
{
23802381
unsigned int pgsize_idx;
2382+
unsigned long pgsizes;
23812383
size_t pgsize;
23822384

2383-
/* Max page size that still fits into 'size' */
2384-
pgsize_idx = __fls(size);
2385+
/* Page sizes supported by the hardware and small enough for @size */
2386+
pgsizes = domain->pgsize_bitmap & GENMASK(__fls(size), 0);
23852387

2386-
/* need to consider alignment requirements ? */
2387-
if (likely(addr_merge)) {
2388-
/* Max page size allowed by address */
2389-
unsigned int align_pgsize_idx = __ffs(addr_merge);
2390-
pgsize_idx = min(pgsize_idx, align_pgsize_idx);
2391-
}
2392-
2393-
/* build a mask of acceptable page sizes */
2394-
pgsize = (1UL << (pgsize_idx + 1)) - 1;
2395-
2396-
/* throw away page sizes not supported by the hardware */
2397-
pgsize &= domain->pgsize_bitmap;
2388+
/* Constrain the page sizes further based on the maximum alignment */
2389+
if (likely(addr_merge))
2390+
pgsizes &= GENMASK(__ffs(addr_merge), 0);
23982391

2399-
/* make sure we're still sane */
2400-
BUG_ON(!pgsize);
2392+
/* Make sure we have at least one suitable page size */
2393+
BUG_ON(!pgsizes);
24012394

2402-
/* pick the biggest page */
2403-
pgsize_idx = __fls(pgsize);
2404-
pgsize = 1UL << pgsize_idx;
2395+
/* Pick the biggest page size remaining */
2396+
pgsize_idx = __fls(pgsizes);
2397+
pgsize = BIT(pgsize_idx);
24052398

24062399
return pgsize;
24072400
}

0 commit comments

Comments
 (0)