On Tue, May 12, 2026 at 05:05:54PM -0400, Michael S. Tsirkin wrote:
> When post_alloc_hook() needs to zero a page for an explicit
> __GFP_ZERO allocation for a user page (user_addr is set), use 
> folio_zero_user()
> instead of kernel_init_pages().  This zeros near the faulting
> address last, keeping those cachelines hot for the impending
> user access.
> 
> folio_zero_user() is only used for explicit __GFP_ZERO, not for
> init_on_alloc.  On architectures with virtually-indexed caches
> (e.g., ARM), clear_user_highpage() performs per-line cache
> operations; using it for init_on_alloc would add overhead that
> kernel_init_pages() avoids (the page fault path flushes the
> cache at PTE installation time regardless).
> 
> No functional change yet: current callers do not pass __GFP_ZERO
> for user pages (they zero at the callsite instead).  Subsequent
> patches will convert them.
> 
> Signed-off-by: Michael S. Tsirkin <[email protected]>
> Assisted-by: Claude:claude-opus-4-6
> ---
>  mm/page_alloc.c | 17 ++++++++++++++---
>  1 file changed, 14 insertions(+), 3 deletions(-)
> 
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index db387dd6b813..76f39dd026ff 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -1861,9 +1861,20 @@ inline void post_alloc_hook(struct page *page, 
> unsigned int order,
>               for (i = 0; i != 1 << order; ++i)
>                       page_kasan_tag_reset(page + i);
>       }
> -     /* If memory is still not initialized, initialize it now. */
> -     if (init)
> -             kernel_init_pages(page, 1 << order);
> +     /*
> +      * If memory is still not initialized, initialize it now.
> +      * When __GFP_ZERO was explicitly requested and user_addr is set,
> +      * use folio_zero_user() which zeros near the faulting address
> +      * last, keeping those cachelines hot.  For init_on_alloc, use
> +      * kernel_init_pages() to avoid unnecessary cache flush overhead
> +      * on architectures with virtually-indexed caches.
> +      */
> +     if (init) {
> +             if ((gfp_flags & __GFP_ZERO) && user_addr != USER_ADDR_NONE)
> +                     folio_zero_user(page_folio(page), user_addr);
> +             else
> +                     kernel_init_pages(page, 1 << order);
> +     }

Open question but not necessarily in-scope:

Should __GFP_ZERO just be implied if (user_addr != USER_ADDR_NONE)?

Putting aside how that's done without introducing another gfp flag
(maybe something explicit like `alloc_pages_nozero(...)` ), it seems
like a very short jump to just adding __GFP_ZERO to any user-alloc by
default.

I'd be curious to know how many callers across the system omit
__GFP_ZERO when allocating a user-page, and whether there might be
scenarios where we subtly miss it (seems unlikely and narrow, but very
possibly something a driver could do unintentionally).

~Gregory

Reply via email to