On Sun, 25 Jan 2026 00:52:12 -0500, guoren@kernel.org wrote: > Unlike no4lvl, no5lvl still continues detect satp, which > requires va=pa mapping. When pa=0x800000000000, no5lvl > would fail in Sv48 mode due to an illegal VA value of > 0x800000000000. > > So, prevent detecting the satp flow for no5lvl, when > vaddr is invalid. Add the is_vaddr_valid() function for > checking. > > Fixes: 26e7aacb83df ("riscv: Allow to downgrade paging mode from the command line") > Cc: Alexandre Ghiti > Cc: Björn Töpel > Signed-off-by: Guo Ren (Alibaba DAMO Academy) > --- > Changelog: > > v2: > - Use is_vaddr_valid() instead of simple return. > - Don't change the original no5lvl code logic. > > v1: > https://lore.kernel.org/linux-riscv/20260118145441.291302-1-guoren@kernel.org/ > --- > arch/riscv/mm/init.c | 25 +++++++++++++++++++++++++ > 1 file changed, 25 insertions(+) > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index addb8a9305be..bfea9f73e703 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -852,6 +852,27 @@ static void __init set_mmap_rnd_bits_max(void) > mmap_rnd_bits_max = MMAP_VA_BITS - PAGE_SHIFT - 3; > } > > +static bool __init is_vaddr_valid(unsigned long va) > +{ > + unsigned long up = 0; > + > + switch (satp_mode) { > + case SATP_MODE_39: > + up = 1UL << 38; > + break; > + case SATP_MODE_48: > + up = 1UL << 47; > + break; > + case SATP_MODE_57: > + up = 1UL << 56; > + break; > + default: > + return false; > + } > + > + return (va < up) || (va >= (ULONG_MAX - up + 1)); > +} > + > /* > * There is a simple way to determine if 4-level is supported by the > * underlying hardware: establish 1:1 mapping in 4-level page table mode > @@ -893,6 +914,9 @@ static __init void set_satp_mode(uintptr_t dtb_pa) > set_satp_mode_pmd + PMD_SIZE, > PMD_SIZE, PAGE_KERNEL_EXEC); > retry: > + if (!is_vaddr_valid(set_satp_mode_pmd)) > + goto out; > + > create_pgd_mapping(early_pg_dir, > set_satp_mode_pmd, > pgtable_l5_enabled ? > @@ -915,6 +939,7 @@ static __init void set_satp_mode(uintptr_t dtb_pa) > disable_pgtable_l4(); > } > > +out: > memset(early_pg_dir, 0, PAGE_SIZE); > memset(early_p4d, 0, PAGE_SIZE); > memset(early_pud, 0, PAGE_SIZE); Tested-by: Chen Pei Thanks, Pei