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 iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu