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 <will@kernel.org> Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org> Signed-off-by: Georgi Djakov <quic_c_gdjako@quicinc.com> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> Link: https://lore.kernel.org/r/1623850736-389584-6-git-send-email-quic_c_gdjako@quicinc.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
910c4406cc
commit
e7d6fff6b3
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/bits.h>
|
||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -2378,30 +2379,22 @@ static size_t iommu_pgsize(struct iommu_domain *domain,
|
||||||
unsigned long addr_merge, size_t size)
|
unsigned long addr_merge, size_t size)
|
||||||
{
|
{
|
||||||
unsigned int pgsize_idx;
|
unsigned int pgsize_idx;
|
||||||
|
unsigned long pgsizes;
|
||||||
size_t pgsize;
|
size_t pgsize;
|
||||||
|
|
||||||
/* Max page size that still fits into 'size' */
|
/* Page sizes supported by the hardware and small enough for @size */
|
||||||
pgsize_idx = __fls(size);
|
pgsizes = domain->pgsize_bitmap & GENMASK(__fls(size), 0);
|
||||||
|
|
||||||
/* need to consider alignment requirements ? */
|
/* Constrain the page sizes further based on the maximum alignment */
|
||||||
if (likely(addr_merge)) {
|
if (likely(addr_merge))
|
||||||
/* Max page size allowed by address */
|
pgsizes &= GENMASK(__ffs(addr_merge), 0);
|
||||||
unsigned int align_pgsize_idx = __ffs(addr_merge);
|
|
||||||
pgsize_idx = min(pgsize_idx, align_pgsize_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build a mask of acceptable page sizes */
|
/* Make sure we have at least one suitable page size */
|
||||||
pgsize = (1UL << (pgsize_idx + 1)) - 1;
|
BUG_ON(!pgsizes);
|
||||||
|
|
||||||
/* throw away page sizes not supported by the hardware */
|
/* Pick the biggest page size remaining */
|
||||||
pgsize &= domain->pgsize_bitmap;
|
pgsize_idx = __fls(pgsizes);
|
||||||
|
pgsize = BIT(pgsize_idx);
|
||||||
/* make sure we're still sane */
|
|
||||||
BUG_ON(!pgsize);
|
|
||||||
|
|
||||||
/* pick the biggest page */
|
|
||||||
pgsize_idx = __fls(pgsize);
|
|
||||||
pgsize = 1UL << pgsize_idx;
|
|
||||||
|
|
||||||
return pgsize;
|
return pgsize;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue