* [RFC PATCH] LoongArch: mm: avoid backing vmemmap beyond max_pfn
@ 2026-10-21 6:21 Wentao Guan
2026-10-21 7:23 ` Muchun Song
0 siblings, 1 reply; 2+ messages in thread
From: Wentao Guan @ 2026-10-21 6:21 UTC (permalink / raw)
To: chenhuacai
Cc: kernel, loongarch, linux-kernel, linux-mm, akpm, rppt, david,
muchun.song, Wentao Guan
A PMD maps 32MiB of vmemmap on LoongArch with 16KiB base pages, while a
512MiB section only needs 2MiB. vmemmap_populate() is called for each
section and vmemmap_populate_hugepages() installs a PMD mapping for the
whole PMD, so the last PMD also backs struct pages for PFNs beyond
max_pfn.
On a 34GiB system 160MiB of vmemmap is mapped although 136MiB is
needed. The extra 24MiB describes PFNs that do not exist.
Other architectures handle this differently. On x86, arm64 with 4KiB
pages, and riscv, the PMD covers exactly one section's vmemmap, so the
huge page path never maps beyond the populated range; x86 tracks
partially used PMDs with PAGE_UNUSED for memory hotremove. arm64 uses
base pages for 16KiB and 64KiB kernels. s390 deliberately keeps using
1MiB frames even for partially used PMDs because vmemmap_populate() is
called per section and falling back would add page tables. powerpc
radix falls back to base pages only when the altmap cannot back a full
PMD or the allocation fails, and powerpc hash maps the vmemmap with the
linear mapping page size, which can exceed a section as well.
With 16KiB pages the LoongArch PMD is 16 times the vmemmap of one
section. Moving the whole vmemmap to base pages, as arm64 does for
16KiB and 64KiB, would also remove the tail, but it would give up PMD
mappings for the 128MiB that is fully populated. Use base pages only
for the PMD that extends beyond pfn_to_page(max_pfn) and keep huge
mappings for the rest.
The altmap case is left alone because max_pfn does not describe it.
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
---
arch/loongarch/mm/init.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c
index 4b46c5d30708d..bb7a17bdb0e51 100644
--- a/arch/loongarch/mm/init.c
+++ b/arch/loongarch/mm/init.c
@@ -146,6 +146,11 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end,
#if CONFIG_PGTABLE_LEVELS == 2
return vmemmap_populate_basepages(start, end, node, NULL);
#else
+ unsigned long vmemmap_end = (unsigned long)pfn_to_page(max_pfn);
+
+ if (!altmap && (start & PMD_MASK) + PMD_SIZE > vmemmap_end)
+ return vmemmap_populate_basepages(start, end, node, NULL);
+
return vmemmap_populate_hugepages(start, end, node, NULL);
#endif
}
--
2.39.5
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [RFC PATCH] LoongArch: mm: avoid backing vmemmap beyond max_pfn
2026-10-21 6:21 [RFC PATCH] LoongArch: mm: avoid backing vmemmap beyond max_pfn Wentao Guan
@ 2026-10-21 7:23 ` Muchun Song
0 siblings, 0 replies; 2+ messages in thread
From: Muchun Song @ 2026-10-21 7:23 UTC (permalink / raw)
To: Wentao Guan
Cc: chenhuacai, kernel, loongarch, linux-kernel, linux-mm, akpm, rppt, david
> On Oct 21, 2026, at 14:21, Wentao Guan <guanwentao@uniontech.com> wrote:
>
> A PMD maps 32MiB of vmemmap on LoongArch with 16KiB base pages, while a
> 512MiB section only needs 2MiB. vmemmap_populate() is called for each
> section and vmemmap_populate_hugepages() installs a PMD mapping for the
> whole PMD, so the last PMD also backs struct pages for PFNs beyond
> max_pfn.
>
> On a 34GiB system 160MiB of vmemmap is mapped although 136MiB is
> needed. The extra 24MiB describes PFNs that do not exist.
Your commit messages are very detailed, but I don't really understand the
problem you're trying to solve. What issue did you run into, and what was
the resulting impact?
Thanks,
Muchun
>
> Other architectures handle this differently. On x86, arm64 with 4KiB
> pages, and riscv, the PMD covers exactly one section's vmemmap, so the
> huge page path never maps beyond the populated range; x86 tracks
> partially used PMDs with PAGE_UNUSED for memory hotremove. arm64 uses
> base pages for 16KiB and 64KiB kernels. s390 deliberately keeps using
> 1MiB frames even for partially used PMDs because vmemmap_populate() is
> called per section and falling back would add page tables. powerpc
> radix falls back to base pages only when the altmap cannot back a full
> PMD or the allocation fails, and powerpc hash maps the vmemmap with the
> linear mapping page size, which can exceed a section as well.
>
> With 16KiB pages the LoongArch PMD is 16 times the vmemmap of one
> section. Moving the whole vmemmap to base pages, as arm64 does for
> 16KiB and 64KiB, would also remove the tail, but it would give up PMD
> mappings for the 128MiB that is fully populated. Use base pages only
> for the PMD that extends beyond pfn_to_page(max_pfn) and keep huge
> mappings for the rest.
>
> The altmap case is left alone because max_pfn does not describe it.
>
> Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
> ---
> arch/loongarch/mm/init.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/loongarch/mm/init.c b/arch/loongarch/mm/init.c
> index 4b46c5d30708d..bb7a17bdb0e51 100644
> --- a/arch/loongarch/mm/init.c
> +++ b/arch/loongarch/mm/init.c
> @@ -146,6 +146,11 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end,
> #if CONFIG_PGTABLE_LEVELS == 2
> return vmemmap_populate_basepages(start, end, node, NULL);
> #else
> + unsigned long vmemmap_end = (unsigned long)pfn_to_page(max_pfn);
> +
> + if (!altmap && (start & PMD_MASK) + PMD_SIZE > vmemmap_end)
> + return vmemmap_populate_basepages(start, end, node, NULL);
> +
> return vmemmap_populate_hugepages(start, end, node, NULL);
> #endif
> }
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-21 7:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-21 6:21 [RFC PATCH] LoongArch: mm: avoid backing vmemmap beyond max_pfn Wentao Guan
2026-10-21 7:23 ` Muchun Song
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®