On 26/01/2026 09:26, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <[email protected]>
> 
> Instead of blindly overwriting existing live entries with the contiguous
> bit cleared when mapping DRAM regions, check whether the contiguous
> region in question starts with a descriptor that has the valid bit set
> and the contiguous bit cleared, and in that case, leave the contiguous
> bit unset on the entire region. This permits the logic of mapping the
> kernel's linear alias to be simplified in a subsequent patch.
> 
> Note that not setting the contiguous bit on any of the descriptors in
> the contiguous region can only result in an invalid configuration if it
> was already invalid to begin with.
> 
> Signed-off-by: Ard Biesheuvel <[email protected]>

Reviewed-by: Ryan Roberts <[email protected]>

> ---
>  arch/arm64/include/asm/pgtable.h | 4 ++++
>  arch/arm64/mm/mmu.c              | 6 ++++--
>  2 files changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/pgtable.h 
> b/arch/arm64/include/asm/pgtable.h
> index 64d5f1d9cce9..cb2c4525e49a 100644
> --- a/arch/arm64/include/asm/pgtable.h
> +++ b/arch/arm64/include/asm/pgtable.h
> @@ -224,6 +224,10 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t 
> phys)
>   * Returns true if the pte is valid and has the contiguous bit set.
>   */
>  #define pte_valid_cont(pte)  (pte_valid(pte) && pte_cont(pte))
> +/*
> + * Returns true if the pte is valid and has the contiguous bit cleared.
> + */
> +#define pte_valid_noncont(pte)       (pte_valid(pte) && !pte_cont(pte))
>  /*
>   * Could the pte be present in the TLB? We must check mm_tlb_flush_pending
>   * so that we don't erroneously return false for pages that have been
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 28cc3cda042c..d7faa98f427c 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -230,7 +230,8 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long 
> addr,
>  
>               /* use a contiguous mapping if the range is suitably aligned */
>               if ((((addr | next | phys) & ~CONT_PTE_MASK) == 0) &&
> -                 (flags & NO_CONT_MAPPINGS) == 0)
> +                 (flags & NO_CONT_MAPPINGS) == 0 &&
> +                 !pte_valid_noncont(__ptep_get(ptep)))
>                       __prot = __pgprot(pgprot_val(prot) | PTE_CONT);
>  
>               init_pte(ptep, addr, next, phys, __prot);
> @@ -330,7 +331,8 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long 
> addr,
>  
>               /* use a contiguous mapping if the range is suitably aligned */
>               if ((((addr | next | phys) & ~CONT_PMD_MASK) == 0) &&
> -                 (flags & NO_CONT_MAPPINGS) == 0)
> +                 (flags & NO_CONT_MAPPINGS) == 0 &&
> +                 !pte_valid_noncont(pmd_pte(READ_ONCE(*pmdp))))
>                       __prot = __pgprot(pgprot_val(prot) | PTE_CONT);
>  
>               ret = init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, 
> flags);


Reply via email to