[PATCH v2] LoongArch: mm: Define DIRECT_MAP_PHYSMEM_END

Han Gao <[email protected]>
Newsgroups dev.linux.lists.loongarch,org.infradead.lists.linux-riscv,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
get_free_mem_region() and mhp_get_pluggable_range() bound their
search to DIRECT_MAP_PHYSMEM_END.  LoongArch does not define it, so
the fallback in include/linux/mm.h applies: under
CONFIG_SPARSEMEM_VMEMMAP it is (1ULL << MAX_PHYSMEM_BITS) - 1, a
compile-time constant that does not adapt to the CPU's physical
address bits (cpu_pabits, probed from CPUCFG1).

The vmemmap window only covers physical space below 2^(cpu_pabits+1)
(VMEMMAP_SIZE), so on CPUs with fewer physical address bits than
MAX_PHYSMEM_BITS the fallback allows get_free_mem_region() to return
a ZONE_DEVICE region outside the vmemmap window;
vmemmap_populate() then wraps the memmap range around and maps it
into low memory, silently corrupting the page tables.  The same
search also picked the top-of-address-space region that crashed
memmap_init_zone_device() with amdkfd on 3C6000 in 6.16 [1];
commit 2969b42c8f99 ("LoongArch/mm: align vmemmap to maximal folio
size") keeps that region in bounds on current 3C6000 configs, but
CPUs with smaller cpu_pabits (e.g. the 2K series) are still
affected.

Define DIRECT_MAP_PHYSMEM_END as the vmemmap-covered physical
range, (1ULL << (cpu_pabits + 1)) - 1, capped at
(1ULL << MAX_PHYSMEM_BITS) - 1 under CONFIG_SPARSEMEM, mirroring
commit f3336b48cf9d ("riscv: mm: Define DIRECT_MAP_PHYSMEM_END").

[1] https://lore.kernel.org/amd-gfx/[email protected]/

Cc: [email protected] # v6.13+
Signed-off-by: Han Gao <[email protected]>
---
Changes in v2:
- Redefine DIRECT_MAP_PHYSMEM_END as the vmemmap-covered range
  (1ULL << (cpu_pabits + 1)) - 1, capped at
  (1ULL << MAX_PHYSMEM_BITS) - 1 under CONFIG_SPARSEMEM, per Huacai
  Chen's review (the previous (1ULL << cpu_pabits) - 1 wrongly
  limits CPUs with 48-bit physical addresses).
- Note that 3C6000 has 48-bit physical addresses as well.
- v1: https://lore.kernel.org/all/[email protected]/

 arch/loongarch/include/asm/pgtable.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h
index 223528c04d73..8395aea209b5 100644
--- a/arch/loongarch/include/asm/pgtable.h
+++ b/arch/loongarch/include/asm/pgtable.h
@@ -125,6 +125,14 @@ struct vm_area_struct;
 
 #endif
 
+/* Needed to limit get_free_mem_region() */
+#ifndef CONFIG_SPARSEMEM
+#define DIRECT_MAP_PHYSMEM_END ((1ULL << (cpu_pabits + 1)) - 1)
+#else
+#define DIRECT_MAP_PHYSMEM_END \
+	min((1ULL << (cpu_pabits + 1)) - 1, (1ULL << MAX_PHYSMEM_BITS) - 1)
+#endif
+
 #define ptep_get(ptep) READ_ONCE(*(ptep))
 #define pmdp_get(pmdp) READ_ONCE(*(pmdp))
 
-- 
2.47.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.