arch/sparc/mm/init_64.c | 56 ++++++++++++++++------------------------- include/linux/mm.h | 1 + mm/sparse-vmemmap.c | 7 +++++- 3 files changed, 28 insertions(+), 36 deletions(-)
From: Chengkaitao <chengkaitao@kylinos.cn>
1. Added the vmemmap_false_pmd function to accommodate architectures
that do not support basepages.
2. In the SPARC architecture, reimplemented vmemmap_populate using
vmemmap_populate_hugepages.
Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn>
---
arch/sparc/mm/init_64.c | 56 ++++++++++++++++-------------------------
include/linux/mm.h | 1 +
mm/sparse-vmemmap.c | 7 +++++-
3 files changed, 28 insertions(+), 36 deletions(-)
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index df9f7c444c39..a80cdfa6ba98 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -5,7 +5,7 @@
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1997-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
-
+
#include <linux/extable.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -2397,11 +2397,11 @@ void __init paging_init(void)
* work.
*/
init_mm.pgd += ((shift) / (sizeof(pgd_t)));
-
+
memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
inherit_prom_mappings();
-
+
/* Ok, we can use our TLB miss and window trap handlers safely. */
setup_tba();
@@ -2581,8 +2581,8 @@ unsigned long _PAGE_CACHE __read_mostly;
EXPORT_SYMBOL(_PAGE_CACHE);
#ifdef CONFIG_SPARSEMEM_VMEMMAP
-int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
- int node, struct vmem_altmap *altmap)
+void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
+ unsigned long addr, unsigned long next)
{
unsigned long pte_base;
@@ -2595,39 +2595,25 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
pte_base |= _PAGE_PMD_HUGE;
- vstart = vstart & PMD_MASK;
- vend = ALIGN(vend, PMD_SIZE);
- for (; vstart < vend; vstart += PMD_SIZE) {
- pgd_t *pgd = vmemmap_pgd_populate(vstart, node);
- unsigned long pte;
- p4d_t *p4d;
- pud_t *pud;
- pmd_t *pmd;
-
- if (!pgd)
- return -ENOMEM;
-
- p4d = vmemmap_p4d_populate(pgd, vstart, node);
- if (!p4d)
- return -ENOMEM;
-
- pud = vmemmap_pud_populate(p4d, vstart, node);
- if (!pud)
- return -ENOMEM;
-
- pmd = pmd_offset(pud, vstart);
- pte = pmd_val(*pmd);
- if (!(pte & _PAGE_VALID)) {
- void *block = vmemmap_alloc_block(PMD_SIZE, node);
+ pmd_val(*pmd) = pte_base | __pa(p);
+}
- if (!block)
- return -ENOMEM;
+bool __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
+{
+ return true;
+}
- pmd_val(*pmd) = pte_base | __pa(block);
- }
- }
+int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
+ unsigned long addr, unsigned long next)
+{
+ vmemmap_verify((pte_t *)pmdp, node, addr, next);
+ return 1;
+}
- return 0;
+int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
+ int node, struct vmem_altmap *altmap)
+{
+ return vmemmap_populate_hugepages(vstart, vend, node, altmap);
}
#endif /* CONFIG_SPARSEMEM_VMEMMAP */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 15076261d0c2..5e005b0f947d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4248,6 +4248,7 @@ void *vmemmap_alloc_block_buf(unsigned long size, int node,
void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
void vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
unsigned long addr, unsigned long next);
+bool vmemmap_false_pmd(pmd_t *pmd, int node);
int vmemmap_check_pmd(pmd_t *pmd, int node,
unsigned long addr, unsigned long next);
int vmemmap_populate_basepages(unsigned long start, unsigned long end,
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index 37522d6cb398..bd54b8c6f56e 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -407,6 +407,11 @@ void __weak __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
{
}
+bool __weak __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
+{
+ return 0;
+}
+
int __weak __meminit vmemmap_check_pmd(pmd_t *pmd, int node,
unsigned long addr, unsigned long next)
{
@@ -446,7 +451,7 @@ int __meminit vmemmap_populate_hugepages(unsigned long start, unsigned long end,
if (p) {
vmemmap_set_pmd(pmd, p, node, addr, next);
continue;
- } else if (altmap) {
+ } else if (altmap || vmemmap_false_pmd(pmd, node)) {
/*
* No fallback: In any case we care about, the
* altmap should be reasonably sized and aligned
--
2.50.1 (Apple Git-155)
On Wed, Dec 17, 2025 at 08:08:58PM +0800, chengkaitao wrote: > From: Chengkaitao <chengkaitao@kylinos.cn> > > 1. Added the vmemmap_false_pmd function to accommodate architectures > that do not support basepages. > 2. In the SPARC architecture, reimplemented vmemmap_populate using > vmemmap_populate_hugepages. What problem this patch is trying to solve? > Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn> > --- -- Sincerely yours, Mike.
On Thu, Dec 18, 2025 at 7:14 PM Mike Rapoport <rppt@kernel.org> wrote: > > On Wed, Dec 17, 2025 at 08:08:58PM +0800, chengkaitao wrote: > > From: Chengkaitao <chengkaitao@kylinos.cn> > > > > 1. Added the vmemmap_false_pmd function to accommodate architectures > > that do not support basepages. > > 2. In the SPARC architecture, reimplemented vmemmap_populate using > > vmemmap_populate_hugepages. > > What problem this patch is trying to solve? Following the pattern established by other architectures, vmemmap_populate is reimplemented using vmemmap_populate_hugepages in the SPARC architecture, which fulfills the intended purpose of vmemmap_populate_hugepages. The functional logic remains unchanged. > > Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn> > > --- -- Yours, Kaitao Cheng
On Thu, Dec 18, 2025 at 07:45:52PM +0800, Tao pilgrim wrote: > On Thu, Dec 18, 2025 at 7:14 PM Mike Rapoport <rppt@kernel.org> wrote: > > > > On Wed, Dec 17, 2025 at 08:08:58PM +0800, chengkaitao wrote: > > > From: Chengkaitao <chengkaitao@kylinos.cn> > > > > > > 1. Added the vmemmap_false_pmd function to accommodate architectures > > > that do not support basepages. > > > 2. In the SPARC architecture, reimplemented vmemmap_populate using > > > vmemmap_populate_hugepages. > > > > What problem this patch is trying to solve? > > Following the pattern established by other architectures, vmemmap_populate > is reimplemented using vmemmap_populate_hugepages in the SPARC architecture, > which fulfills the intended purpose of vmemmap_populate_hugepages. But what's wrong with the current sparc::vmemmap_populate()? > The functional logic remains unchanged. > > > > Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn> > > > --- > > -- > Yours, > Kaitao Cheng -- Sincerely yours, Mike.
On Thu, Dec 18, 2025 at 8:11 PM Mike Rapoport <rppt@kernel.org> wrote: > > On Thu, Dec 18, 2025 at 07:45:52PM +0800, Tao pilgrim wrote: > > On Thu, Dec 18, 2025 at 7:14 PM Mike Rapoport <rppt@kernel.org> wrote: > > > > > > On Wed, Dec 17, 2025 at 08:08:58PM +0800, chengkaitao wrote: > > > > From: Chengkaitao <chengkaitao@kylinos.cn> > > > > > > > > 1. Added the vmemmap_false_pmd function to accommodate architectures > > > > that do not support basepages. > > > > 2. In the SPARC architecture, reimplemented vmemmap_populate using > > > > vmemmap_populate_hugepages. > > > > > > What problem this patch is trying to solve? > > > > Following the pattern established by other architectures, vmemmap_populate > > is reimplemented using vmemmap_populate_hugepages in the SPARC architecture, > > which fulfills the intended purpose of vmemmap_populate_hugepages. > > But what's wrong with the current sparc::vmemmap_populate()? The current implementation of sparc::vmemmap_populate() is correct and functional. However, I believe that generalizing vmemmap_populate_hugepages() still results in certain architectures requiring special-case handling branches, which is contrary to our goal of a unified implementation. Another benefit is that it allows us to eliminate the external declarations of vmemmap_p?d_populate functions and convert them to static functions. > > The functional logic remains unchanged. > > > > > > Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn> > > > > --- -- Yours, Kaitao Cheng
On Thu, Dec 18, 2025 at 08:29:27PM +0800, Tao pilgrim wrote: > On Thu, Dec 18, 2025 at 8:11 PM Mike Rapoport <rppt@kernel.org> wrote: > > > > On Thu, Dec 18, 2025 at 07:45:52PM +0800, Tao pilgrim wrote: > > > On Thu, Dec 18, 2025 at 7:14 PM Mike Rapoport <rppt@kernel.org> wrote: > > > > > > > > On Wed, Dec 17, 2025 at 08:08:58PM +0800, chengkaitao wrote: > > > > > From: Chengkaitao <chengkaitao@kylinos.cn> > > > > > > > > > > 1. Added the vmemmap_false_pmd function to accommodate architectures > > > > > that do not support basepages. > > > > > 2. In the SPARC architecture, reimplemented vmemmap_populate using > > > > > vmemmap_populate_hugepages. > > > > > > > > What problem this patch is trying to solve? > > > > > > Following the pattern established by other architectures, vmemmap_populate > > > is reimplemented using vmemmap_populate_hugepages in the SPARC architecture, > > > which fulfills the intended purpose of vmemmap_populate_hugepages. > > > > But what's wrong with the current sparc::vmemmap_populate()? > > The current implementation of sparc::vmemmap_populate() is correct > and functional. > > However, I believe that generalizing vmemmap_populate_hugepages() > still results in certain architectures requiring special-case handling > branches, which is contrary to our goal of a unified implementation. > > Another benefit is that it allows us to eliminate the external > declarations of vmemmap_p?d_populate functions and convert > them to static functions. If the goals are to provide a unified implementation and eliminate the external declarations of vmemmap_p?d_populate() functions, I'd suggest to send all this a single series rather than a single patch that updates sparc implementation. Regarding the ability of sparc to fallback to vmemmap_populate_basepages(), it does not seem to me that this is an architectural limitation. sparc uses base pages in the kernel page tables, so it should be able to use them in vmemmap as well. > > > The functional logic remains unchanged. > > > > > > > > Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn> > > > > > --- > > -- > Yours, > Kaitao Cheng -- Sincerely yours, Mike.
On Thu, Dec 18, 2025 at 9:17 PM Mike Rapoport <rppt@kernel.org> wrote: > > On Thu, Dec 18, 2025 at 08:29:27PM +0800, Tao pilgrim wrote: > > On Thu, Dec 18, 2025 at 8:11 PM Mike Rapoport <rppt@kernel.org> wrote: > > > > > > On Thu, Dec 18, 2025 at 07:45:52PM +0800, Tao pilgrim wrote: > > > > On Thu, Dec 18, 2025 at 7:14 PM Mike Rapoport <rppt@kernel.org> wrote: > > > > > > > > > > On Wed, Dec 17, 2025 at 08:08:58PM +0800, chengkaitao wrote: > > > > > > From: Chengkaitao <chengkaitao@kylinos.cn> > > > > > > > > > > > > 1. Added the vmemmap_false_pmd function to accommodate architectures > > > > > > that do not support basepages. > > > > > > 2. In the SPARC architecture, reimplemented vmemmap_populate using > > > > > > vmemmap_populate_hugepages. > > > > > > > > > > What problem this patch is trying to solve? > > > > > > > > Following the pattern established by other architectures, vmemmap_populate > > > > is reimplemented using vmemmap_populate_hugepages in the SPARC architecture, > > > > which fulfills the intended purpose of vmemmap_populate_hugepages. > > > > > > But what's wrong with the current sparc::vmemmap_populate()? > > > > The current implementation of sparc::vmemmap_populate() is correct > > and functional. > > > > However, I believe that generalizing vmemmap_populate_hugepages() > > still results in certain architectures requiring special-case handling > > branches, which is contrary to our goal of a unified implementation. > > > > Another benefit is that it allows us to eliminate the external > > declarations of vmemmap_p?d_populate functions and convert > > them to static functions. > > If the goals are to provide a unified implementation and eliminate the > external declarations of vmemmap_p?d_populate() functions, I'd suggest to > send all this a single series rather than a single patch that updates sparc > implementation. > > Regarding the ability of sparc to fallback to vmemmap_populate_basepages(), > it does not seem to me that this is an architectural limitation. sparc uses > base pages in the kernel page tables, so it should be able to use them in > vmemmap as well. If SPARC can use base pages in vmemmap, I might remove the vmemmap_false_pmd implementation. Thanks for your review. > > > > The functional logic remains unchanged. > > > > > > > > > > Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn> > > > > > > --- > > -- Yours, Kaitao Cheng
On 12/17/25 13:08, chengkaitao wrote:
> From: Chengkaitao <chengkaitao@kylinos.cn>
>
> 1. Added the vmemmap_false_pmd function to accommodate architectures
> that do not support basepages.
> 2. In the SPARC architecture, reimplemented vmemmap_populate using
> vmemmap_populate_hugepages.
>
> Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn>
> ---
> arch/sparc/mm/init_64.c | 56 ++++++++++++++++-------------------------
> include/linux/mm.h | 1 +
> mm/sparse-vmemmap.c | 7 +++++-
> 3 files changed, 28 insertions(+), 36 deletions(-)
>
> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> index df9f7c444c39..a80cdfa6ba98 100644
> --- a/arch/sparc/mm/init_64.c
> +++ b/arch/sparc/mm/init_64.c
> @@ -5,7 +5,7 @@
> * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
> * Copyright (C) 1997-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
> */
> -
> +
> #include <linux/extable.h>
> #include <linux/kernel.h>
> #include <linux/sched.h>
> @@ -2397,11 +2397,11 @@ void __init paging_init(void)
> * work.
> */
> init_mm.pgd += ((shift) / (sizeof(pgd_t)));
> -
> +
> memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
>
> inherit_prom_mappings();
> -
> +
> /* Ok, we can use our TLB miss and window trap handlers safely. */
> setup_tba();
>
Bunch of unrelated changes that should not go in here.
> @@ -2581,8 +2581,8 @@ unsigned long _PAGE_CACHE __read_mostly;
> EXPORT_SYMBOL(_PAGE_CACHE);
>
> #ifdef CONFIG_SPARSEMEM_VMEMMAP
> -int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
> - int node, struct vmem_altmap *altmap)
> +void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> + unsigned long addr, unsigned long next)
> {
> unsigned long pte_base;
>
> @@ -2595,39 +2595,25 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
>
> pte_base |= _PAGE_PMD_HUGE;
>
> - vstart = vstart & PMD_MASK;
> - vend = ALIGN(vend, PMD_SIZE);
> - for (; vstart < vend; vstart += PMD_SIZE) {
> - pgd_t *pgd = vmemmap_pgd_populate(vstart, node);
> - unsigned long pte;
> - p4d_t *p4d;
> - pud_t *pud;
> - pmd_t *pmd;
> -
> - if (!pgd)
> - return -ENOMEM;
> -
> - p4d = vmemmap_p4d_populate(pgd, vstart, node);
> - if (!p4d)
> - return -ENOMEM;
> -
> - pud = vmemmap_pud_populate(p4d, vstart, node);
> - if (!pud)
> - return -ENOMEM;
> -
> - pmd = pmd_offset(pud, vstart);
> - pte = pmd_val(*pmd);
> - if (!(pte & _PAGE_VALID)) {
> - void *block = vmemmap_alloc_block(PMD_SIZE, node);
> + pmd_val(*pmd) = pte_base | __pa(p);
> +}
>
> - if (!block)
> - return -ENOMEM;
> +bool __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
> +{
> + return true;
> +}
>
> - pmd_val(*pmd) = pte_base | __pa(block);
> - }
> - }
> +int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
> + unsigned long addr, unsigned long next)
> +{
> + vmemmap_verify((pte_t *)pmdp, node, addr, next);
> + return 1;
> +}
>
> - return 0;
> +int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
> + int node, struct vmem_altmap *altmap)
> +{
> + return vmemmap_populate_hugepages(vstart, vend, node, altmap);
> }
> #endif /* CONFIG_SPARSEMEM_VMEMMAP */
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 15076261d0c2..5e005b0f947d 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -4248,6 +4248,7 @@ void *vmemmap_alloc_block_buf(unsigned long size, int node,
> void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
> void vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> unsigned long addr, unsigned long next);
> +bool vmemmap_false_pmd(pmd_t *pmd, int node);
> int vmemmap_check_pmd(pmd_t *pmd, int node,
> unsigned long addr, unsigned long next);
> int vmemmap_populate_basepages(unsigned long start, unsigned long end,
> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> index 37522d6cb398..bd54b8c6f56e 100644
> --- a/mm/sparse-vmemmap.c
> +++ b/mm/sparse-vmemmap.c
> @@ -407,6 +407,11 @@ void __weak __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> {
> }
>
> +bool __weak __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
> +{
> + return 0;
> +}
> +
Reading that function I have absolutely no clue what this is supposed to
do. :)
Also, why are you passing pmd+node when sparc ignores them completely
and statically returns "true" ?
If you can tell me what the semantics of that function should be, maybe
we can come up with a more descriptive name.
--
Cheers
David
On Thu, Dec 18, 2025 at 4:44 PM David Hildenbrand (Red Hat)
<david@kernel.org> wrote:
>
> On 12/17/25 13:08, chengkaitao wrote:
> > From: Chengkaitao <chengkaitao@kylinos.cn>
> >
> > 1. Added the vmemmap_false_pmd function to accommodate architectures
> > that do not support basepages.
> > 2. In the SPARC architecture, reimplemented vmemmap_populate using
> > vmemmap_populate_hugepages.
> >
> > Signed-off-by: Chengkaitao <chengkaitao@kylinos.cn>
> > ---
> > arch/sparc/mm/init_64.c | 56 ++++++++++++++++-------------------------
> > include/linux/mm.h | 1 +
> > mm/sparse-vmemmap.c | 7 +++++-
> > 3 files changed, 28 insertions(+), 36 deletions(-)
> >
> > diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> > index df9f7c444c39..a80cdfa6ba98 100644
> > --- a/arch/sparc/mm/init_64.c
> > +++ b/arch/sparc/mm/init_64.c
> > @@ -5,7 +5,7 @@
> > * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
> > * Copyright (C) 1997-1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
> > */
> > -
> > +
> > #include <linux/extable.h>
> > #include <linux/kernel.h>
> > #include <linux/sched.h>
> > @@ -2397,11 +2397,11 @@ void __init paging_init(void)
> > * work.
> > */
> > init_mm.pgd += ((shift) / (sizeof(pgd_t)));
> > -
> > +
> > memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
> >
> > inherit_prom_mappings();
> > -
> > +
> > /* Ok, we can use our TLB miss and window trap handlers safely. */
> > setup_tba();
> >
>
> Bunch of unrelated changes that should not go in here.
This indeed contains some unrelated code changes and removal of
extra whitespace. These could be split into a separate patch,
but the new patch might be somewhat redundant, lol. If you'd
like me to proceed this way, please reply confirming.
> > @@ -2581,8 +2581,8 @@ unsigned long _PAGE_CACHE __read_mostly;
> > EXPORT_SYMBOL(_PAGE_CACHE);
> >
> > #ifdef CONFIG_SPARSEMEM_VMEMMAP
> > -int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
> > - int node, struct vmem_altmap *altmap)
> > +void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> > + unsigned long addr, unsigned long next)
> > {
> > unsigned long pte_base;
> >
> > @@ -2595,39 +2595,25 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
> >
> > pte_base |= _PAGE_PMD_HUGE;
> >
> > - vstart = vstart & PMD_MASK;
> > - vend = ALIGN(vend, PMD_SIZE);
> > - for (; vstart < vend; vstart += PMD_SIZE) {
> > - pgd_t *pgd = vmemmap_pgd_populate(vstart, node);
> > - unsigned long pte;
> > - p4d_t *p4d;
> > - pud_t *pud;
> > - pmd_t *pmd;
> > -
> > - if (!pgd)
> > - return -ENOMEM;
> > -
> > - p4d = vmemmap_p4d_populate(pgd, vstart, node);
> > - if (!p4d)
> > - return -ENOMEM;
> > -
> > - pud = vmemmap_pud_populate(p4d, vstart, node);
> > - if (!pud)
> > - return -ENOMEM;
> > -
> > - pmd = pmd_offset(pud, vstart);
> > - pte = pmd_val(*pmd);
> > - if (!(pte & _PAGE_VALID)) {
> > - void *block = vmemmap_alloc_block(PMD_SIZE, node);
> > + pmd_val(*pmd) = pte_base | __pa(p);
> > +}
> >
> > - if (!block)
> > - return -ENOMEM;
> > +bool __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
> > +{
> > + return true;
> > +}
> >
> > - pmd_val(*pmd) = pte_base | __pa(block);
> > - }
> > - }
> > +int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
> > + unsigned long addr, unsigned long next)
> > +{
> > + vmemmap_verify((pte_t *)pmdp, node, addr, next);
> > + return 1;
> > +}
> >
> > - return 0;
> > +int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
> > + int node, struct vmem_altmap *altmap)
> > +{
> > + return vmemmap_populate_hugepages(vstart, vend, node, altmap);
> > }
> > #endif /* CONFIG_SPARSEMEM_VMEMMAP */
> >
> > diff --git a/include/linux/mm.h b/include/linux/mm.h
> > index 15076261d0c2..5e005b0f947d 100644
> > --- a/include/linux/mm.h
> > +++ b/include/linux/mm.h
> > @@ -4248,6 +4248,7 @@ void *vmemmap_alloc_block_buf(unsigned long size, int node,
> > void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
> > void vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> > unsigned long addr, unsigned long next);
> > +bool vmemmap_false_pmd(pmd_t *pmd, int node);
> > int vmemmap_check_pmd(pmd_t *pmd, int node,
> > unsigned long addr, unsigned long next);
> > int vmemmap_populate_basepages(unsigned long start, unsigned long end,
> > diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> > index 37522d6cb398..bd54b8c6f56e 100644
> > --- a/mm/sparse-vmemmap.c
> > +++ b/mm/sparse-vmemmap.c
> > @@ -407,6 +407,11 @@ void __weak __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> > {
> > }
> >
> > +bool __weak __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
> > +{
> > + return 0;
> > +}
> > +
>
> Reading that function I have absolutely no clue what this is supposed to
> do. :)
>
> Also, why are you passing pmd+node when sparc ignores them completely
> and statically returns "true" ?
The pmd+node is indeed unnecessary. My original intention was
to provide convenience for future architecture extensions, but
upon reflection, this appears to be a case of over-engineering.
> If you can tell me what the semantics of that function should be, maybe
> we can come up with a more descriptive name.
In the SPARC architecture, the original vmemmap_populate
function does not retry with vmemmap_populate_basepages
after vmemmap_alloc_block fails. I suspect SPARC doesn't
support basepages, which is why we need to modify
vmemmap_populate_hugepages to provide an interface that
skips basepages handling.
--
Yours,
Kaitao Cheng
On 12/18/25 12:02, Tao pilgrim wrote:
> On Thu, Dec 18, 2025 at 4:44 PM David Hildenbrand (Red Hat)
> <david@kernel.org> wrote:
>>
>> On 12/17/25 13:08, chengkaitao wrote:
>>> From: Chengkaitao <chengkaitao@kylinos.cn>
^ this is the author
And you reply from a completely different address with a completely
different name.
To whom am I talking here? The patch author?
[...]
>>>
>>
>> Bunch of unrelated changes that should not go in here.
>
> This indeed contains some unrelated code changes and removal of
> extra whitespace. These could be split into a separate patch,
> but the new patch might be somewhat redundant, lol. If you'd
> like me to proceed this way, please reply confirming.
We usually don't do random other stuff as part of one patch. It's a
different story if you touch the surrounding code, but that doesn't look
like that here?
>
>>> @@ -2581,8 +2581,8 @@ unsigned long _PAGE_CACHE __read_mostly;
>>> EXPORT_SYMBOL(_PAGE_CACHE);
>>>
>>> #ifdef CONFIG_SPARSEMEM_VMEMMAP
>>> -int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
>>> - int node, struct vmem_altmap *altmap)
>>> +void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
>>> + unsigned long addr, unsigned long next)
>>> {
>>> unsigned long pte_base;
>>>
>>> @@ -2595,39 +2595,25 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
>>>
>>> pte_base |= _PAGE_PMD_HUGE;
>>>
>>> - vstart = vstart & PMD_MASK;
>>> - vend = ALIGN(vend, PMD_SIZE);
>>> - for (; vstart < vend; vstart += PMD_SIZE) {
>>> - pgd_t *pgd = vmemmap_pgd_populate(vstart, node);
>>> - unsigned long pte;
>>> - p4d_t *p4d;
>>> - pud_t *pud;
>>> - pmd_t *pmd;
>>> -
>>> - if (!pgd)
>>> - return -ENOMEM;
>>> -
>>> - p4d = vmemmap_p4d_populate(pgd, vstart, node);
>>> - if (!p4d)
>>> - return -ENOMEM;
>>> -
>>> - pud = vmemmap_pud_populate(p4d, vstart, node);
>>> - if (!pud)
>>> - return -ENOMEM;
>>> -
>>> - pmd = pmd_offset(pud, vstart);
>>> - pte = pmd_val(*pmd);
>>> - if (!(pte & _PAGE_VALID)) {
>>> - void *block = vmemmap_alloc_block(PMD_SIZE, node);
>>> + pmd_val(*pmd) = pte_base | __pa(p);
>>> +}
>>>
>>> - if (!block)
>>> - return -ENOMEM;
>>> +bool __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
>>> +{
>>> + return true;
>>> +}
>>>
>>> - pmd_val(*pmd) = pte_base | __pa(block);
>>> - }
>>> - }
>>> +int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
>>> + unsigned long addr, unsigned long next)
>>> +{
>>> + vmemmap_verify((pte_t *)pmdp, node, addr, next);
>>> + return 1;
>>> +}
>>>
>>> - return 0;
>>> +int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
>>> + int node, struct vmem_altmap *altmap)
>>> +{
>>> + return vmemmap_populate_hugepages(vstart, vend, node, altmap);
>>> }
>>> #endif /* CONFIG_SPARSEMEM_VMEMMAP */
>>>
>>> diff --git a/include/linux/mm.h b/include/linux/mm.h
>>> index 15076261d0c2..5e005b0f947d 100644
>>> --- a/include/linux/mm.h
>>> +++ b/include/linux/mm.h
>>> @@ -4248,6 +4248,7 @@ void *vmemmap_alloc_block_buf(unsigned long size, int node,
>>> void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
>>> void vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
>>> unsigned long addr, unsigned long next);
>>> +bool vmemmap_false_pmd(pmd_t *pmd, int node);
>>> int vmemmap_check_pmd(pmd_t *pmd, int node,
>>> unsigned long addr, unsigned long next);
>>> int vmemmap_populate_basepages(unsigned long start, unsigned long end,
>>> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
>>> index 37522d6cb398..bd54b8c6f56e 100644
>>> --- a/mm/sparse-vmemmap.c
>>> +++ b/mm/sparse-vmemmap.c
>>> @@ -407,6 +407,11 @@ void __weak __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
>>> {
>>> }
>>>
>>> +bool __weak __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
>>> +{
>>> + return 0;
>>> +}
>>> +
>>
>> Reading that function I have absolutely no clue what this is supposed to
>> do. :)
>>
>> Also, why are you passing pmd+node when sparc ignores them completely
>> and statically returns "true" ?
>
> The pmd+node is indeed unnecessary. My original intention was
> to provide convenience for future architecture extensions, but
> upon reflection, this appears to be a case of over-engineering.
Jup.
>
>> If you can tell me what the semantics of that function should be, maybe
>> we can come up with a more descriptive name.
>
> In the SPARC architecture, the original vmemmap_populate
> function does not retry with vmemmap_populate_basepages
> after vmemmap_alloc_block fails. I suspect SPARC doesn't
> support basepages, which is why we need to modify
> vmemmap_populate_hugepages to provide an interface that
> skips basepages handling.
So, something like vmemmap_pte_fallback_allowed() ?
--
Cheers
David
On Thu, Dec 18, 2025 at 7:49 PM David Hildenbrand (Red Hat)
<david@kernel.org> wrote:
>
> On 12/18/25 12:02, Tao pilgrim wrote:
> > On Thu, Dec 18, 2025 at 4:44 PM David Hildenbrand (Red Hat)
> > <david@kernel.org> wrote:
> >>
> >> On 12/17/25 13:08, chengkaitao wrote:
> >>> From: Chengkaitao <chengkaitao@kylinos.cn>
>
> ^ this is the author
>
> And you reply from a completely different address with a completely
> different name.
>
> To whom am I talking here? The patch author?
Yes, I'm the author. Due to company security policies, I have to
use two different email addresses, which I have no choice...
> [...]
>
> >> Bunch of unrelated changes that should not go in here.
> >
> > This indeed contains some unrelated code changes and removal of
> > extra whitespace. These could be split into a separate patch,
> > but the new patch might be somewhat redundant, lol. If you'd
> > like me to proceed this way, please reply confirming.
>
> We usually don't do random other stuff as part of one patch. It's a
> different story if you touch the surrounding code, but that doesn't look
> like that here?
>
> >
> >>> @@ -2581,8 +2581,8 @@ unsigned long _PAGE_CACHE __read_mostly;
> >>> EXPORT_SYMBOL(_PAGE_CACHE);
> >>>
> >>> #ifdef CONFIG_SPARSEMEM_VMEMMAP
> >>> -int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
> >>> - int node, struct vmem_altmap *altmap)
> >>> +void __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> >>> + unsigned long addr, unsigned long next)
> >>> {
> >>> unsigned long pte_base;
> >>>
> >>> @@ -2595,39 +2595,25 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
> >>>
> >>> pte_base |= _PAGE_PMD_HUGE;
> >>>
> >>> - vstart = vstart & PMD_MASK;
> >>> - vend = ALIGN(vend, PMD_SIZE);
> >>> - for (; vstart < vend; vstart += PMD_SIZE) {
> >>> - pgd_t *pgd = vmemmap_pgd_populate(vstart, node);
> >>> - unsigned long pte;
> >>> - p4d_t *p4d;
> >>> - pud_t *pud;
> >>> - pmd_t *pmd;
> >>> -
> >>> - if (!pgd)
> >>> - return -ENOMEM;
> >>> -
> >>> - p4d = vmemmap_p4d_populate(pgd, vstart, node);
> >>> - if (!p4d)
> >>> - return -ENOMEM;
> >>> -
> >>> - pud = vmemmap_pud_populate(p4d, vstart, node);
> >>> - if (!pud)
> >>> - return -ENOMEM;
> >>> -
> >>> - pmd = pmd_offset(pud, vstart);
> >>> - pte = pmd_val(*pmd);
> >>> - if (!(pte & _PAGE_VALID)) {
> >>> - void *block = vmemmap_alloc_block(PMD_SIZE, node);
> >>> + pmd_val(*pmd) = pte_base | __pa(p);
> >>> +}
> >>>
> >>> - if (!block)
> >>> - return -ENOMEM;
> >>> +bool __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
> >>> +{
> >>> + return true;
> >>> +}
> >>>
> >>> - pmd_val(*pmd) = pte_base | __pa(block);
> >>> - }
> >>> - }
> >>> +int __meminit vmemmap_check_pmd(pmd_t *pmdp, int node,
> >>> + unsigned long addr, unsigned long next)
> >>> +{
> >>> + vmemmap_verify((pte_t *)pmdp, node, addr, next);
> >>> + return 1;
> >>> +}
> >>>
> >>> - return 0;
> >>> +int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
> >>> + int node, struct vmem_altmap *altmap)
> >>> +{
> >>> + return vmemmap_populate_hugepages(vstart, vend, node, altmap);
> >>> }
> >>> #endif /* CONFIG_SPARSEMEM_VMEMMAP */
> >>>
> >>> diff --git a/include/linux/mm.h b/include/linux/mm.h
> >>> index 15076261d0c2..5e005b0f947d 100644
> >>> --- a/include/linux/mm.h
> >>> +++ b/include/linux/mm.h
> >>> @@ -4248,6 +4248,7 @@ void *vmemmap_alloc_block_buf(unsigned long size, int node,
> >>> void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
> >>> void vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> >>> unsigned long addr, unsigned long next);
> >>> +bool vmemmap_false_pmd(pmd_t *pmd, int node);
> >>> int vmemmap_check_pmd(pmd_t *pmd, int node,
> >>> unsigned long addr, unsigned long next);
> >>> int vmemmap_populate_basepages(unsigned long start, unsigned long end,
> >>> diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
> >>> index 37522d6cb398..bd54b8c6f56e 100644
> >>> --- a/mm/sparse-vmemmap.c
> >>> +++ b/mm/sparse-vmemmap.c
> >>> @@ -407,6 +407,11 @@ void __weak __meminit vmemmap_set_pmd(pmd_t *pmd, void *p, int node,
> >>> {
> >>> }
> >>>
> >>> +bool __weak __meminit vmemmap_false_pmd(pmd_t *pmd, int node)
> >>> +{
> >>> + return 0;
> >>> +}
> >>> +
> >>
> >> Reading that function I have absolutely no clue what this is supposed to
> >> do. :)
> >>
> >> Also, why are you passing pmd+node when sparc ignores them completely
> >> and statically returns "true" ?
> >
> > The pmd+node is indeed unnecessary. My original intention was
> > to provide convenience for future architecture extensions, but
> > upon reflection, this appears to be a case of over-engineering.
>
> Jup.
>
> >
> >> If you can tell me what the semantics of that function should be, maybe
> >> we can come up with a more descriptive name.
> >
> > In the SPARC architecture, the original vmemmap_populate
> > function does not retry with vmemmap_populate_basepages
> > after vmemmap_alloc_block fails. I suspect SPARC doesn't
> > support basepages, which is why we need to modify
> > vmemmap_populate_hugepages to provide an interface that
> > skips basepages handling.
>
> So, something like vmemmap_pte_fallback_allowed() ?
LGTM!
--
Yours,
Kaitao Cheng
© 2016 - 2026 Red Hat, Inc.