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 >