The current __kpti_install_ng_mappings() allocates a temporary PGD
while installing the NG mapping for KPTI under stop_machine(),
using GFP_ATOMIC.
This is fine in the non-PREEMPT_RT case. However, it becomes a problem
under PREEMPT_RT because generic memory allocation/free APIs
(e.g., pgtable_alloc(), __get_free_pages(), etc.) cannot be invoked
in a non-preemptible context, except for the *_nolock() variants.
These generic allocators may sleep due to their use of spin_lock().
In other words, calling __get_free_pages(), even with GFP_ATOMIC,
is not allowed in __kpti_install_ng_mappings(), which is executed by
the stopper thread where preemption is disabled under PREEMPT_RT.
To address this, preallocate the page needed for the temporary PGD
before invoking __kpti_install_ng_mappings() via stop_machine().
Fixes: 47546a1912fc ("arm64: mm: install KPTI nG mappings with MMU enabled")
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
---
arch/arm64/mm/mmu.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index e4e6c7e0a016..69d9651de0cd 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1360,7 +1360,7 @@ static phys_addr_t __init kpti_ng_pgd_alloc(enum pgtable_type type)
return kpti_ng_temp_alloc;
}
-static int __init __kpti_install_ng_mappings(void *__unused)
+static int __init __kpti_install_ng_mappings(void *data)
{
typedef void (kpti_remap_fn)(int, int, phys_addr_t, unsigned long);
extern kpti_remap_fn idmap_kpti_install_ng_mappings;
@@ -1368,10 +1368,9 @@ static int __init __kpti_install_ng_mappings(void *__unused)
int cpu = smp_processor_id();
int levels = CONFIG_PGTABLE_LEVELS;
- int order = order_base_2(levels);
u64 kpti_ng_temp_pgd_pa = 0;
pgd_t *kpti_ng_temp_pgd;
- u64 alloc = 0;
+ u64 alloc = *(u64 *)data;
if (levels == 5 && !pgtable_l5_enabled())
levels = 4;
@@ -1382,8 +1381,6 @@ static int __init __kpti_install_ng_mappings(void *__unused)
if (!cpu) {
int ret;
-
- alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
kpti_ng_temp_pgd = (pgd_t *)(alloc + (levels - 1) * PAGE_SIZE);
kpti_ng_temp_alloc = kpti_ng_temp_pgd_pa = __pa(kpti_ng_temp_pgd);
@@ -1414,16 +1411,17 @@ static int __init __kpti_install_ng_mappings(void *__unused)
remap_fn(cpu, num_online_cpus(), kpti_ng_temp_pgd_pa, KPTI_NG_TEMP_VA);
cpu_uninstall_idmap();
- if (!cpu) {
- free_pages(alloc, order);
+ if (!cpu)
arm64_use_ng_mappings = true;
- }
return 0;
}
void __init kpti_install_ng_mappings(void)
{
+ int order = order_base_2(CONFIG_PGTABLE_LEVELS);
+ u64 alloc;
+
/* Check whether KPTI is going to be used */
if (!arm64_kernel_unmapped_at_el0())
return;
@@ -1436,8 +1434,14 @@ void __init kpti_install_ng_mappings(void)
if (arm64_use_ng_mappings)
return;
+ alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
+ if (!alloc)
+ panic("Failed to alloc page tables\n");
+
init_idmap_kpti_bbml2_flag();
- stop_machine(__kpti_install_ng_mappings, NULL, cpu_online_mask);
+ stop_machine(__kpti_install_ng_mappings, &alloc, cpu_online_mask);
+
+ free_pages(alloc, order);
}
static pgprot_t __init kernel_exec_prot(void)
--
LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
On 17/12/2025 18:20, Yeoreum Yun wrote:
> The current __kpti_install_ng_mappings() allocates a temporary PGD
> while installing the NG mapping for KPTI under stop_machine(),
> using GFP_ATOMIC.
>
> This is fine in the non-PREEMPT_RT case. However, it becomes a problem
> under PREEMPT_RT because generic memory allocation/free APIs
> (e.g., pgtable_alloc(), __get_free_pages(), etc.) cannot be invoked
> in a non-preemptible context, except for the *_nolock() variants.
> These generic allocators may sleep due to their use of spin_lock().
>
> In other words, calling __get_free_pages(), even with GFP_ATOMIC,
> is not allowed in __kpti_install_ng_mappings(), which is executed by
> the stopper thread where preemption is disabled under PREEMPT_RT.
>
> To address this, preallocate the page needed for the temporary PGD
> before invoking __kpti_install_ng_mappings() via stop_machine().
>
> Fixes: 47546a1912fc ("arm64: mm: install KPTI nG mappings with MMU enabled")
> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> ---
> arch/arm64/mm/mmu.c | 22 +++++++++++++---------
> 1 file changed, 13 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index e4e6c7e0a016..69d9651de0cd 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -1360,7 +1360,7 @@ static phys_addr_t __init kpti_ng_pgd_alloc(enum pgtable_type type)
> return kpti_ng_temp_alloc;
> }
>
> -static int __init __kpti_install_ng_mappings(void *__unused)
> +static int __init __kpti_install_ng_mappings(void *data)
> {
> typedef void (kpti_remap_fn)(int, int, phys_addr_t, unsigned long);
> extern kpti_remap_fn idmap_kpti_install_ng_mappings;
> @@ -1368,10 +1368,9 @@ static int __init __kpti_install_ng_mappings(void *__unused)
>
> int cpu = smp_processor_id();
> int levels = CONFIG_PGTABLE_LEVELS;
> - int order = order_base_2(levels);
> u64 kpti_ng_temp_pgd_pa = 0;
> pgd_t *kpti_ng_temp_pgd;
> - u64 alloc = 0;
> + u64 alloc = *(u64 *)data;
>
> if (levels == 5 && !pgtable_l5_enabled())
> levels = 4;
> @@ -1382,8 +1381,6 @@ static int __init __kpti_install_ng_mappings(void *__unused)
>
> if (!cpu) {
> int ret;
> -
> - alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
> kpti_ng_temp_pgd = (pgd_t *)(alloc + (levels - 1) * PAGE_SIZE);
> kpti_ng_temp_alloc = kpti_ng_temp_pgd_pa = __pa(kpti_ng_temp_pgd);
>
> @@ -1414,16 +1411,17 @@ static int __init __kpti_install_ng_mappings(void *__unused)
> remap_fn(cpu, num_online_cpus(), kpti_ng_temp_pgd_pa, KPTI_NG_TEMP_VA);
> cpu_uninstall_idmap();
>
> - if (!cpu) {
> - free_pages(alloc, order);
> + if (!cpu)
> arm64_use_ng_mappings = true;
> - }
>
> return 0;
> }
>
> void __init kpti_install_ng_mappings(void)
> {
> + int order = order_base_2(CONFIG_PGTABLE_LEVELS);
> + u64 alloc;
> +
> /* Check whether KPTI is going to be used */
> if (!arm64_kernel_unmapped_at_el0())
> return;
> @@ -1436,8 +1434,14 @@ void __init kpti_install_ng_mappings(void)
> if (arm64_use_ng_mappings)
> return;
>
> + alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
I don't think this requires GFP_ATOMIC now?
With that removed:
Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
> + if (!alloc)
> + panic("Failed to alloc page tables\n");
> +
> init_idmap_kpti_bbml2_flag();
> - stop_machine(__kpti_install_ng_mappings, NULL, cpu_online_mask);
> + stop_machine(__kpti_install_ng_mappings, &alloc, cpu_online_mask);
> +
> + free_pages(alloc, order);
> }
>
> static pgprot_t __init kernel_exec_prot(void)
On 12/17/25 20:03, Ryan Roberts wrote:
> On 17/12/2025 18:20, Yeoreum Yun wrote:
>> The current __kpti_install_ng_mappings() allocates a temporary PGD
>> while installing the NG mapping for KPTI under stop_machine(),
>> using GFP_ATOMIC.
>>
>> This is fine in the non-PREEMPT_RT case. However, it becomes a problem
>> under PREEMPT_RT because generic memory allocation/free APIs
>> (e.g., pgtable_alloc(), __get_free_pages(), etc.) cannot be invoked
>> in a non-preemptible context, except for the *_nolock() variants.
>> These generic allocators may sleep due to their use of spin_lock().
>>
>> In other words, calling __get_free_pages(), even with GFP_ATOMIC,
>> is not allowed in __kpti_install_ng_mappings(), which is executed by
>> the stopper thread where preemption is disabled under PREEMPT_RT.
>>
>> To address this, preallocate the page needed for the temporary PGD
>> before invoking __kpti_install_ng_mappings() via stop_machine().
>>
>> Fixes: 47546a1912fc ("arm64: mm: install KPTI nG mappings with MMU enabled")
>> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
>> ---
>> arch/arm64/mm/mmu.c | 22 +++++++++++++---------
>> 1 file changed, 13 insertions(+), 9 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index e4e6c7e0a016..69d9651de0cd 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -1360,7 +1360,7 @@ static phys_addr_t __init kpti_ng_pgd_alloc(enum pgtable_type type)
>> return kpti_ng_temp_alloc;
>> }
>>
>> -static int __init __kpti_install_ng_mappings(void *__unused)
>> +static int __init __kpti_install_ng_mappings(void *data)
>> {
>> typedef void (kpti_remap_fn)(int, int, phys_addr_t, unsigned long);
>> extern kpti_remap_fn idmap_kpti_install_ng_mappings;
>> @@ -1368,10 +1368,9 @@ static int __init __kpti_install_ng_mappings(void *__unused)
>>
>> int cpu = smp_processor_id();
>> int levels = CONFIG_PGTABLE_LEVELS;
>> - int order = order_base_2(levels);
>> u64 kpti_ng_temp_pgd_pa = 0;
>> pgd_t *kpti_ng_temp_pgd;
>> - u64 alloc = 0;
>> + u64 alloc = *(u64 *)data;
>>
>> if (levels == 5 && !pgtable_l5_enabled())
>> levels = 4;
>> @@ -1382,8 +1381,6 @@ static int __init __kpti_install_ng_mappings(void *__unused)
>>
>> if (!cpu) {
>> int ret;
>> -
>> - alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
>> kpti_ng_temp_pgd = (pgd_t *)(alloc + (levels - 1) * PAGE_SIZE);
>> kpti_ng_temp_alloc = kpti_ng_temp_pgd_pa = __pa(kpti_ng_temp_pgd);
>>
>> @@ -1414,16 +1411,17 @@ static int __init __kpti_install_ng_mappings(void *__unused)
>> remap_fn(cpu, num_online_cpus(), kpti_ng_temp_pgd_pa, KPTI_NG_TEMP_VA);
>> cpu_uninstall_idmap();
>>
>> - if (!cpu) {
>> - free_pages(alloc, order);
>> + if (!cpu)
>> arm64_use_ng_mappings = true;
>> - }
>>
>> return 0;
>> }
>>
>> void __init kpti_install_ng_mappings(void)
>> {
>> + int order = order_base_2(CONFIG_PGTABLE_LEVELS);
>> + u64 alloc;
>> +
>> /* Check whether KPTI is going to be used */
>> if (!arm64_kernel_unmapped_at_el0())
>> return;
>> @@ -1436,8 +1434,14 @@ void __init kpti_install_ng_mappings(void)
>> if (arm64_use_ng_mappings)
>> return;
>>
>> + alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
>
> I don't think this requires GFP_ATOMIC now?
Do you mean it's fine to use GFP_KERNEL now, or still not, and you mean that
GFP_NOWAIT is sufficient?
> With that removed:
>
> Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
>
>> + if (!alloc)
>> + panic("Failed to alloc page tables\n");
>> +
>> init_idmap_kpti_bbml2_flag();
>> - stop_machine(__kpti_install_ng_mappings, NULL, cpu_online_mask);
>> + stop_machine(__kpti_install_ng_mappings, &alloc, cpu_online_mask);
>> +
>> + free_pages(alloc, order);
>> }
>>
>> static pgprot_t __init kernel_exec_prot(void)
>
On 18/12/2025 07:51, Vlastimil Babka wrote:
> On 12/17/25 20:03, Ryan Roberts wrote:
>> On 17/12/2025 18:20, Yeoreum Yun wrote:
>>> The current __kpti_install_ng_mappings() allocates a temporary PGD
>>> while installing the NG mapping for KPTI under stop_machine(),
>>> using GFP_ATOMIC.
>>>
>>> This is fine in the non-PREEMPT_RT case. However, it becomes a problem
>>> under PREEMPT_RT because generic memory allocation/free APIs
>>> (e.g., pgtable_alloc(), __get_free_pages(), etc.) cannot be invoked
>>> in a non-preemptible context, except for the *_nolock() variants.
>>> These generic allocators may sleep due to their use of spin_lock().
>>>
>>> In other words, calling __get_free_pages(), even with GFP_ATOMIC,
>>> is not allowed in __kpti_install_ng_mappings(), which is executed by
>>> the stopper thread where preemption is disabled under PREEMPT_RT.
>>>
>>> To address this, preallocate the page needed for the temporary PGD
>>> before invoking __kpti_install_ng_mappings() via stop_machine().
>>>
>>> Fixes: 47546a1912fc ("arm64: mm: install KPTI nG mappings with MMU enabled")
>>> Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
>>> ---
>>> arch/arm64/mm/mmu.c | 22 +++++++++++++---------
>>> 1 file changed, 13 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>>> index e4e6c7e0a016..69d9651de0cd 100644
>>> --- a/arch/arm64/mm/mmu.c
>>> +++ b/arch/arm64/mm/mmu.c
>>> @@ -1360,7 +1360,7 @@ static phys_addr_t __init kpti_ng_pgd_alloc(enum pgtable_type type)
>>> return kpti_ng_temp_alloc;
>>> }
>>>
>>> -static int __init __kpti_install_ng_mappings(void *__unused)
>>> +static int __init __kpti_install_ng_mappings(void *data)
>>> {
>>> typedef void (kpti_remap_fn)(int, int, phys_addr_t, unsigned long);
>>> extern kpti_remap_fn idmap_kpti_install_ng_mappings;
>>> @@ -1368,10 +1368,9 @@ static int __init __kpti_install_ng_mappings(void *__unused)
>>>
>>> int cpu = smp_processor_id();
>>> int levels = CONFIG_PGTABLE_LEVELS;
>>> - int order = order_base_2(levels);
>>> u64 kpti_ng_temp_pgd_pa = 0;
>>> pgd_t *kpti_ng_temp_pgd;
>>> - u64 alloc = 0;
>>> + u64 alloc = *(u64 *)data;
>>>
>>> if (levels == 5 && !pgtable_l5_enabled())
>>> levels = 4;
>>> @@ -1382,8 +1381,6 @@ static int __init __kpti_install_ng_mappings(void *__unused)
>>>
>>> if (!cpu) {
>>> int ret;
>>> -
>>> - alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
>>> kpti_ng_temp_pgd = (pgd_t *)(alloc + (levels - 1) * PAGE_SIZE);
>>> kpti_ng_temp_alloc = kpti_ng_temp_pgd_pa = __pa(kpti_ng_temp_pgd);
>>>
>>> @@ -1414,16 +1411,17 @@ static int __init __kpti_install_ng_mappings(void *__unused)
>>> remap_fn(cpu, num_online_cpus(), kpti_ng_temp_pgd_pa, KPTI_NG_TEMP_VA);
>>> cpu_uninstall_idmap();
>>>
>>> - if (!cpu) {
>>> - free_pages(alloc, order);
>>> + if (!cpu)
>>> arm64_use_ng_mappings = true;
>>> - }
>>>
>>> return 0;
>>> }
>>>
>>> void __init kpti_install_ng_mappings(void)
>>> {
>>> + int order = order_base_2(CONFIG_PGTABLE_LEVELS);
>>> + u64 alloc;
>>> +
>>> /* Check whether KPTI is going to be used */
>>> if (!arm64_kernel_unmapped_at_el0())
>>> return;
>>> @@ -1436,8 +1434,14 @@ void __init kpti_install_ng_mappings(void)
>>> if (arm64_use_ng_mappings)
>>> return;
>>>
>>> + alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
>>
>> I don't think this requires GFP_ATOMIC now?
>
> Do you mean it's fine to use GFP_KERNEL now, or still not, and you mean that
> GFP_NOWAIT is sufficient?
I mean it's fine to use "GFP_KERNEL | __GFP_ZERO"; this context can sleep so we
don't want to dip into the reserves - we can sleep and reclaim if needed.
>
>> With that removed:
>>
>> Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
>>
>>> + if (!alloc)
>>> + panic("Failed to alloc page tables\n");
>>> +
>>> init_idmap_kpti_bbml2_flag();
>>> - stop_machine(__kpti_install_ng_mappings, NULL, cpu_online_mask);
>>> + stop_machine(__kpti_install_ng_mappings, &alloc, cpu_online_mask);
>>> +
>>> + free_pages(alloc, order);
>>> }
>>>
>>> static pgprot_t __init kernel_exec_prot(void)
>>
>
Hi Ryanc,
[...]
> > - if (!cpu) {
> > - free_pages(alloc, order);
> > + if (!cpu)
> > arm64_use_ng_mappings = true;
> > - }
> >
> > return 0;
> > }
> >
> > void __init kpti_install_ng_mappings(void)
> > {
> > + int order = order_base_2(CONFIG_PGTABLE_LEVELS);
> > + u64 alloc;
> > +
> > /* Check whether KPTI is going to be used */
> > if (!arm64_kernel_unmapped_at_el0())
> > return;
> > @@ -1436,8 +1434,14 @@ void __init kpti_install_ng_mappings(void)
> > if (arm64_use_ng_mappings)
> > return;
> >
> > + alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
>
> I don't think this requires GFP_ATOMIC now?
>
> With that removed:
>
> Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
I think it would be better to use only __GFP_HIGH in here since
when kpti_install_ng_mappings() is called, "kswpd" doesn't created yet.
and to allocate page with assurance, It would be good to use
min_reserved to.
Am I missing something?
Thanks.
[...]
--
Sincerely,
Yeoreum Yun
On 17/12/2025 19:09, Yeoreum Yun wrote:
> Hi Ryanc,
>
> [...]
>>> - if (!cpu) {
>>> - free_pages(alloc, order);
>>> + if (!cpu)
>>> arm64_use_ng_mappings = true;
>>> - }
>>>
>>> return 0;
>>> }
>>>
>>> void __init kpti_install_ng_mappings(void)
>>> {
>>> + int order = order_base_2(CONFIG_PGTABLE_LEVELS);
>>> + u64 alloc;
>>> +
>>> /* Check whether KPTI is going to be used */
>>> if (!arm64_kernel_unmapped_at_el0())
>>> return;
>>> @@ -1436,8 +1434,14 @@ void __init kpti_install_ng_mappings(void)
>>> if (arm64_use_ng_mappings)
>>> return;
>>>
>>> + alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order);
>>
>> I don't think this requires GFP_ATOMIC now?
>>
>> With that removed:
>>
>> Reviewed-by: Ryan Roberts <ryan.roberts@arm.com>
>
> I think it would be better to use only __GFP_HIGH in here since
> when kpti_install_ng_mappings() is called, "kswpd" doesn't created yet.
> and to allocate page with assurance, It would be good to use
> min_reserved to.
>
> Am I missing something?
Personally I think we should just use "GFP_KERNEL | __GFP_ZERO". Anything else
would make this allocation look special, which it is not. If we fail to allocate
at this point in boot, we have bigger problems.
>
> Thanks.
>
> [...]
>
> --
> Sincerely,
> Yeoreum Yun
[...] > > I think it would be better to use only __GFP_HIGH in here since > > when kpti_install_ng_mappings() is called, "kswpd" doesn't created yet. > > and to allocate page with assurance, It would be good to use > > min_reserved to. > > > > Am I missing something? > > Personally I think we should just use "GFP_KERNEL | __GFP_ZERO". Anything else > would make this allocation look special, which it is not. If we fail to allocate > at this point in boot, we have bigger problems. But I'm not sure *HOW effective* to use GFP_KERNEL in here. Since it's before the any filesystem inited. IOW, in this context, almost there would be no *page cache* and I think it seems meaningless to use "GFP_KERNEL" and "direct reclaim" So to get success for allocation, __GFP_HIGH | _GFP_ZERO seems much better. Thanks -- Sincerely, Yeoreum Yun
On 12/18/25 09:37, Yeoreum Yun wrote: > [...] >>> I think it would be better to use only __GFP_HIGH in here since >>> when kpti_install_ng_mappings() is called, "kswpd" doesn't created yet. >>> and to allocate page with assurance, It would be good to use >>> min_reserved to. >>> >>> Am I missing something? >> >> Personally I think we should just use "GFP_KERNEL | __GFP_ZERO". Anything else >> would make this allocation look special, which it is not. If we fail to allocate >> at this point in boot, we have bigger problems. > > But I'm not sure *HOW effective* to use GFP_KERNEL in here. > Since it's before the any filesystem inited. > IOW, in this context, almost there would be no *page cache* > and I think it seems meaningless to use "GFP_KERNEL" and "direct > reclaim" > > So to get success for allocation, __GFP_HIGH | _GFP_ZERO seems much > better. Unless there is a real reason to confuse readers why this is very special, just go with "GFP_KERNEL | __GFP_ZERO", really. In particular if it doesn't matter in practice? Or does it and we are not getting your point? -- Cheers David
Hi David,
> On 12/18/25 09:37, Yeoreum Yun wrote:
> > [...]
> > > > I think it would be better to use only __GFP_HIGH in here since
> > > > when kpti_install_ng_mappings() is called, "kswpd" doesn't created yet.
> > > > and to allocate page with assurance, It would be good to use
> > > > min_reserved to.
> > > >
> > > > Am I missing something?
> > >
> > > Personally I think we should just use "GFP_KERNEL | __GFP_ZERO". Anything else
> > > would make this allocation look special, which it is not. If we fail to allocate
> > > at this point in boot, we have bigger problems.
> >
> > But I'm not sure *HOW effective* to use GFP_KERNEL in here.
> > Since it's before the any filesystem inited.
> > IOW, in this context, almost there would be no *page cache*
> > and I think it seems meaningless to use "GFP_KERNEL" and "direct
> > reclaim"
> >
> > So to get success for allocation, __GFP_HIGH | _GFP_ZERO seems much
> > better.
>
> Unless there is a real reason to confuse readers why this is very special,
> just go with "GFP_KERNEL | __GFP_ZERO", really.
>
> In particular if it doesn't matter in practice? Or does it and we are not
> getting your point?
My worries was
- kpti_install_ng_mappings() is called while in "smp_init()" which is
before creating the kswapd thread via module_init().
Just wondered whether it allows to call wakeup_kswapd() before
kswapd is created.
- Similar reason kcompactd too.
- Just wonder how much direct reclaim is effecitve since
when kpti_install_ng_mappings() called before each
filesystem initialised where not much of page cache in usage.
TBH (1) and (2) seems fine since each wakeup function checks
the waitqueue. but because of (3),
I think not GFP_KERNEL but __GFP_HIGH | __GFP_DIRECT_RECLAIM | __GFP_ZERO (?)
Am I missing?
--
Sincerely,
Yeoreum Yun
On 12/18/25 10:31, Yeoreum Yun wrote: > Hi David, > >> On 12/18/25 09:37, Yeoreum Yun wrote: >>> [...] >>>>> I think it would be better to use only __GFP_HIGH in here since >>>>> when kpti_install_ng_mappings() is called, "kswpd" doesn't created yet. >>>>> and to allocate page with assurance, It would be good to use >>>>> min_reserved to. >>>>> >>>>> Am I missing something? >>>> >>>> Personally I think we should just use "GFP_KERNEL | __GFP_ZERO". Anything else >>>> would make this allocation look special, which it is not. If we fail to allocate >>>> at this point in boot, we have bigger problems. >>> >>> But I'm not sure *HOW effective* to use GFP_KERNEL in here. >>> Since it's before the any filesystem inited. >>> IOW, in this context, almost there would be no *page cache* >>> and I think it seems meaningless to use "GFP_KERNEL" and "direct >>> reclaim" >>> >>> So to get success for allocation, __GFP_HIGH | _GFP_ZERO seems much >>> better. >> >> Unless there is a real reason to confuse readers why this is very special, >> just go with "GFP_KERNEL | __GFP_ZERO", really. >> >> In particular if it doesn't matter in practice? Or does it and we are not >> getting your point? > > My worries was > - kpti_install_ng_mappings() is called while in "smp_init()" which is > before creating the kswapd thread via module_init(). > Just wondered whether it allows to call wakeup_kswapd() before > kswapd is created. The buddy should really be able to deal with that, no? > > - Similar reason kcompactd too. Same as well. We cannot expect alloc API users to know about these hidden details to work around them :) > > - Just wonder how much direct reclaim is effecitve since > when kpti_install_ng_mappings() called before each > filesystem initialised where not much of page cache in usage. Right, but do you really think we would ever trigger that path? The default should always be GFP_KERNEL unless we have for very good reason special demands. So, do you think in practice there is real value in NOT using GFP_KERNEL? :) -- Cheers David
Hi David, > On 12/18/25 10:31, Yeoreum Yun wrote: > > Hi David, > > > > > On 12/18/25 09:37, Yeoreum Yun wrote: > > > > [...] > > > > > > I think it would be better to use only __GFP_HIGH in here since > > > > > > when kpti_install_ng_mappings() is called, "kswpd" doesn't created yet. > > > > > > and to allocate page with assurance, It would be good to use > > > > > > min_reserved to. > > > > > > > > > > > > Am I missing something? > > > > > > > > > > Personally I think we should just use "GFP_KERNEL | __GFP_ZERO". Anything else > > > > > would make this allocation look special, which it is not. If we fail to allocate > > > > > at this point in boot, we have bigger problems. > > > > > > > > But I'm not sure *HOW effective* to use GFP_KERNEL in here. > > > > Since it's before the any filesystem inited. > > > > IOW, in this context, almost there would be no *page cache* > > > > and I think it seems meaningless to use "GFP_KERNEL" and "direct > > > > reclaim" > > > > > > > > So to get success for allocation, __GFP_HIGH | _GFP_ZERO seems much > > > > better. > > > > > > Unless there is a real reason to confuse readers why this is very special, > > > just go with "GFP_KERNEL | __GFP_ZERO", really. > > > > > > In particular if it doesn't matter in practice? Or does it and we are not > > > getting your point? > > > > My worries was > > - kpti_install_ng_mappings() is called while in "smp_init()" which is > > before creating the kswapd thread via module_init(). > > Just wondered whether it allows to call wakeup_kswapd() before > > kswapd is created. > > The buddy should really be able to deal with that, no? > > > > > - Similar reason kcompactd too. > > Same as well. Nope. buddy handles them. It was a past :) > > We cannot expect alloc API users to know about these hidden details to work > around them :) > > > > > - Just wonder how much direct reclaim is effecitve since > > when kpti_install_ng_mappings() called before each > > filesystem initialised where not much of page cache in usage. > > Right, but do you really think we would ever trigger that path? > > The default should always be GFP_KERNEL unless we have for very good reason > special demands. > > So, do you think in practice there is real value in NOT using GFP_KERNEL? :) In the *practical view*. Absoultely NOT since I don't think it reaches those codes. Okay. I'll change with GFP_KERNEL | __GFP_ZERO. Thanks! -- Sincerely, Yeoreum Yun
© 2016 - 2026 Red Hat, Inc.