]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
riscv: mm: Fixup no5lvl failure when vaddr is invalid
authorGuo Ren (Alibaba DAMO Academy) <guoren@kernel.org>
Sun, 25 Jan 2026 05:52:12 +0000 (00:52 -0500)
committerPaul Walmsley <pjw@kernel.org>
Sat, 2 May 2026 03:18:58 +0000 (21:18 -0600)
Unlike no4lvl, no5lvl still continues to 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 <alexghiti@rivosinc.com>
Cc: Björn Töpel <bjorn@rivosinc.com>
Signed-off-by: Guo Ren (Alibaba DAMO Academy) <guoren@kernel.org>
Tested-by: Fangyu Yu <fangyu.yu@linux.alibaba.com>
Link: https://patch.msgid.link/20260125055212.433163-1-guoren@kernel.org
[pjw@kernel.org: cleaned up commit message]
Signed-off-by: Paul Walmsley <pjw@kernel.org>
arch/riscv/mm/init.c

index decd7df40fa421550cb0d6c7ff3b8016f41b402f..fa8d2f6f554b57a6e438c9caaa04637017633166 100644 (file)
@@ -792,6 +792,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
@@ -833,6 +854,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 ?
@@ -855,6 +879,7 @@ retry:
                disable_pgtable_l4();
        }
 
+out:
        memset(early_pg_dir, 0, PAGE_SIZE);
        memset(early_p4d, 0, PAGE_SIZE);
        memset(early_pud, 0, PAGE_SIZE);