From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
To: Imre Kaloz <kaloz@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>,
Andreas Larsson <andreas@gaisler.com>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, Jann Horn <jannh@google.com>,
Pedro Falcato <pfalcato@suse.de>,
sparclinux@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org
Subject: Re: [PATCH] sparc64: replace move_pte() with a D-cache flush in flush_cache_range()
Date: Wed, 4 Nov 2026 13:48:50 +0000 [thread overview]
Message-ID: <aus2bLyqhZCNP7rN@gremlin> (raw)
In-Reply-To: <20261104105300.16260-1-kaloz@kernel.org>
On Wed, Nov 04, 2026 at 11:52:58AM +0100, Imre Kaloz wrote:
> mremap() can move a page to an address of the other D-cache color,
> leaving lines of the old color in the virtually indexed D-cache of
> Spitfire and Cheetah CPUs. move_pte() flushed the page for each PTE
> moved, which is only correct while move_ptes() handles one PTE at a
> time.
>
> Drop move_pte(), which no other architecture defines, and flush the
> whole D-cache in flush_cache_range(), which mremap() calls on the old
> range before moving the PTEs. This keeps the fix in sparc64 without
> a page table walk.
>
> Suggested-by: David Hildenbrand (Arm) <david@kernel.org>
> Link: https://lore.kernel.org/all/409079fe-ab52-4389-9fe0-d7246eb27bad@kernel.org/
> Signed-off-by: Imre Kaloz <kaloz@kernel.org>
Oh lovely thanks :) LGTM!
Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> ---
> Andreas asked for this as a separate patch once the merge window was
> over [1]. It applies on top of sparc for-next.
>
> [1] https://lore.kernel.org/all/4fba060e-c4f4-4d73-8efe-dbed0b5a7bc3@gaisler.com/
>
> arch/sparc/include/asm/cacheflush_64.h | 4 ++--
> arch/sparc/include/asm/pgtable_64.h | 21 ---------------------
> arch/sparc/mm/init_64.c | 18 ++++++++++++++++++
> include/linux/pgtable.h | 4 ----
> mm/mremap.c | 1 -
> 5 files changed, 20 insertions(+), 28 deletions(-)
>
> diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
> index 54a2d37008e6..1a116b288816 100644
> --- a/arch/sparc/include/asm/cacheflush_64.h
> +++ b/arch/sparc/include/asm/cacheflush_64.h
> @@ -21,8 +21,8 @@ void __flushw_user(void);
> #define flush_cache_mm(__mm) \
> do { if ((__mm) == current->mm) flushw_user(); } while(0)
> #define flush_cache_dup_mm(mm) flush_cache_mm(mm)
> -#define flush_cache_range(vma, start, end) \
> - flush_cache_mm((vma)->vm_mm)
> +void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
> + unsigned long end);
> #define flush_cache_page(vma, page, pfn) \
> flush_cache_mm((vma)->vm_mm)
>
> diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
> index c26f2888aa18..310b66459521 100644
> --- a/arch/sparc/include/asm/pgtable_64.h
> +++ b/arch/sparc/include/asm/pgtable_64.h
> @@ -935,27 +935,6 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> #define pte_clear(mm,addr,ptep) \
> set_pte_at((mm), (addr), (ptep), __pte(0UL))
>
> -#ifdef DCACHE_ALIASING_POSSIBLE
> -/* This flushes only the page the PTE maps, so it relies on move_ptes()
> - * calling it for one PTE at a time, which the default pte_batch_hint()
> - * guarantees.
> - */
> -#define __HAVE_ARCH_MOVE_PTE
> -#define move_pte(pte, old_addr, new_addr) \
> -({ \
> - pte_t newpte = (pte); \
> - if (tlb_type != hypervisor && pte_present(pte)) { \
> - unsigned long this_pfn = pte_pfn(pte); \
> - \
> - if (pfn_valid(this_pfn) && \
> - (((old_addr) ^ (new_addr)) & (1 << 13))) \
> - flush_dcache_page_all(current->mm, \
> - pfn_to_page(this_pfn)); \
> - } \
> - newpte; \
> -})
> -#endif
> -
> extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
>
> void paging_init(void);
> diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
> index 6a0ba9a01a21..a1ab1eacbf33 100644
> --- a/arch/sparc/mm/init_64.c
> +++ b/arch/sparc/mm/init_64.c
> @@ -3115,6 +3115,24 @@ void flush_cache_vmap(unsigned long start, unsigned long end)
> #endif
> }
>
> +/*
> + * mremap() moves the PTEs of [start, end) to addresses that may have the
> + * other color, and calls this on the old range first. Flush the whole
> + * D-cache so no line of the old color outlives the move.
> + */
> +void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
> + unsigned long end)
> +{
> + /* flush_cache_mm() spills the user register windows. */
> + flush_cache_mm(vma->vm_mm);
> +#ifdef DCACHE_ALIASING_POSSIBLE
> + /* The D-cache is virtually indexed on Spitfire and Cheetah. */
> + if (tlb_type == spitfire || tlb_type == cheetah ||
> + tlb_type == cheetah_plus)
> + flush_dcache_all();
> +#endif
> +}
> +
> void flush_tlb_kernel_range(unsigned long start, unsigned long end)
> {
> if (start < HI_OBP_ADDRESS && end > LOW_OBP_ADDRESS) {
> diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
> index 780fe849ff8b..c729c3cc8bda 100644
> --- a/include/linux/pgtable.h
> +++ b/include/linux/pgtable.h
> @@ -1470,10 +1470,6 @@ static inline void arch_swap_restore(swp_entry_t entry, struct folio *folio)
> }
> #endif
>
> -#ifndef __HAVE_ARCH_MOVE_PTE
> -#define move_pte(pte, old_addr, new_addr) (pte)
> -#endif
> -
> #ifndef pte_accessible
> # define pte_accessible(mm, pte) ((void)(pte), 1)
> #endif
> diff --git a/mm/mremap.c b/mm/mremap.c
> index 0d06d7f37f19..87cb15027bfd 100644
> --- a/mm/mremap.c
> +++ b/mm/mremap.c
> @@ -289,7 +289,6 @@ static int move_ptes(struct pagetable_move_control *pmc,
> force_flush = true;
> }
> pte = get_and_clear_ptes(mm, old_addr, old_ptep, nr_ptes);
> - pte = move_pte(pte, old_addr, new_addr);
:))
> pte = move_soft_dirty_pte(pte);
>
> if (need_clear_uffd_wp && pte_is_uffd_wp_marker(pte))
>
> base-commit: c95443b98771a74c6689f5e7bbc56794fe95f550
> --
> 2.47.3
>
--
Cheers, Lorenzo
prev parent reply other threads:[~2026-11-04 13:48 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 10:52 [PATCH] sparc64: replace move_pte() with a D-cache flush in flush_cache_range() Imre Kaloz
2026-11-04 13:35 ` David Hildenbrand (Arm)
2026-11-04 13:41 ` Pedro Falcato
2026-11-04 13:47 ` Mike Rapoport
2026-11-04 13:48 ` Lorenzo Stoakes (ARM) [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aus2bLyqhZCNP7rN@gremlin \
--to=ljs@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=andreas@gaisler.com \
--cc=davem@davemloft.net \
--cc=david@kernel.org \
--cc=jannh@google.com \
--cc=kaloz@kernel.org \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@suse.com \
--cc=pfalcato@suse.de \
--cc=rppt@kernel.org \
--cc=sparclinux@vger.kernel.org \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.