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);
