The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: James Houghton <jthoughton@google.com>
To: Will Deacon <will@kernel.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	 Muchun Song <muchun.song@linux.dev>,
	Oscar Salvador <osalvador@suse.de>
Cc: Nikos Nikoleris <nikos.nikoleris@arm.com>,
	Linu Cherian <linu.cherian@arm.com>,
	 Mark Rutland <mark.rutland@arm.com>,
	David Hildenbrand <david@kernel.org>,
	 Andrew Morton <akpm@linux-foundation.org>,
	Ryan Roberts <ryan.roberts@arm.com>,
	 Nanyong Sun <sunnanyong@huawei.com>, Yu Zhao <yuzhao@google.com>,
	 Frank van der Linden <fvdl@google.com>,
	David Rientjes <rientjes@google.com>,
	 James Houghton <jthoughton@google.com>,
	linux-kernel@vger.kernel.org,
	 linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org
Subject: [PATCH 08/18] arm64: Implement try_update_vmemmap_pte using the AF trick
Date: Wed,  8 Jul 2026 03:11:18 +0000	[thread overview]
Message-ID: <20260708031129.3503195-9-jthoughton@google.com> (raw)
In-Reply-To: <20260708031129.3503195-1-jthoughton@google.com>

try_update_vmemmap_pte() must modify vmemmap PTEs without introducing a
time window where other CPUs on the system might fault.

Normally a break-before-make sequence is required to avoid conflicts
with cached translations. However, if we can guarantee that the existing
translation cannot be cached, a BBM sequence is not needed.

Translations with the AF unset may not be cached (see Arm ARM Rule
DWZCQ); the implementation of try_update_vmemmap_pte() on arm64 takes
advantage of this fact to replace a PTE without BBM and therefore
without leaving a window open where PE might fault on this translation.

Of course, if some CPUs on the system do not support HW AF management,
clearing the AF will introduce potential faults. system_supports_hvo()
will return false if any CPUs on the system do not support HW AF.

Signed-off-by: James Houghton <jthoughton@google.com>
---
 arch/arm64/include/asm/pgtable.h | 53 ++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 5f21d3a738ee..7b11aa41d0a0 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -1302,8 +1302,7 @@ static inline void __pte_clear(struct mm_struct *mm,
 	__set_pte(ptep, __pte(0));
 }
 
-static inline bool __ptep_test_and_clear_young(struct vm_area_struct *vma,
-		unsigned long address, pte_t *ptep)
+static inline pte_t __ptep_clear_young(pte_t *ptep)
 {
 	pte_t old_pte, pte;
 
@@ -1315,7 +1314,13 @@ static inline bool __ptep_test_and_clear_young(struct vm_area_struct *vma,
 					       pte_val(old_pte), pte_val(pte));
 	} while (pte_val(pte) != pte_val(old_pte));
 
-	return pte_young(pte);
+	return pte;
+}
+
+static inline bool __ptep_test_and_clear_young(struct vm_area_struct *vma,
+		unsigned long address, pte_t *ptep)
+{
+	return pte_young(__ptep_clear_young(ptep));
 }
 
 static inline bool __ptep_clear_flush_young(struct vm_area_struct *vma,
@@ -1793,6 +1798,48 @@ static inline void pte_clear(struct mm_struct *mm,
 	__pte_clear(mm, addr, ptep);
 }
 
+#define __HAVE_ARCH_TRY_UPDATE_VMEMMAP_PTE
+static inline int try_update_vmemmap_pte(unsigned long addr, pte_t *ptep,
+					 const pte_t pte)
+{
+	const int max_attempts = 16;
+	int attempts = 0;
+	pte_t old_pte;
+
+	if (!system_supports_hvo())
+		return -EOPNOTSUPP;
+
+	/* This routine is only to be used for valid-to-valid transitions. */
+	if (WARN_ON_ONCE(!pte_valid(pte)))
+		return -EINVAL;
+
+	old_pte = __ptep_get(ptep);
+
+	do {
+		if (WARN_ON_ONCE(!pte_valid(old_pte)))
+			return -EINVAL;
+
+		/* We should never get a contiguous PTE here. */
+		if (WARN_ON_ONCE(pte_valid_cont(old_pte)))
+			return -EINVAL;
+
+		if (pte_young(old_pte)) {
+			/* __ptep_clear_young() returns the overwritten PTE */
+			old_pte = pte_mkold(__ptep_clear_young(ptep));
+
+			flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+		}
+	/*
+	 * Translations without AF cannot be cached, so we can replace
+	 * them without BBM.
+	 */
+	} while (!try_cmpxchg_relaxed(&pte_val(*ptep), &pte_val(old_pte),
+				      pte_val(pte)) &&
+		 ++attempts < max_attempts);
+
+	return attempts == max_attempts ? -EAGAIN : 0;
+}
+
 #define clear_full_ptes clear_full_ptes
 static inline void clear_full_ptes(struct mm_struct *mm, unsigned long addr,
 				pte_t *ptep, unsigned int nr, int full)
-- 
2.55.0.795.g602f6c329a-goog


  parent reply	other threads:[~2026-07-08  3:11 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-08  3:11 [PATCH 00/18] Another attempt at HVO support on arm64 James Houghton
2026-07-08  3:11 ` [PATCH 01/18] hugetlb_vmemmap: Always flush TLB if needed upon PTE remapping James Houghton
2026-07-08  3:11 ` [PATCH 02/18] hugetlb_vmemmap: Move vmemmap_get_tail up James Houghton
2026-07-08  3:11 ` [PATCH 03/18] hugetlb_vmemmap: Leave pages partially HVOed upon restore failure James Houghton
2026-07-08  3:11 ` [PATCH 04/18] hugetlb_vmemmap: Use try_update_vmemmap_pte to update in-use PTEs James Houghton
2026-07-08  3:11 ` [PATCH 05/18] hugetlb_vmemmap: Allow architectures not to allow HVO at runtime James Houghton
2026-07-08  3:11 ` [PATCH 06/18] arm64: Rename cpu_has_hw_af to system_has_hw_af James Houghton
2026-07-08  3:11 ` [PATCH 07/18] arm64: Add system_supports_hvo James Houghton
2026-07-08  3:11 ` James Houghton [this message]
2026-07-08  3:11 ` [PATCH 09/18] arm64: Prevent HVO if the HVO system feature is not enabled James Houghton
2026-07-08  3:11 ` [PATCH 10/18] arm64: Support hugetlb vmemmap optimization James Houghton
2026-07-08  3:11 ` [PATCH 11/18] hugetlb_vmemmap: Use try_populate_vmemmap_pmd for replacing in-use PMDs James Houghton
2026-07-08  3:11 ` [PATCH 12/18] arm64: Implement try_populate_vmemmap_pmd using AF trick James Houghton
2026-07-08  3:11 ` [PATCH 13/18] arm64: Drop BBML2_NOABORT requirement for HVO James Houghton
2026-07-08  3:11 ` [PATCH 14/18] hugetlb_vmemmap: Rename mm/hugetlb_vmemmap.h to mm/hugetlb_vmemmap_internal.h James Houghton
2026-07-08  3:11 ` [PATCH 15/18] hugetlb_vmemmap: Add a way to permanently disable HVO when needed James Houghton
2026-07-08  3:11 ` [PATCH 16/18] arm64: Allow "optional" CPU features to be required sometimes James Houghton
2026-07-08  3:11 ` [PATCH 17/18] arm64: Permit onlining of HVO-incompatible late CPUs if HVO is not in use James Houghton
2026-07-08  3:11 ` [PATCH 18/18] arm64: Remove user-selectable HVO Kconfig James Houghton
2026-07-08  8:40 ` [PATCH 00/18] Another attempt at HVO support on arm64 Muchun Song
2026-07-08 16:49   ` James Houghton
2026-07-09  9:54     ` Muchun Song
2026-07-09 19:04       ` James Houghton
2026-07-10  3:40         ` Muchun Song
2026-07-09  9:58 ` David Hildenbrand (Arm)
2026-07-10  4:58 ` Muchun Song

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=20260708031129.3503195-9-jthoughton@google.com \
    --to=jthoughton@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=catalin.marinas@arm.com \
    --cc=david@kernel.org \
    --cc=fvdl@google.com \
    --cc=linu.cherian@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mark.rutland@arm.com \
    --cc=muchun.song@linux.dev \
    --cc=nikos.nikoleris@arm.com \
    --cc=osalvador@suse.de \
    --cc=rientjes@google.com \
    --cc=ryan.roberts@arm.com \
    --cc=sunnanyong@huawei.com \
    --cc=will@kernel.org \
    --cc=yuzhao@google.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox