* Re: [RFC PATCH 6/7] mm: memory: add mTHP support for wp [not found] ` <226e21a5-8a8e-43a0-bf5f-12a761f49a27@redhat.com> @ 2025-08-15 15:20 ` Vernon Yang 2025-08-16 6:40 ` David Hildenbrand 0 siblings, 1 reply; 3+ messages in thread From: Vernon Yang @ 2025-08-15 15:20 UTC (permalink / raw) To: David Hildenbrand Cc: akpm, lorenzo.stoakes, ziy, baolin.wang, Liam.Howlett, npache, ryan.roberts, dev.jain, baohua, glider, elver, dvyukov, vbabka, rppt, surenb, mhocko, muchun.song, osalvador, shuah, richardcochran, linux-mm, linux-kernel On Thu, Aug 14, 2025 at 01:58:34PM +0200, David Hildenbrand wrote: > On 14.08.25 13:38, Vernon Yang wrote: > > Currently pagefaults on anonymous pages support mthp, and hardware > > features (such as arm64 contpte) can be used to store multiple ptes in > > one TLB entry, reducing the probability of TLB misses. However, when the > > process is forked and the cow is triggered again, the above optimization > > effect is lost, and only 4KB is requested once at a time. > > > > Therefore, make pagefault write-protect copy support mthp to maintain the > > optimization effect of TLB and improve the efficiency of cow pagefault. > > > > vm-scalability usemem shows a great improvement, > > test using: usemem -n 32 --prealloc --prefault 249062617 > > (result unit is KB/s, bigger is better) > > > > | size | w/o patch | w/ patch | delta | > > |-------------|-----------|-----------|---------| > > | baseline 4K | 723041.63 | 717643.21 | -0.75% | > > | mthp 16K | 732871.14 | 799513.18 | +9.09% | > > | mthp 32K | 746060.91 | 836261.83 | +12.09% | > > | mthp 64K | 747333.18 | 855570.43 | +14.48% | > > You're missing two of the most important metrics: COW latency and memory > waste. OK, I will add the above two test later. > > Just imagine what happens if you have PMD-sized THP. > > I would suggest you explore why Redis used to recommend to disable THPs > (hint: tail latency due to COW of way-too-large chunks before we do what we > do today). Thanks for the suggestion, I'm not very familiar with Redis indeed. Currently, this series supports small granularity sizes, such as 16KB, and I will also test redis-benchmark later to see the severity of tail latency. > > So staring at usemem micro-benchmark results is a bit misleading. > > As discussed in the past, I would actually suggest to > > a) Let khugepaged deal with fixing this up later, keeping CoW path > simpler and faster. > b) If we really really have to do this during fault time, limit it to > some order (might even be have to be configurable). This is a good way to add a similar shmem_enabled knob after if need. > > I really think we should keep CoW latency low and instead let khugepaged fix > that up later. (Nico is working on mTHP collapse support) > > [are you handling having a mixture of PageAnonExclusive within a folio > properly? Only staring at R/O PTEs is usually insufficient to determine > whether you can COW or whether you must reuse]. There is no extra processing on PageAnonExclusive here, only judging by R/O PTEs, thank you for pointing it out, and I will look into how to properly handle this situation later. > > -- > Cheers > > David / dhildenb > ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC PATCH 6/7] mm: memory: add mTHP support for wp 2025-08-15 15:20 ` [RFC PATCH 6/7] mm: memory: add mTHP support for wp Vernon Yang @ 2025-08-16 6:40 ` David Hildenbrand 0 siblings, 0 replies; 3+ messages in thread From: David Hildenbrand @ 2025-08-16 6:40 UTC (permalink / raw) To: Vernon Yang Cc: akpm, lorenzo.stoakes, ziy, baolin.wang, Liam.Howlett, npache, ryan.roberts, dev.jain, baohua, glider, elver, dvyukov, vbabka, rppt, surenb, mhocko, muchun.song, osalvador, shuah, richardcochran, linux-mm, linux-kernel On 15.08.25 17:20, Vernon Yang wrote: > On Thu, Aug 14, 2025 at 01:58:34PM +0200, David Hildenbrand wrote: >> On 14.08.25 13:38, Vernon Yang wrote: >>> Currently pagefaults on anonymous pages support mthp, and hardware >>> features (such as arm64 contpte) can be used to store multiple ptes in >>> one TLB entry, reducing the probability of TLB misses. However, when the >>> process is forked and the cow is triggered again, the above optimization >>> effect is lost, and only 4KB is requested once at a time. >>> >>> Therefore, make pagefault write-protect copy support mthp to maintain the >>> optimization effect of TLB and improve the efficiency of cow pagefault. >>> >>> vm-scalability usemem shows a great improvement, >>> test using: usemem -n 32 --prealloc --prefault 249062617 >>> (result unit is KB/s, bigger is better) >>> >>> | size | w/o patch | w/ patch | delta | >>> |-------------|-----------|-----------|---------| >>> | baseline 4K | 723041.63 | 717643.21 | -0.75% | >>> | mthp 16K | 732871.14 | 799513.18 | +9.09% | >>> | mthp 32K | 746060.91 | 836261.83 | +12.09% | >>> | mthp 64K | 747333.18 | 855570.43 | +14.48% | >> >> You're missing two of the most important metrics: COW latency and memory >> waste. > > OK, I will add the above two test later. > >> >> Just imagine what happens if you have PMD-sized THP. >> >> I would suggest you explore why Redis used to recommend to disable THPs >> (hint: tail latency due to COW of way-too-large chunks before we do what we >> do today). > > Thanks for the suggestion, I'm not very familiar with Redis indeed. Currently, > this series supports small granularity sizes, such as 16KB, and I will also > test redis-benchmark later to see the severity of tail latency. > >> >> So staring at usemem micro-benchmark results is a bit misleading. >> >> As discussed in the past, I would actually suggest to >> >> a) Let khugepaged deal with fixing this up later, keeping CoW path >> simpler and faster. >> b) If we really really have to do this during fault time, limit it to >> some order (might even be have to be configurable). > > This is a good way to add a similar shmem_enabled knob after if need. > >> >> I really think we should keep CoW latency low and instead let khugepaged fix >> that up later. (Nico is working on mTHP collapse support) >> >> [are you handling having a mixture of PageAnonExclusive within a folio >> properly? Only staring at R/O PTEs is usually insufficient to determine >> whether you can COW or whether you must reuse]. > > There is no extra processing on PageAnonExclusive here, only judging by R/O PTEs, > thank you for pointing it out, and I will look into how to properly handle > this situation later. Yes, but as I said: I much prefer to let khugepaged handle that. I am not convinced the complexity here is warranted. Nico's patches should soon be in shape to collapse mthp. (see the list) -- Cheers David / dhildenb ^ permalink raw reply [flat|nested] 3+ messages in thread
[parent not found: <b607985d-d319-4b47-9365-0595f7d87f28@redhat.com>]
* Re: [RFC PATCH 6/7] mm: memory: add mTHP support for wp [not found] ` <b607985d-d319-4b47-9365-0595f7d87f28@redhat.com> @ 2025-08-15 15:30 ` Vernon Yang 0 siblings, 0 replies; 3+ messages in thread From: Vernon Yang @ 2025-08-15 15:30 UTC (permalink / raw) To: David Hildenbrand Cc: akpm, lorenzo.stoakes, ziy, baolin.wang, Liam.Howlett, npache, ryan.roberts, dev.jain, baohua, glider, elver, dvyukov, vbabka, rppt, surenb, mhocko, muchun.song, osalvador, shuah, richardcochran, linux-mm, linux-kernel On Thu, Aug 14, 2025 at 02:57:34PM +0200, David Hildenbrand wrote: > On 14.08.25 13:38, Vernon Yang wrote: > > Currently pagefaults on anonymous pages support mthp, and hardware > > features (such as arm64 contpte) can be used to store multiple ptes in > > one TLB entry, reducing the probability of TLB misses. However, when the > > process is forked and the cow is triggered again, the above optimization > > effect is lost, and only 4KB is requested once at a time. > > > > Therefore, make pagefault write-protect copy support mthp to maintain the > > optimization effect of TLB and improve the efficiency of cow pagefault. > > > > vm-scalability usemem shows a great improvement, > > test using: usemem -n 32 --prealloc --prefault 249062617 > > (result unit is KB/s, bigger is better) > > > > | size | w/o patch | w/ patch | delta | > > |-------------|-----------|-----------|---------| > > | baseline 4K | 723041.63 | 717643.21 | -0.75% | > > | mthp 16K | 732871.14 | 799513.18 | +9.09% | > > | mthp 32K | 746060.91 | 836261.83 | +12.09% | > > | mthp 64K | 747333.18 | 855570.43 | +14.48% | > > > > Signed-off-by: Vernon Yang <vernon2gm@gmail.com> > > --- > > include/linux/huge_mm.h | 3 + > > mm/memory.c | 174 ++++++++++++++++++++++++++++++++++++---- > > 2 files changed, 163 insertions(+), 14 deletions(-) > > > > diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h > > index 2f190c90192d..d1ebbe0636fb 100644 > > --- a/include/linux/huge_mm.h > > +++ b/include/linux/huge_mm.h > > @@ -132,6 +132,9 @@ enum mthp_stat_item { > > MTHP_STAT_SHMEM_ALLOC, > > MTHP_STAT_SHMEM_FALLBACK, > > MTHP_STAT_SHMEM_FALLBACK_CHARGE, > > + MTHP_STAT_WP_FAULT_ALLOC, > > + MTHP_STAT_WP_FAULT_FALLBACK, > > + MTHP_STAT_WP_FAULT_FALLBACK_CHARGE, > > MTHP_STAT_SPLIT, > > MTHP_STAT_SPLIT_FAILED, > > MTHP_STAT_SPLIT_DEFERRED, > > diff --git a/mm/memory.c b/mm/memory.c > > index 8dd869b0cfc1..ea84c49cc975 100644 > > --- a/mm/memory.c > > +++ b/mm/memory.c > > @@ -3344,6 +3344,21 @@ static inline int __wp_page_copy_user(struct page *dst, struct page *src, > > return ret; > > } > > +static inline int __wp_folio_copy_user(struct folio *dst, struct folio *src, > > + unsigned int offset, > > + struct vm_fault *vmf) > > +{ > > + struct vm_area_struct *vma = vmf->vma; > > + void __user *uaddr; > > + > > + if (likely(src)) > > + return copy_user_large_folio(dst, src, offset, vmf->address, vma); > > + > > + uaddr = (void __user *)ALIGN_DOWN(vmf->address, folio_size(dst)); > > + > > + return copy_folio_from_user(dst, uaddr, 0); > > +} > > + > > static gfp_t __get_fault_gfp_mask(struct vm_area_struct *vma) > > { > > struct file *vm_file = vma->vm_file; > > @@ -3527,6 +3542,119 @@ vm_fault_t __vmf_anon_prepare(struct vm_fault *vmf) > > return ret; > > } > > +static inline unsigned long thp_wp_suitable_orders(struct folio *old_folio, > > + unsigned long orders) > > +{ > > + int order, max_order; > > + > > + max_order = folio_order(old_folio); > > + order = highest_order(orders); > > + > > + /* > > + * Since need to copy content from the old folio to the new folio, the > > + * maximum size of the new folio will not exceed the old folio size, > > + * so filter the inappropriate order. > > + */ > > + while (orders) { > > + if (order <= max_order) > > + break; > > + order = next_order(&orders, order); > > + } > > + > > + return orders; > > +} > > + > > +static bool pte_range_readonly(pte_t *pte, int nr_pages) > > +{ > > + int i; > > + > > + for (i = 0; i < nr_pages; i++) { > > + if (pte_write(ptep_get_lockless(pte + i))) > > + return false; > > + } > > + > > + return true; > > +} > > + > > +static struct folio *alloc_wp_folio(struct vm_fault *vmf, bool pfn_is_zero) > > +{ > > + struct vm_area_struct *vma = vmf->vma; > > +#ifdef CONFIG_TRANSPARENT_HUGEPAGE > > + unsigned long orders; > > + struct folio *folio; > > + unsigned long addr; > > + pte_t *pte; > > + gfp_t gfp; > > + int order; > > + > > + /* > > + * If uffd is active for the vma we need per-page fault fidelity to > > + * maintain the uffd semantics. > > + */ > > + if (unlikely(userfaultfd_armed(vma))) > > + goto fallback; > > + > > + if (pfn_is_zero || !vmf->page) > > + goto fallback; > > + > > + /* > > + * Get a list of all the (large) orders below folio_order() that are enabled > > + * for this vma. Then filter out the orders that can't be allocated over > > + * the faulting address and still be fully contained in the vma. > > + */ > > + orders = thp_vma_allowable_orders(vma, vma->vm_flags, > > + TVA_IN_PF | TVA_ENFORCE_SYSFS, BIT(PMD_ORDER) - 1); > > + orders = thp_vma_suitable_orders(vma, vmf->address, orders); > > + orders = thp_wp_suitable_orders(page_folio(vmf->page), orders); > > + > > + if (!orders) > > + goto fallback; > > + > > + pte = pte_offset_map(vmf->pmd, vmf->address & PMD_MASK); > > + if (!pte) > > + return ERR_PTR(-EAGAIN); > > + > > + /* > > + * Find the highest order where the aligned range is completely readonly. > > + * Note that all remaining orders will be completely readonly. > > + */ > > + order = highest_order(orders); > > + while (orders) { > > + addr = ALIGN_DOWN(vmf->address, PAGE_SIZE << order); > > + if (pte_range_readonly(pte + pte_index(addr), 1 << order)) > > + break; > > + order = next_order(&orders, order); > > + } > > + > > + pte_unmap(pte); > > + > > + if (!orders) > > + goto fallback; > > + > > + /* Try allocating the highest of the remaining orders. */ > > + gfp = vma_thp_gfp_mask(vma); > > + while (orders) { > > + addr = ALIGN_DOWN(vmf->address, PAGE_SIZE << order); > > + folio = vma_alloc_folio(gfp, order, vma, addr); > > + if (folio) { > > + if (mem_cgroup_charge(folio, vma->vm_mm, gfp)) { > > + count_mthp_stat(order, MTHP_STAT_WP_FAULT_FALLBACK_CHARGE); > > + folio_put(folio); > > + goto next; > > + } > > + folio_throttle_swaprate(folio, gfp); > > + return folio; > > + } > > I might be missing something, but besides the PAE issue I think there are > more issues lurking here: > > * Are you scanning outside of the current VMA, and some PTEs might > actually belong to a !writable VMA? In thp_vma_suitable_order(), it not exceed the size of the current VMA, and all PTEs belong to current writable VMA. > * Are you assuming that the R/O PTE range is actually mapping all-pages > from the same large folio? Yes, is there a potential problem with this assumption? maybe I'm missing something. > > I am not sure if you are assuming some natural alignment of the old folio. > Due to mremap() that must not be the case. Here it is assumed that the virtual address aligns the old folio size, the mremap would break that assumption, right? > > Which stresses my point: khugepaged might be the better place to re-collapse > where reasonable, avoiding further complexity in our CoW handling. > > -- > Cheers > > David / dhildenb > ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-08-16 6:40 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20250814113813.4533-1-vernon2gm@gmail.com>
[not found] ` <20250814113813.4533-7-vernon2gm@gmail.com>
[not found] ` <226e21a5-8a8e-43a0-bf5f-12a761f49a27@redhat.com>
2025-08-15 15:20 ` [RFC PATCH 6/7] mm: memory: add mTHP support for wp Vernon Yang
2025-08-16 6:40 ` David Hildenbrand
[not found] ` <b607985d-d319-4b47-9365-0595f7d87f28@redhat.com>
2025-08-15 15:30 ` Vernon Yang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox