Reviewed-by: "Mitchell Augustin" <mitchell.augustin@xxxxxxxxxxxxx> Tested-by: "Mitchell Augustin" <mitchell.augustin@xxxxxxxxxxxxx> On Wed, Feb 5, 2025 at 5:18 PM Alex Williamson <alex.williamson@xxxxxxxxxx> wrote: > > follow_pfnmap_start() walks the page table for a given address and > fills out the struct follow_pfnmap_args in pfnmap_args_setup(). > The page mask of the page table level is already provided to this > latter function for calculating the pfn. This page mask can also be > useful for the caller to determine the extent of the contiguous > mapping. > > For example, vfio-pci now supports huge_fault for pfnmaps and is able > to insert pud and pmd mappings. When we DMA map these pfnmaps, ex. > PCI MMIO BARs, we iterate follow_pfnmap_start() to get each pfn to test > for a contiguous pfn range. Providing the mapping page mask allows us > to skip the extent of the mapping level. Assuming a 1GB pud level and > 4KB page size, iterations are reduced by a factor of 256K. In wall > clock time, mapping a 32GB PCI BAR is reduced from ~1s to <1ms. > > Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> > Cc: linux-mm@xxxxxxxxx > Signed-off-by: Alex Williamson <alex.williamson@xxxxxxxxxx> > --- > include/linux/mm.h | 2 ++ > mm/memory.c | 1 + > 2 files changed, 3 insertions(+) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index b1c3db9cf355..0ef7e7a0b4eb 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2416,11 +2416,13 @@ struct follow_pfnmap_args { > * Outputs: > * > * @pfn: the PFN of the address > + * @pgmask: page mask covering pfn > * @pgprot: the pgprot_t of the mapping > * @writable: whether the mapping is writable > * @special: whether the mapping is a special mapping (real PFN maps) > */ > unsigned long pfn; > + unsigned long pgmask; > pgprot_t pgprot; > bool writable; > bool special; > diff --git a/mm/memory.c b/mm/memory.c > index 398c031be9ba..97ccd43761b2 100644 > --- a/mm/memory.c > +++ b/mm/memory.c > @@ -6388,6 +6388,7 @@ static inline void pfnmap_args_setup(struct follow_pfnmap_args *args, > args->lock = lock; > args->ptep = ptep; > args->pfn = pfn_base + ((args->address & ~addr_mask) >> PAGE_SHIFT); > + args->pgmask = addr_mask; > args->pgprot = pgprot; > args->writable = writable; > args->special = special; > -- > 2.47.1 > -- Mitchell Augustin Software Engineer - Ubuntu Partner Engineering