[PATCH RFC 12/18] x86/pat/mm, mm/set_memory: abstract the CPA page table lock

"Mike Rapoport (Microsoft)" <[email protected]> Tue, 21 Jul 2026 19:23:35 +0300
Newsgroups dev.linux.lists.loongarch,org.infradead.lists.linux-arm-kernel,org.infradead.lists.linux-riscv,org.kernel.vger.linux-kernel,org.kvack.linux-mm
Message-ID <[email protected]>
x86 requires taking pgd_lock to serialize large page splits against
parallel page table operations, for instance such as
arch_sync_kernel_mappings() and pgd allocation and freeing.

Add arch_lock() and arch_unlock() static inlines that replace direct
locking/unlocking of the pgd_lock in CPA core.

Since only x86 needs such lock, keep things simple and use #ifdef
CONFIG_X86 rather than creating an overridable infrastructure.

No functional change intended.

Assisted-by: Copilot:claude-opus-4.8
Signed-off-by: Mike Rapoport (Microsoft) <[email protected]>
---
 mm/set_memory.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/mm/set_memory.c b/mm/set_memory.c
index 712264de8e9b..d2846804e4e6 100644
--- a/mm/set_memory.c
+++ b/mm/set_memory.c
@@ -14,6 +14,20 @@
  */
 static DEFINE_SPINLOCK(cpa_lock);
 
+static inline void arch_lock(void)
+{
+#ifdef CONFIG_X86
+	spin_lock(&pgd_lock);
+#endif
+}
+
+static inline void arch_unlock(void)
+{
+#ifdef CONFIG_X86
+	spin_unlock(&pgd_lock);
+#endif
+}
+
 unsigned long cpa_addr(struct cpa_data *cpa, unsigned long idx)
 {
 	if (cpa->flags & CPA_PAGES_ARRAY) {
@@ -170,7 +184,7 @@ static int cpa_handle_large_page(struct cpa_data *cpa, pte_t *kpte,
 	if (!sd.ptdesc)
 		return -ENOMEM;
 
-	spin_lock(&pgd_lock);
+	arch_lock();
 
 	/*
 	 * Check for races, another CPU might have split this page
@@ -202,11 +216,11 @@ static int cpa_handle_large_page(struct cpa_data *cpa, pte_t *kpte,
 	if (ret)
 		goto out_free_ptdesc;
 
-	spin_unlock(&pgd_lock);
+	arch_unlock();
 	return do_split;
 
 out_free_ptdesc:
-	spin_unlock(&pgd_lock);
+	arch_unlock();
 	pagetable_free(sd.ptdesc);
 	return ret;
 }

-- 
2.53.0