Re: [PATCH v2 1/2] arm64: mmu: don't allocate page while spliting linear mapping

Yeoreum Yun
2025-12-18T15:55:50Z

> On 18/12/2025 15:01, Yeoreum Yun wrote:
> > Hi Ryan,
> >
> >> On 17/12/2025 18:20, Yeoreum Yun wrote:
> >>> Current linear_map_split_to_ptes() allocate the pagetable
> >>> while split linear mapping to ptes by stop_machine() with GFP_ATOMIC.
> >>>
> >>> This is fine for non-PREEMPR_RT case.
> >>> However It's a problem in PREEMPR_RT case since
> >>> generic memory allocation/free APIs (e.x) pgtable_alloc(), __get_free_pages and etc
> >>> couldn't be called in non-preemptible context except _nolock() APIs
> >>> since generic memory allocation/free APIs are *sleepable* for using *spin_lock()*
> >>>
> >>> IOW, calling a pgtable_alloc() even with GFP_ATOMIC
> >>> doesn't allow in __linear_map_split_to_pte() executed by stopper thread
> >>> where preemption is disabled in PREEMPR_RT.
> >>>
> >>> To address this, divide linear_map_maybe_split_ptes:
> >>> - collect number of pages to require for spliting.
> >>> - allocate the required number of pages for spliting.
> >>> - with pre-allocate page, split the linear map.
> >>
> >> Thanks for working on this fix!
> >>
> >> First some high level comments: I'm not a huge fan of the approach with the
> >> different modes to modify behaviour.
> >>
> >> For the first step of figuring out the number of pages required; there is no
> >> need to be inside stop_machine() for that. Can should be able to just walk the
> >> linear map without any locking since it is created once and remains static, with
> >> the exception of hotplug, but that is not enabled yet.
> >>
> >> I think it would be cleaner to just create separate walker callbacks rather than
> >> repurpose the existing walker.
> >
> > Okay. I'll repsin with separate walker.
> >
> >>
> >> Then you could simply change the gfp flag to a callback function pointer and
> >> pass the desired allocator as a function pointer. This would match the existing
> >> patterns used in mmu.c today.
> >>
> >> The preallocated page list could be stored in a global static variable and you
> >> could create an allocation function that just strims a page from that list. See
> >> kpti_ng_pgd_alloc() for an existing example. That assumes a contiguous block,
> >> but you could generalize it to hold a list of struct pages and reuse it for both
> >> cases?
> >
> > If we use walker callbacks, I think it not only pass the callback
> > function, but it need to pass the gfp flag too since split_xxx() is
> > called by another functions. (i.e) set_memory_xxx()
> >
> > I think I can remove the mode with the suggestion of @David
> > but, I think it would be still use split_args with information of
> > gfp and preallocate buffer.
>
> I don't think that's necessary; all other users pass GFP_PGTABLE_KERNEL, so we
> just need one allocator function that allocates with GFP_PGTABLE_KERNEL and
> another allocator function that allocates from the prealloc'ed list. Then the
> user passes the function they want to use.
>
> That would work, I think?

True. I forgot I removed GFP_ATOMIC myself for pgtable alloc.
Okay. then I'll move the preallocated buffer information to global
and just pass function pointer then.

Thanks

--
Sincerely,
Yeoreum Yun