iommu/io-pgtable-arm: Simplify level indexing

The nature of the LPAE format means that data->pg_shift is always
redundant with data->bits_per_level, since they represent the size of a
page and the number of PTEs per page respectively, and the size of a PTE
is constant. Thus it works out more efficient to only store the latter,
and derive the former via a trivial addition where necessary.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
[will: Reworked granule check in iopte_to_paddr()]
Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
Robin Murphy 2019-10-25 19:08:35 +01:00 committed by Will Deacon
parent c79278c185
commit 5fb190b0b5

View file

@ -36,10 +36,11 @@
* in a virtual address mapped by the pagetable in d. * in a virtual address mapped by the pagetable in d.
*/ */
#define ARM_LPAE_LVL_SHIFT(l,d) \ #define ARM_LPAE_LVL_SHIFT(l,d) \
(((ARM_LPAE_MAX_LEVELS - 1 - (l)) * (d)->bits_per_level) + \ (((ARM_LPAE_MAX_LEVELS - (l)) * (d)->bits_per_level) + \
(d)->pg_shift) ilog2(sizeof(arm_lpae_iopte)))
#define ARM_LPAE_GRANULE(d) (1UL << (d)->pg_shift) #define ARM_LPAE_GRANULE(d) \
(sizeof(arm_lpae_iopte) << (d)->bits_per_level)
#define ARM_LPAE_PGD_SIZE(d) \ #define ARM_LPAE_PGD_SIZE(d) \
(sizeof(arm_lpae_iopte) << (d)->pgd_bits) (sizeof(arm_lpae_iopte) << (d)->pgd_bits)
@ -55,9 +56,7 @@
((1 << ((d)->bits_per_level + ARM_LPAE_PGD_IDX(l,d))) - 1)) ((1 << ((d)->bits_per_level + ARM_LPAE_PGD_IDX(l,d))) - 1))
/* Calculate the block/page mapping size at level l for pagetable in d. */ /* Calculate the block/page mapping size at level l for pagetable in d. */
#define ARM_LPAE_BLOCK_SIZE(l,d) \ #define ARM_LPAE_BLOCK_SIZE(l,d) (1ULL << ARM_LPAE_LVL_SHIFT(l,d))
(1ULL << (ilog2(sizeof(arm_lpae_iopte)) + \
((ARM_LPAE_MAX_LEVELS - (l)) * (d)->bits_per_level)))
/* Page table bits */ /* Page table bits */
#define ARM_LPAE_PTE_TYPE_SHIFT 0 #define ARM_LPAE_PTE_TYPE_SHIFT 0
@ -175,8 +174,7 @@ struct arm_lpae_io_pgtable {
int pgd_bits; int pgd_bits;
int start_level; int start_level;
unsigned long pg_shift; int bits_per_level;
unsigned long bits_per_level;
void *pgd; void *pgd;
}; };
@ -206,7 +204,7 @@ static phys_addr_t iopte_to_paddr(arm_lpae_iopte pte,
{ {
u64 paddr = pte & ARM_LPAE_PTE_ADDR_MASK; u64 paddr = pte & ARM_LPAE_PTE_ADDR_MASK;
if (data->pg_shift < 16) if (ARM_LPAE_GRANULE(data) < SZ_64K)
return paddr; return paddr;
/* Rotate the packed high-order bits back to the top */ /* Rotate the packed high-order bits back to the top */
@ -742,9 +740,8 @@ static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)
static struct arm_lpae_io_pgtable * static struct arm_lpae_io_pgtable *
arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg) arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
{ {
unsigned long va_bits;
struct arm_lpae_io_pgtable *data; struct arm_lpae_io_pgtable *data;
int levels; int levels, va_bits, pg_shift;
arm_lpae_restrict_pgsizes(cfg); arm_lpae_restrict_pgsizes(cfg);
@ -766,10 +763,10 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
if (!data) if (!data)
return NULL; return NULL;
data->pg_shift = __ffs(cfg->pgsize_bitmap); pg_shift = __ffs(cfg->pgsize_bitmap);
data->bits_per_level = data->pg_shift - ilog2(sizeof(arm_lpae_iopte)); data->bits_per_level = pg_shift - ilog2(sizeof(arm_lpae_iopte));
va_bits = cfg->ias - data->pg_shift; va_bits = cfg->ias - pg_shift;
levels = DIV_ROUND_UP(va_bits, data->bits_per_level); levels = DIV_ROUND_UP(va_bits, data->bits_per_level);
data->start_level = ARM_LPAE_MAX_LEVELS - levels; data->start_level = ARM_LPAE_MAX_LEVELS - levels;
@ -1135,9 +1132,9 @@ static void __init arm_lpae_dump_ops(struct io_pgtable_ops *ops)
pr_err("cfg: pgsize_bitmap 0x%lx, ias %u-bit\n", pr_err("cfg: pgsize_bitmap 0x%lx, ias %u-bit\n",
cfg->pgsize_bitmap, cfg->ias); cfg->pgsize_bitmap, cfg->ias);
pr_err("data: %d levels, 0x%zx pgd_size, %lu pg_shift, %lu bits_per_level, pgd @ %p\n", pr_err("data: %d levels, 0x%zx pgd_size, %u pg_shift, %u bits_per_level, pgd @ %p\n",
ARM_LPAE_MAX_LEVELS - data->start_level, ARM_LPAE_PGD_SIZE(data), ARM_LPAE_MAX_LEVELS - data->start_level, ARM_LPAE_PGD_SIZE(data),
data->pg_shift, data->bits_per_level, data->pgd); ilog2(ARM_LPAE_GRANULE(data)), data->bits_per_level, data->pgd);
} }
#define __FAIL(ops, i) ({ \ #define __FAIL(ops, i) ({ \