* [RFC] mm: Is flush_cache_page() in wp_page_reuse() really necessary? [not found] <7a217590-1e37-4d80-9c5c-1f7d2c2b556c@huawei.com> @ 2025-09-29 7:54 ` wuyifeng (C) [not found] ` <f775b4a3-77c4-46a8-92e2-17308097df3e@redhat.com> 1 sibling, 0 replies; 2+ messages in thread From: wuyifeng (C) @ 2025-09-29 7:54 UTC (permalink / raw) To: linux-mm, akpm [Forwarded] This is the email I previously sent to the maintainer. I forgot to copy the mailing list, so I am resending it here. -------- 转发的消息 -------- 主题: [RFC] mm: Is flush_cache_page() in wp_page_reuse() really necessary? 日期: Mon, 29 Sep 2025 15:29:37 +0800 From: wuyifeng (C) <wuyifeng10@huawei.com> 收件人: David Hildenbrand <david@redhat.com>, akpm@linux-foundation.org, lorenzo.stoakes@oracle.com 抄送: baohua@kernel.org Hi Linux MM developers, I am reviewing the page fault handling code in the memory management subsystem and came across a point that puzzled me regarding the use of flush_cache_page(). When I referred to Documentation/core-api/cachetlb.rst, it describes a typical sequence in a page fault scenario: flush_cache_page(vma, addr, pfn); set_pte(pte_pointer, new_pte_val); flush_tlb_page(vma, addr); That is, first the CPU cache is flushed, then the PTE is updated, and finally the TLB is flushed for the corresponding virtual address. This makes sense: when the virtual-to-physical mapping changes, flushing the CPU cache is necessary to prevent stale or corrupted cache from affecting the new mapping. However, in wp_page_reuse(), the virtual-to-physical mapping does not change. The function looks like this: static inline void wp_page_reuse(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; struct page *page = vmf->page; pte_t entry; if (page) page_cpupid_xchg_last(page, (1 << LAST_CPUPID_SHIFT) - 1); flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte)); entry = pte_mkyoung(vmf->orig_pte); entry = maybe_mkwrite(pte_mkdirty(entry), vma); if (ptep_set_access_flags(vma, vmf->address, vmf->pte, entry, 1)) update_mmu_cache(vma, vmf->address, vmf->pte); } Since the mapping itself does not change, I am puzzled whether this flush_cache_page() call is actually necessary. A similar situation appears in do_huge_pmd_wp_page(), which handles huge pages. When the system reaches the reuse branch after the relevant checks, the code looks like this: reuse: entry = pmd_mkyoung(orig_pmd); entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); if (pmdp_set_access_flags(vma, haddr, vmf->pmd, entry, 1)) update_mmu_cache_pmd(vma, vmf->address, vmf->pmd); Here, flush_cache_page() is not called. Instead, the code relies on updating PMD access flags and calling update_mmu_cache_pmd() to refresh the TLB. I have traced this back to the 2.6 kernel, and observed that the `flush_cache_page` interface has already been present in the reuse-related logic since then. It appears that this part has not received much attention over time, and the invocation of `flush_cache_page` here may indeed be redundant? code in do_wp_page (linux 2.6): /* reuse the old page */ if (PageAnon(old_page) && !TestSetPageLocked(old_page)) { int reuse = can_share_swap_page(old_page); unlock_page(old_page); if (reuse) { flush_cache_page(vma, address, pfn); entry = maybe_mkwrite(pte_mkyoung(pte_mkdirty(pte)), vma); ptep_set_access_flags(vma, address, page_table, entry, 1); update_mmu_cache(vma, address, entry); lazy_mmu_prot_update(entry); pte_unmap(page_table); spin_unlock(&mm->page_table_lock); return VM_FAULT_MINOR|VM_FAULT_WRITE; } } So my questions are: Is the flush_cache_page() call in wp_page_reuse() actually necessary? If it is necessary, why is flush_cache_page() not required in the reuse branch of do_huge_pmd_wp_page() for huge pages? I would greatly appreciate your reply. Thank you very much! Best regards, [wuyifeng] ^ permalink raw reply [flat|nested] 2+ messages in thread
[parent not found: <f775b4a3-77c4-46a8-92e2-17308097df3e@redhat.com>]
* Re: [RFC] mm: Is flush_cache_page() in wp_page_reuse() really necessary? [not found] ` <f775b4a3-77c4-46a8-92e2-17308097df3e@redhat.com> @ 2025-09-29 8:52 ` wuyifeng (C) 0 siblings, 0 replies; 2+ messages in thread From: wuyifeng (C) @ 2025-09-29 8:52 UTC (permalink / raw) To: David Hildenbrand, akpm, lorenzo.stoakes; +Cc: baohua, linux-mm Thanks for your reply and the pointers. I went through the kernel arch/ code and looked into architectures that support PMD-level THP, such as arm64 and x86_64 etc. I found that their flush_cache_page() implementations are all nop. More precisely, for modern cache architectures (VIPT no-alias, PIPT), flush_cache_page() is nop. So the call in wp_page_reuse() looks more like a historical artifact, and it’s hard to judge whether it was strictly necessary. I really appreciate your clarifications! Best regards, Wuyifeng 在 2025/9/29 16:09, David Hildenbrand 写道: > On 29.09.25 09:29, wuyifeng (C) wrote: >> Hi Linux MM developers, > > Hi, > >> >> I am reviewing the page fault handling code in the memory management >> subsystem and came across a point that puzzled me regarding the use of >> flush_cache_page(). >> >> When I referred to Documentation/core-api/cachetlb.rst, it describes a >> typical sequence in a page fault scenario: >> >> flush_cache_page(vma, addr, pfn); >> set_pte(pte_pointer, new_pte_val); >> flush_tlb_page(vma, addr); >> > > The number of archs that actually implement flush_cache_page() is limited, so likely there is not a lot of interest around optimizing some out. > >> >> That is, first the CPU cache is flushed, then the PTE is updated, and >> finally the TLB is flushed for the corresponding virtual address. This >> makes sense: when the virtual-to-physical mapping changes, flushing the >> CPU cache is necessary to prevent stale or corrupted cache from affecting >> the new mapping. >> >> However, in wp_page_reuse(), the virtual-to-physical mapping does >> not change. The function looks like this: >> >> static inline void wp_page_reuse(struct vm_fault *vmf) >> { >> struct vm_area_struct *vma = vmf->vma; >> struct page *page = vmf->page; >> pte_t entry; >> >> if (page) >> page_cpupid_xchg_last(page, (1 << LAST_CPUPID_SHIFT) - 1); >> >> flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte)); >> entry = pte_mkyoung(vmf->orig_pte); >> entry = maybe_mkwrite(pte_mkdirty(entry), vma); >> if (ptep_set_access_flags(vma, vmf->address, vmf->pte, entry, 1)) >> update_mmu_cache(vma, vmf->address, vmf->pte); >> } > > Note that an "old" PTE might, depending on the arch, not actually have the hw-present bit set, so next access would trigger a page fault to maintain the clean/old PTE bit in software. > > So it could easily be that we are transitioning from non-hw-present to hw-present here. > > If that requires a flush_cache_page(), I really don't know :) > >> >> >> Since the mapping itself does not change, I am puzzled whether this >> flush_cache_page() call is actually necessary. > > Same here. I have no idea if the scenario described above would require it, or only when we are changing something present to something non-present or differently-present. > >> >> A similar situation appears in do_huge_pmd_wp_page(), which handles >> huge pages. When the system reaches the reuse branch after the relevant >> checks, the code looks like this: >> >> reuse: >> entry = pmd_mkyoung(orig_pmd); >> entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); >> if (pmdp_set_access_flags(vma, haddr, vmf->pmd, entry, 1)) >> update_mmu_cache_pmd(vma, vmf->address, vmf->pmd); >> >> >> Here, flush_cache_page() is not called. Instead, the code relies on >> updating PMD access flags and calling update_mmu_cache_pmd() to refresh >> the TLB. > > Does any architecture that cares about flush_cache_page() actually support PMD THPs? > > I mean, looking at mm/khugepaged.c, I cannot spot any flush_cache_*(). Maybe it's implicit, but my best guess is that no architecture that supports THPs really requires it? > ^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-09-29 8:52 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <7a217590-1e37-4d80-9c5c-1f7d2c2b556c@huawei.com>
2025-09-29 7:54 ` [RFC] mm: Is flush_cache_page() in wp_page_reuse() really necessary? wuyifeng (C)
[not found] ` <f775b4a3-77c4-46a8-92e2-17308097df3e@redhat.com>
2025-09-29 8:52 ` wuyifeng (C)
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox