All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lance Yang <lance.yang@linux.dev>
To: Dave Hansen <dave.hansen@intel.com>
Cc: peterz@infradead.org, david@kernel.org,
	dave.hansen@linux.intel.com, ypodemsk@redhat.com,
	hughd@google.com, will@kernel.org, aneesh.kumar@kernel.org,
	npiggin@gmail.com, tglx@linutronix.de, mingo@redhat.com,
	bp@alien8.de, x86@kernel.org, hpa@zytor.com, arnd@arndb.de,
	lorenzo.stoakes@oracle.com, ziy@nvidia.com,
	baolin.wang@linux.alibaba.com, Liam.Howlett@oracle.com,
	npache@redhat.com, ryan.roberts@arm.com, dev.jain@arm.com,
	baohua@kernel.org, akpm@linux-foundation.org,
	shy828301@gmail.com, riel@surriel.com, jannh@google.com,
	jgross@suse.com, seanjc@google.com, pbonzini@redhat.com,
	boris.ostrovsky@oracle.com, virtualization@lists.linux.dev,
	kvm@vger.kernel.org, linux-arch@vger.kernel.org,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	ioworker0@gmail.com
Subject: Re: [PATCH v6 2/2] x86/tlb: skip redundant sync IPIs for native TLB flush
Date: Thu, 5 Mar 2026 17:16:12 +0800	[thread overview]
Message-ID: <5f0aea3d-3189-4712-a6e4-aaf70af3d830@linux.dev> (raw)
In-Reply-To: <7dc30fbf-17c0-47db-8457-24b531cd0071@intel.com>

Hi Dave,

Thanks for taking time to review!

On 2026/3/5 01:59, Dave Hansen wrote:
> On 3/3/26 18:10, Lance Yang wrote:
> ...
>> +	if (pv_ops.mmu.flush_tlb_multi == native_flush_tlb_multi &&
>> +	    !cpu_feature_enabled(X86_FEATURE_INVLPGB)) {
>> +		pv_ops.mmu.flush_tlb_multi_implies_ipi_broadcast = true;
>> +		static_branch_enable(&tlb_ipi_broadcast_key);
>> +	}
>> +}
> ...
>> +#ifndef CONFIG_PARAVIRT
>> +void __init native_pv_tlb_init(void)
>> +{
>> +	/*
>> +	 * For non-PARAVIRT builds, check if native TLB flush sends real IPIs
>> +	 * (i.e., not using INVLPGB broadcast invalidation).
>> +	 */
>> +	if (!cpu_feature_enabled(X86_FEATURE_INVLPGB))
>> +		static_branch_enable(&tlb_ipi_broadcast_key);
>> +}
>> +#endif
> 
> I really despise duplicated logic. The X86_FEATURE_INVLPGB check is
> small, but it is duplicated. You're also setting the static branch in a
> *bunch* of different places.

Sorry for the mess :(

> Can this be arranged so that the PV code just tells the core code that
> it is compatible with flush_tlb_multi_implies_ipi_broadcast?

Yeah, much much better and cleaner!

> void __init bool is_pv_ok(void)
> {
> 	/* This check is super sketchy an unexplained: */
> 	if (pv_ops.mmu.flush_tlb_multi_implies_ipi_broadcast)
> 		return true;
> 
> 	if (pv_ops.mmu.flush_tlb_multi != native_flush_tlb_multi)
> 		return false;
> 
> 	pv_ops.mmu.flush_tlb_multi_implies_ipi_broadcast = true;
> 
> 	return true;
> }
> 
> void __init tlb_init(void)
> {
> 	if (!is_pv_ok())
> 		return;
> 
> 	if (cpu_feature_enabled(X86_FEATURE_INVLPGB))
> 		return;
> 		
> 	static_branch_enable(&tlb_ipi_broadcast_key);
> }
> 
> Isn't that like a billion times more readable? It has one
> X86_FEATURE_INVLPGB check and one static_branch_enable() point and no
> #ifdeffery other than defining a stub is_pv_ok().

Yep, absolutely ;) Will rework it for v7 as you suggested.

> BTW, why is there even an early return for the case where
> flush_tlb_multi_implies_ipi_broadcast is already set? Isn't this
> decision made once on the boot CPU and then never touched again? Do any
> PV instances actually set the bit?

Good point. No PV backend sets it today, so we don't need that check or
even the property. I'll drop them. If a PV backend ever needs to
indicate it sends real IPIs, we can add the property back then.

Does the following look reasonable?

---8<---
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index 866ea78ba156..74292abe8852 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -5,11 +5,19 @@
  #define tlb_flush tlb_flush
  static inline void tlb_flush(struct mmu_gather *tlb);

+#define tlb_table_flush_implies_ipi_broadcast 
tlb_table_flush_implies_ipi_broadcast
+static inline bool tlb_table_flush_implies_ipi_broadcast(void);
+
  #include <asm-generic/tlb.h>
  #include <linux/kernel.h>
  #include <vdso/bits.h>
  #include <vdso/page.h>

+static inline bool tlb_table_flush_implies_ipi_broadcast(void)
+{
+	return static_branch_likely(&tlb_ipi_broadcast_key);
+}
+
  static inline void tlb_flush(struct mmu_gather *tlb)
  {
  	unsigned long start = 0UL, end = TLB_FLUSH_ALL;
@@ -20,7 +28,12 @@ static inline void tlb_flush(struct mmu_gather *tlb)
  		end = tlb->end;
  	}

-	flush_tlb_mm_range(tlb->mm, start, end, stride_shift, tlb->freed_tables);
+	/*
+	 * Pass both freed_tables and unshared_tables so that lazy-TLB CPUs
+	 * also receive IPIs during unsharing page tables.
+	 */
+	flush_tlb_mm_range(tlb->mm, start, end, stride_shift,
+			   tlb->freed_tables || tlb->unshared_tables);
  }

  static inline void invlpg(unsigned long addr)
diff --git a/arch/x86/include/asm/tlbflush.h 
b/arch/x86/include/asm/tlbflush.h
index 5a3cdc439e38..d086454eb760 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -5,6 +5,7 @@
  #include <linux/mm_types.h>
  #include <linux/mmu_notifier.h>
  #include <linux/sched.h>
+#include <linux/jump_label.h>

  #include <asm/barrier.h>
  #include <asm/processor.h>
@@ -15,9 +16,35 @@
  #include <asm/pti.h>
  #include <asm/processor-flags.h>
  #include <asm/pgtable.h>
+#include <asm/paravirt.h>

  DECLARE_PER_CPU(u64, tlbstate_untag_mask);

+DECLARE_STATIC_KEY_FALSE(tlb_ipi_broadcast_key);
+
+#ifdef CONFIG_PARAVIRT
+static inline bool __init pv_tlb_is_native(void)
+{
+	return pv_ops.mmu.flush_tlb_multi == native_flush_tlb_multi;
+}
+#else
+static inline bool __init pv_tlb_is_native(void)
+{
+	return true;
+}
+#endif
+
+static inline void __init native_pv_tlb_init(void)
+{
+	if (!pv_tlb_is_native())
+		return;
+
+	if (cpu_feature_enabled(X86_FEATURE_INVLPGB))
+		return;
+
+	static_branch_enable(&tlb_ipi_broadcast_key);
+}
+
  void __flush_tlb_all(void);

  #define TLB_FLUSH_ALL	-1UL
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 5cd6950ab672..3cdb04162843 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1167,6 +1167,7 @@ void __init native_smp_prepare_boot_cpu(void)
  		switch_gdt_and_percpu_base(me);

  	native_pv_lock_init();
+	native_pv_tlb_init();
  }

  void __init native_smp_cpus_done(unsigned int max_cpus)
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 621e09d049cb..43e60cca38f1 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -26,6 +26,8 @@

  #include "mm_internal.h"

+DEFINE_STATIC_KEY_FALSE(tlb_ipi_broadcast_key);
+
  #ifdef CONFIG_PARAVIRT
  # define STATIC_NOPV
  #else
---


Thanks,
Lance

  reply	other threads:[~2026-03-05  9:16 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-04  2:10 [PATCH v6 0/2] skip redundant sync IPIs when TLB flush sent them Lance Yang
2026-03-04  2:10 ` [PATCH v6 1/2] mm/mmu_gather: prepare to skip redundant sync IPIs Lance Yang
2026-03-04  2:10 ` [PATCH v6 2/2] x86/tlb: skip redundant sync IPIs for native TLB flush Lance Yang
2026-03-04 17:59   ` Dave Hansen
2026-03-05  9:16     ` Lance Yang [this message]
2026-03-06 14:35   ` kernel test robot
2026-03-06 15:41   ` kernel test robot

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=5f0aea3d-3189-4712-a6e4-aaf70af3d830@linux.dev \
    --to=lance.yang@linux.dev \
    --cc=Liam.Howlett@oracle.com \
    --cc=akpm@linux-foundation.org \
    --cc=aneesh.kumar@kernel.org \
    --cc=arnd@arndb.de \
    --cc=baohua@kernel.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=david@kernel.org \
    --cc=dev.jain@arm.com \
    --cc=hpa@zytor.com \
    --cc=hughd@google.com \
    --cc=ioworker0@gmail.com \
    --cc=jannh@google.com \
    --cc=jgross@suse.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=lorenzo.stoakes@oracle.com \
    --cc=mingo@redhat.com \
    --cc=npache@redhat.com \
    --cc=npiggin@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=riel@surriel.com \
    --cc=ryan.roberts@arm.com \
    --cc=seanjc@google.com \
    --cc=shy828301@gmail.com \
    --cc=tglx@linutronix.de \
    --cc=virtualization@lists.linux.dev \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    --cc=ypodemsk@redhat.com \
    --cc=ziy@nvidia.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 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.