Skip to content

Commit 94dab12

Browse files
Dev Jainakpm00
authored andcommitted
mm: call pointers to ptes as ptep
Patch series "Optimize mremap() for large folios", v4. Currently move_ptes() iterates through ptes one by one. If the underlying folio mapped by the ptes is large, we can process those ptes in a batch using folio_pte_batch(), thus clearing and setting the PTEs in one go. For arm64 specifically, this results in a 16x reduction in the number of ptep_get() calls (since on a contig block, ptep_get() on arm64 will iterate through all 16 entries to collect a/d bits), and we also elide extra TLBIs through get_and_clear_full_ptes, replacing ptep_get_and_clear. Mapping 1M of memory with 64K folios, memsetting it, remapping it to src + 1M, and munmapping it 10,000 times, the average execution time reduces from 1.9 to 1.2 seconds, giving a 37% performance optimization, on Apple M3 (arm64). No regression is observed for small folios. Test program for reference: #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> #include <string.h> #include <errno.h> #define SIZE (1UL << 20) // 1M int main(void) { void *new_addr, *addr; for (int i = 0; i < 10000; ++i) { addr = mmap((void *)(1UL << 30), SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { perror("mmap"); return 1; } memset(addr, 0xAA, SIZE); new_addr = mremap(addr, SIZE, SIZE, MREMAP_MAYMOVE | MREMAP_FIXED, addr + SIZE); if (new_addr != (addr + SIZE)) { perror("mremap"); return 1; } munmap(new_addr, SIZE); } } This patch (of 2): Avoid confusion between pte_t* and pte_t data types by suffixing pointer type variables with p. No functional change. Link: https://lkml.kernel.org/r/20250610035043.75448-1-dev.jain@arm.com Link: https://lkml.kernel.org/r/20250610035043.75448-2-dev.jain@arm.com Signed-off-by: Dev Jain <dev.jain@arm.com> Reviewed-by: Barry Song <baohua@kernel.org> Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com> Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Acked-by: David Hildenbrand <david@redhat.com> Reviewed-by: Pedro Falcato <pfalcato@suse.de> Cc: Bang Li <libang.li@antgroup.com> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: bibo mao <maobibo@loongson.cn> Cc: Hugh Dickins <hughd@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jann Horn <jannh@google.com> Cc: Lance Yang <ioworker0@gmail.com> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Peter Xu <peterx@redhat.com> Cc: Qi Zheng <zhengqi.arch@bytedance.com> Cc: Ryan Roberts <ryan.roberts@arm.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Yang Shi <yang@os.amperecomputing.com> Cc: Zi Yan <ziy@nvidia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent cce3510 commit 94dab12

File tree

1 file changed

+16
-15
lines changed

1 file changed

+16
-15
lines changed

mm/mremap.c

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ static int move_ptes(struct pagetable_move_control *pmc,
176176
struct vm_area_struct *vma = pmc->old;
177177
bool need_clear_uffd_wp = vma_has_uffd_without_event_remap(vma);
178178
struct mm_struct *mm = vma->vm_mm;
179-
pte_t *old_pte, *new_pte, pte;
179+
pte_t *old_ptep, *new_ptep;
180+
pte_t pte;
180181
pmd_t dummy_pmdval;
181182
spinlock_t *old_ptl, *new_ptl;
182183
bool force_flush = false;
@@ -211,8 +212,8 @@ static int move_ptes(struct pagetable_move_control *pmc,
211212
* We don't have to worry about the ordering of src and dst
212213
* pte locks because exclusive mmap_lock prevents deadlock.
213214
*/
214-
old_pte = pte_offset_map_lock(mm, old_pmd, old_addr, &old_ptl);
215-
if (!old_pte) {
215+
old_ptep = pte_offset_map_lock(mm, old_pmd, old_addr, &old_ptl);
216+
if (!old_ptep) {
216217
err = -EAGAIN;
217218
goto out;
218219
}
@@ -223,10 +224,10 @@ static int move_ptes(struct pagetable_move_control *pmc,
223224
* mmap_lock, so this new_pte page is stable, so there is no need to get
224225
* pmdval and do pmd_same() check.
225226
*/
226-
new_pte = pte_offset_map_rw_nolock(mm, new_pmd, new_addr, &dummy_pmdval,
227+
new_ptep = pte_offset_map_rw_nolock(mm, new_pmd, new_addr, &dummy_pmdval,
227228
&new_ptl);
228-
if (!new_pte) {
229-
pte_unmap_unlock(old_pte, old_ptl);
229+
if (!new_ptep) {
230+
pte_unmap_unlock(old_ptep, old_ptl);
230231
err = -EAGAIN;
231232
goto out;
232233
}
@@ -235,14 +236,14 @@ static int move_ptes(struct pagetable_move_control *pmc,
235236
flush_tlb_batched_pending(vma->vm_mm);
236237
arch_enter_lazy_mmu_mode();
237238

238-
for (; old_addr < old_end; old_pte++, old_addr += PAGE_SIZE,
239-
new_pte++, new_addr += PAGE_SIZE) {
240-
VM_WARN_ON_ONCE(!pte_none(*new_pte));
239+
for (; old_addr < old_end; old_ptep++, old_addr += PAGE_SIZE,
240+
new_ptep++, new_addr += PAGE_SIZE) {
241+
VM_WARN_ON_ONCE(!pte_none(*new_ptep));
241242

242-
if (pte_none(ptep_get(old_pte)))
243+
if (pte_none(ptep_get(old_ptep)))
243244
continue;
244245

245-
pte = ptep_get_and_clear(mm, old_addr, old_pte);
246+
pte = ptep_get_and_clear(mm, old_addr, old_ptep);
246247
/*
247248
* If we are remapping a valid PTE, make sure
248249
* to flush TLB before we drop the PTL for the
@@ -260,15 +261,15 @@ static int move_ptes(struct pagetable_move_control *pmc,
260261
pte = move_soft_dirty_pte(pte);
261262

262263
if (need_clear_uffd_wp && pte_marker_uffd_wp(pte))
263-
pte_clear(mm, new_addr, new_pte);
264+
pte_clear(mm, new_addr, new_ptep);
264265
else {
265266
if (need_clear_uffd_wp) {
266267
if (pte_present(pte))
267268
pte = pte_clear_uffd_wp(pte);
268269
else if (is_swap_pte(pte))
269270
pte = pte_swp_clear_uffd_wp(pte);
270271
}
271-
set_pte_at(mm, new_addr, new_pte, pte);
272+
set_pte_at(mm, new_addr, new_ptep, pte);
272273
}
273274
}
274275

@@ -277,8 +278,8 @@ static int move_ptes(struct pagetable_move_control *pmc,
277278
flush_tlb_range(vma, old_end - len, old_end);
278279
if (new_ptl != old_ptl)
279280
spin_unlock(new_ptl);
280-
pte_unmap(new_pte - 1);
281-
pte_unmap_unlock(old_pte - 1, old_ptl);
281+
pte_unmap(new_ptep - 1);
282+
pte_unmap_unlock(old_ptep - 1, old_ptl);
282283
out:
283284
if (pmc->need_rmap_locks)
284285
drop_rmap_locks(vma);

0 commit comments

Comments
 (0)