On Fri, Jun 03, 2022 at 04:51:04PM +0530, Vasant Hegde wrote:
> +/* Allocate page table */
> +static u64 *v2_alloc_pte(u64 *pgd, unsigned long iova,
> + unsigned long pg_size, bool *updated)
> +{
> + u64 *pte, *page;
> + int level, end_level;
> +
> + BUG_ON(!is_power_of_2(pg_size));
> +
> + level = get_pgtable_level() - 1;
> + end_level = page_size_to_level(pg_size);
> + pte = &pgd[PM_LEVEL_INDEX(level, iova)];
> + iova = PAGE_SIZE_ALIGN(iova, PAGE_SIZE);
> +
> + while (level >= end_level) {
> + u64 __pte, __npte;
> +
> + __pte = *pte;
> +
> + if (IOMMU_PTE_PRESENT(__pte) && is_large_pte(__pte)) {
> + /* Unmap large pte */
> + cmpxchg64(pte, *pte, 0ULL);
> + *updated = true;
> + continue;
> + }
> +
> + if (!IOMMU_PTE_PRESENT(__pte)) {
> + page = alloc_pgtable_page();
> + if (!page)
> + return NULL;
> +
> + __npte = set_pgtable_attr(page);
> + /* pte could have been changed somewhere. */
> + if (cmpxchg64(pte, __pte, __npte) != __pte)
> + free_pgtable_page(page);
> + else if (IOMMU_PTE_PRESENT(__pte))
> + *updated = true;
> +
> + continue;
> + }
> +
> + level -= 1;
> + pte = get_pgtable_pte(__pte);
> + pte = &pte[PM_LEVEL_INDEX(level, iova)];
> + }
I know that the V1 page-table code also uses loops for the allocation
path, but the main reason there is the variable amount of page-table
levels. The v2 page-tables have a fixed amount levels, so it is better
to unroll this loop here (and other loops iterating over page-table
levels). This makes the code more clear.
_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu