Re: [PATCH] LoongArch: mm: Define DIRECT_MAP_PHYSMEM_END

Huacai Chen <[email protected]>
Newsgroups dev.linux.lists.loongarch,org.infradead.lists.linux-riscv,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <CAAhV-H7FcV73VB58=zyscfCvP1L5sJ0CZTZ2EZNZkYB=X5dhAg@mail.gmail.com>
Hi, Han,

On Tue, Aug 11, 2026 at 7:58 PM Han Gao <[email protected]> wrote:
>
> 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 physical address
> bits of the CPU (cpu_pabits, probed from CPUCFG1: 48 on
> 3A5000/3A6000, 47 on 3C6000, 40 on the 2K series).
As far as I know, Loongson-3C6000 is also PA48.

>
> The vmemmap window only covers physical space below 2^(cpu_pabits+1)
> (VMEMMAP_SIZE), so on CPUs with fewer than 48 physical address bits
> get_free_mem_region() may hand ZONE_DEVICE a region with no struct
> page backing:
>
> - On the 2K series the region returned at the top of the 48-bit
>   physical space is outside the vmemmap window; vmemmap_populate()
>   wraps the range around and maps it into low memory, silently
>   corrupting the page tables.
> - On 3C6000 the vmemmap range of the region's last section used to
>   end exactly at 2^64 and wrap to 0, leaving vmemmap_populate() with
>   nothing to map, so memmap_init_zone_device() faulted while writing
>   struct page (reported with amdkfd on 6.16 [1]).  Commit 2969b42c8f99
>   ("LoongArch/mm: align vmemmap to maximal folio size") moved the
>   vmemmap base down by one PMD, which keeps that section in bounds on
>   current 3C6000 configs, but the 2K series is still affected and the
>   3C6000 case only holds for the current vmemmap layout.
>
> Define DIRECT_MAP_PHYSMEM_END as (1ULL << cpu_pabits) - 1 so that
> both searches stay within the vmemmap-covered physical space,
> 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]>
> ---
>  arch/loongarch/include/asm/pgtable.h | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/arch/loongarch/include/asm/pgtable.h b/arch/loongarch/include/asm/pgtable.h
> index 223528c04d73..244931e4bc58 100644
> --- a/arch/loongarch/include/asm/pgtable.h
> +++ b/arch/loongarch/include/asm/pgtable.h
> @@ -125,6 +125,13 @@ struct vm_area_struct;
>
>  #endif
>
> +/* Needed to limit get_free_mem_region() */
> +#if defined(CONFIG_FLATMEM) || defined(CONFIG_SPARSEMEM_VMEMMAP)
> +#define DIRECT_MAP_PHYSMEM_END ((1ULL << cpu_pabits) - 1)
> +#elif defined(CONFIG_SPARSEMEM)
> +/* DIRECT_MAP_PHYSMEM_END is not limited by VA space assignment in this case */
> +#endif
 ((1ULL << cpu_pabits) - 1) is not always smaller than  (1ULL <<
MAX_PHYSMEM_BITS) - 1.

So I think a better way is:
+#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

Huacai

> +
>  #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.