[PATCH v2 4/6] drm/pagemap: Allocate folios when possible

Matthew Brost matthew.brost at intel.com
Tue Jul 29 06:15:52 UTC 2025


On Mon, Jul 28, 2025 at 12:18:26PM +0200, Francois Dugast wrote:
> On Fri, Jul 25, 2025 at 02:43:48PM -0700, Matthew Brost wrote:
> > On Fri, Jul 25, 2025 at 05:39:28PM +0200, Francois Dugast wrote:
> > > If the order is greater than zero, allocate a folio when populating the
> > > RAM PFNs instead of allocating individual pages one after the other. For
> > > example if 2MB folios are used instead of 4KB pages, this reduces the
> > > number of calls to the allocation API by 512.
> > > 
> > > v2:
> > > - Use page order instead of extr argument (Matthew Brost)
> > > - Allocate with folio_alloc() (Matthew Brost)
> > > - Loop for mpages and free_pages based on order (Matthew Brost)
> > > 
> > > Signed-off-by: Francois Dugast <francois.dugast at intel.com>
> > > Cc: Matthew Brost <matthew.brost at intel.com>
> > > ---
> > >  drivers/gpu/drm/drm_pagemap.c | 38 ++++++++++++++++++++++++++---------
> > >  1 file changed, 28 insertions(+), 10 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_pagemap.c b/drivers/gpu/drm/drm_pagemap.c
> > > index b6f5d3a8e445..38753ce2bca7 100644
> > > --- a/drivers/gpu/drm/drm_pagemap.c
> > > +++ b/drivers/gpu/drm/drm_pagemap.c
> > > @@ -458,54 +458,72 @@ static int drm_pagemap_migrate_populate_ram_pfn(struct vm_area_struct *vas,
> > >  {
> > >  	unsigned long i;
> > >  
> > > -	for (i = 0; i < npages; ++i, addr += PAGE_SIZE) {
> > > +	for (i = 0; i < npages;) {
> > >  		struct page *page, *src_page;
> > > +		unsigned int order;
> > > +		struct folio *folio;
> > >  
> > >  		if (!(src_mpfn[i] & MIGRATE_PFN_MIGRATE))
> > > -			continue;
> > > +			goto next;
> > >  
> > >  		src_page = migrate_pfn_to_page(src_mpfn[i]);
> > >  		if (!src_page)
> > > -			continue;
> > > +			goto next;
> > >  
> > >  		if (fault_page) {
> > >  			if (src_page->zone_device_data !=
> > >  			    fault_page->zone_device_data)
> > > -				continue;
> > > +				goto next;
> > >  		}
> > >  
> > > +		order = folio_order(page_folio(src_page));
> > > +
> > > +		/* TODO: Support fallback to single pages if THP allocation fails */
> > >  		if (vas)
> > > -			page = alloc_page_vma(GFP_HIGHUSER, vas, addr);
> > > +			folio = vma_alloc_folio(GFP_HIGHUSER, order, vas, addr);
> > >  		else
> > > -			page = alloc_page(GFP_HIGHUSER);
> > > +			folio = folio_alloc(GFP_HIGHUSER, order);
> > 
> > I haven't checked but I assume if order == 0, then alloc_page_vma ==
> > vma_alloc_folio? So goes for alloc_page / folio_alloc. If so, then this
> > looks good.
> 
> Yes according to include/linux/gfp.h:
> - alloc_page_vma()->alloc_page_vma_noprof()->vma_alloc_folio_noprof(order=0)
> - vma_alloc_folio()->vma_alloc_folio_noprof(order)
> 
> > 
> > >  
> > > -		if (!page)
> > > +		if (!folio)
> > >  			goto free_pages;
> > >  
> > > +		page = folio_page(folio, 0);
> > >  		mpfn[i] = migrate_pfn(page_to_pfn(page));
> > > +
> > > +next:
> > > +		addr += page_size(page);
> > > +		i += NR_PAGES(order);
> > >  	}
> > >  
> > > -	for (i = 0; i < npages; ++i) {
> > > +	for (i = 0; i < npages;) {
> > >  		struct page *page = migrate_pfn_to_page(mpfn[i]);
> > > +		unsigned int order;
> > 
> > unsigned int order = 0;
> > 
> > >  
> > >  		if (!page)
> > >  			continue;
> > 
> > s/continue/goto next;
> > 
> > 
> > >  
> > >  		WARN_ON_ONCE(!trylock_page(page));
> > > -		++*mpages;
> > > +
> > > +		order = folio_order(page_folio(page));
> > 
> > next:
> > 
> > > +		*mpages += NR_PAGES(order);

Opps, next should only increment the loop variable.

Matt

> > > +		i += NR_PAGES(order);
> > >  	}
> > >  
> > >  	return 0;
> > >  
> > >  free_pages:
> > > -	for (i = 0; i < npages; ++i) {
> > > +	for (i = 0; i < npages;) {
> > 
> > Same logic changes to this loop as the one above.
> 
> Will fix.
> 
> Francois
> 
> > 
> > Matt
> > 
> > >  		struct page *page = migrate_pfn_to_page(mpfn[i]);
> > > +		unsigned int order;
> > >  
> > >  		if (!page)
> > >  			continue;
> > >  
> > >  		put_page(page);
> > >  		mpfn[i] = 0;
> > > +
> > > +		order = folio_order(page_folio(page));
> > > +		i += NR_PAGES(order);
> > >  	}
> > >  	return -ENOMEM;
> > >  }
> > > -- 
> > > 2.43.0
> > > 


More information about the Intel-xe mailing list