Skip to content

Commit 6f0e114

Browse files
Baolin Wangakpm00
authored andcommitted
arm64: mm: support batch clearing of the young flag for large folios
Currently, contpte_ptep_test_and_clear_young() and contpte_ptep_clear_flush_young() only clear the young flag and flush TLBs for PTEs within the contiguous range. To support batch PTE operations for other sized large folios in the following patches, adding a new parameter to specify the number of PTEs that map consecutive pages of the same large folio in a single VMA and a single page table. While we are at it, rename the functions to maintain consistency with other contpte_*() functions. Link: https://lkml.kernel.org/r/5644250dcc0417278c266ad37118d27f541fd052.1770645603.git.baolin.wang@linux.alibaba.com Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com> Reviewed-by: Ryan Roberts <ryan.roberts@arm.com> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Cc: Barry Song <baohua@kernel.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Harry Yoo <harry.yoo@oracle.com> Cc: Jann Horn <jannh@google.com> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Cc: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Rik van Riel <riel@surriel.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Will Deacon <will@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 67d59bd commit 6f0e114

2 files changed

Lines changed: 25 additions & 20 deletions

File tree

arch/arm64/include/asm/pgtable.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,10 +1648,10 @@ extern void contpte_clear_full_ptes(struct mm_struct *mm, unsigned long addr,
16481648
extern pte_t contpte_get_and_clear_full_ptes(struct mm_struct *mm,
16491649
unsigned long addr, pte_t *ptep,
16501650
unsigned int nr, int full);
1651-
extern int contpte_ptep_test_and_clear_young(struct vm_area_struct *vma,
1652-
unsigned long addr, pte_t *ptep);
1653-
extern int contpte_ptep_clear_flush_young(struct vm_area_struct *vma,
1654-
unsigned long addr, pte_t *ptep);
1651+
int contpte_test_and_clear_young_ptes(struct vm_area_struct *vma,
1652+
unsigned long addr, pte_t *ptep, unsigned int nr);
1653+
int contpte_clear_flush_young_ptes(struct vm_area_struct *vma,
1654+
unsigned long addr, pte_t *ptep, unsigned int nr);
16551655
extern void contpte_wrprotect_ptes(struct mm_struct *mm, unsigned long addr,
16561656
pte_t *ptep, unsigned int nr);
16571657
extern int contpte_ptep_set_access_flags(struct vm_area_struct *vma,
@@ -1823,7 +1823,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
18231823
if (likely(!pte_valid_cont(orig_pte)))
18241824
return __ptep_test_and_clear_young(vma, addr, ptep);
18251825

1826-
return contpte_ptep_test_and_clear_young(vma, addr, ptep);
1826+
return contpte_test_and_clear_young_ptes(vma, addr, ptep, 1);
18271827
}
18281828

18291829
#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
@@ -1835,7 +1835,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
18351835
if (likely(!pte_valid_cont(orig_pte)))
18361836
return __ptep_clear_flush_young(vma, addr, ptep);
18371837

1838-
return contpte_ptep_clear_flush_young(vma, addr, ptep);
1838+
return contpte_clear_flush_young_ptes(vma, addr, ptep, 1);
18391839
}
18401840

18411841
#define wrprotect_ptes wrprotect_ptes

arch/arm64/mm/contpte.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,9 @@ pte_t contpte_get_and_clear_full_ptes(struct mm_struct *mm,
508508
}
509509
EXPORT_SYMBOL_GPL(contpte_get_and_clear_full_ptes);
510510

511-
int contpte_ptep_test_and_clear_young(struct vm_area_struct *vma,
512-
unsigned long addr, pte_t *ptep)
511+
int contpte_test_and_clear_young_ptes(struct vm_area_struct *vma,
512+
unsigned long addr, pte_t *ptep,
513+
unsigned int nr)
513514
{
514515
/*
515516
* ptep_clear_flush_young() technically requires us to clear the access
@@ -518,41 +519,45 @@ int contpte_ptep_test_and_clear_young(struct vm_area_struct *vma,
518519
* contig range when the range is covered by a single folio, we can get
519520
* away with clearing young for the whole contig range here, so we avoid
520521
* having to unfold.
522+
*
523+
* The 'nr' means consecutive (present) PTEs that map consecutive pages
524+
* of the same large folio in a single VMA and a single page table.
521525
*/
522526

527+
unsigned long end = addr + nr * PAGE_SIZE;
523528
int young = 0;
524-
int i;
525529

526-
ptep = contpte_align_down(ptep);
527-
addr = ALIGN_DOWN(addr, CONT_PTE_SIZE);
528-
529-
for (i = 0; i < CONT_PTES; i++, ptep++, addr += PAGE_SIZE)
530+
ptep = contpte_align_addr_ptep(&addr, &end, ptep, nr);
531+
for (; addr != end; ptep++, addr += PAGE_SIZE)
530532
young |= __ptep_test_and_clear_young(vma, addr, ptep);
531533

532534
return young;
533535
}
534-
EXPORT_SYMBOL_GPL(contpte_ptep_test_and_clear_young);
536+
EXPORT_SYMBOL_GPL(contpte_test_and_clear_young_ptes);
535537

536-
int contpte_ptep_clear_flush_young(struct vm_area_struct *vma,
537-
unsigned long addr, pte_t *ptep)
538+
int contpte_clear_flush_young_ptes(struct vm_area_struct *vma,
539+
unsigned long addr, pte_t *ptep,
540+
unsigned int nr)
538541
{
539542
int young;
540543

541-
young = contpte_ptep_test_and_clear_young(vma, addr, ptep);
544+
young = contpte_test_and_clear_young_ptes(vma, addr, ptep, nr);
542545

543546
if (young) {
547+
unsigned long end = addr + nr * PAGE_SIZE;
548+
549+
contpte_align_addr_ptep(&addr, &end, ptep, nr);
544550
/*
545551
* See comment in __ptep_clear_flush_young(); same rationale for
546552
* eliding the trailing DSB applies here.
547553
*/
548-
addr = ALIGN_DOWN(addr, CONT_PTE_SIZE);
549-
__flush_tlb_range_nosync(vma->vm_mm, addr, addr + CONT_PTE_SIZE,
554+
__flush_tlb_range_nosync(vma->vm_mm, addr, end,
550555
PAGE_SIZE, true, 3);
551556
}
552557

553558
return young;
554559
}
555-
EXPORT_SYMBOL_GPL(contpte_ptep_clear_flush_young);
560+
EXPORT_SYMBOL_GPL(contpte_clear_flush_young_ptes);
556561

557562
void contpte_wrprotect_ptes(struct mm_struct *mm, unsigned long addr,
558563
pte_t *ptep, unsigned int nr)

0 commit comments

Comments
 (0)