arm64: mm: Make PUD folding check in set_pud() a runtime check
authorArd Biesheuvel <ardb@kernel.org>
Fri, 16 Feb 2024 23:59:44 +0000 (00:59 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Mon, 19 Feb 2024 16:04:55 +0000 (16:04 +0000)
When set_pud() is called on a 4-level paging build config that runs with
3 levels at runtime (which happens with 16k page size builds with
support for LPA2), the updated entry is in fact a PGD in
swapper_pg_dir[], and this is mapped read-only after boot.

So in this case, the existing check needs to be performed as well, even
though __PAGETABLE_PUD_FOLDED is not #define'd. So replace the #ifdef
with a call to pgtable_l4_enabled().

Cc: Will Deacon <will@kernel.org>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20240216235944.3677178-2-ardb+git@google.com
Reviewed-by: Itaru Kitayama <itaru.kitayama@fujitsu.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/pgtable.h

index b3c716fa81212d321729a05fcd43f22804786828..8bec85350865a173cab3b68cecf6c385d4409834 100644 (file)
@@ -699,14 +699,14 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
 #define pud_user(pud)          pte_user(pud_pte(pud))
 #define pud_user_exec(pud)     pte_user_exec(pud_pte(pud))
 
+static inline bool pgtable_l4_enabled(void);
+
 static inline void set_pud(pud_t *pudp, pud_t pud)
 {
-#ifdef __PAGETABLE_PUD_FOLDED
-       if (in_swapper_pgdir(pudp)) {
+       if (!pgtable_l4_enabled() && in_swapper_pgdir(pudp)) {
                set_swapper_pgd((pgd_t *)pudp, __pgd(pud_val(pud)));
                return;
        }
-#endif /* __PAGETABLE_PUD_FOLDED */
 
        WRITE_ONCE(*pudp, pud);