Re: [PATCH v7 09/31] mm: use folio_zero_user for user pages in post_alloc_hook
From: Gregory Price
Date: Thu May 14 2026 - 09:53:53 EST
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 <mst@xxxxxxxxxx>
> 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