In line with WBINVD usage, add WBONINVD helper functions. For the
wbnoinvd() helper, fall back to WBINVD if X86_FEATURE_WBNOINVD is not
present.
Signed-off-by: Kevin Loughlin <kevinloughlin@google.com>
---
arch/x86/include/asm/smp.h | 7 +++++++
arch/x86/include/asm/special_insns.h | 7 ++++++-
arch/x86/lib/cache-smp.c | 12 ++++++++++++
3 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index ca073f40698f..ecf93a243b83 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -112,6 +112,7 @@ void native_play_dead(void);
void play_dead_common(void);
void wbinvd_on_cpu(int cpu);
int wbinvd_on_all_cpus(void);
+int wbnoinvd_on_all_cpus(void);
void smp_kick_mwait_play_dead(void);
@@ -160,6 +161,12 @@ static inline int wbinvd_on_all_cpus(void)
return 0;
}
+static inline int wbnoinvd_on_all_cpus(void)
+{
+ wbnoinvd();
+ return 0;
+}
+
static inline struct cpumask *cpu_llc_shared_mask(int cpu)
{
return (struct cpumask *)cpumask_of(0);
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
index 03e7c2d49559..bd2eb7430cd6 100644
--- a/arch/x86/include/asm/special_insns.h
+++ b/arch/x86/include/asm/special_insns.h
@@ -117,7 +117,12 @@ static inline void wrpkru(u32 pkru)
static __always_inline void wbinvd(void)
{
- asm volatile("wbinvd": : :"memory");
+ asm volatile("wbinvd" : : : "memory");
+}
+
+static __always_inline void wbnoinvd(void)
+{
+ alternative("wbinvd", "wbnoinvd", X86_FEATURE_WBNOINVD);
}
static inline unsigned long __read_cr4(void)
diff --git a/arch/x86/lib/cache-smp.c b/arch/x86/lib/cache-smp.c
index 7af743bd3b13..7ac5cca53031 100644
--- a/arch/x86/lib/cache-smp.c
+++ b/arch/x86/lib/cache-smp.c
@@ -20,3 +20,15 @@ int wbinvd_on_all_cpus(void)
return 0;
}
EXPORT_SYMBOL(wbinvd_on_all_cpus);
+
+static void __wbnoinvd(void *dummy)
+{
+ wbnoinvd();
+}
+
+int wbnoinvd_on_all_cpus(void)
+{
+ on_each_cpu(__wbnoinvd, NULL, 1);
+ return 0;
+}
+EXPORT_SYMBOL(wbnoinvd_on_all_cpus);
--
2.48.1.262.g85cc9f2d1e-goog
On 1/21/25 16:13, Kevin Loughlin wrote: > +static __always_inline void wbnoinvd(void) > +{ > + alternative("wbinvd", "wbnoinvd", X86_FEATURE_WBNOINVD); > } Could we please comment this a _bit_? /* * Cheaper version of wbinvd(). Call when caches * need to be written back but not invalidated. */ static __always_inline void wbnoinvd(void) { /* * Use the compatible but more destructuve "invalidate" * variant when no-invalidate is unavailable: */ alternative("wbinvd", "wbnoinvd", X86_FEATURE_WBNOINVD); } Sure, folks can read the instruction reference, but it doesn't give you much of the story of why you should use one over the other or why it's OK to call one when you ask for the other.
On Tue, Jan 21, 2025 at 4:32 PM Dave Hansen <dave.hansen@intel.com> wrote: > > On 1/21/25 16:13, Kevin Loughlin wrote: > > +static __always_inline void wbnoinvd(void) > > +{ > > + alternative("wbinvd", "wbnoinvd", X86_FEATURE_WBNOINVD); > > } > > Could we please comment this a _bit_? > > /* > * Cheaper version of wbinvd(). Call when caches > * need to be written back but not invalidated. > */ > static __always_inline void wbnoinvd(void) > { > /* > * Use the compatible but more destructuve "invalidate" > * variant when no-invalidate is unavailable: > */ > alternative("wbinvd", "wbnoinvd", X86_FEATURE_WBNOINVD); > } > > Sure, folks can read the instruction reference, but it doesn't give you > much of the story of why you should use one over the other or why it's > OK to call one when you ask for the other. Yeah, good point. Incoming in v4; thanks!
© 2016 - 2025 Red Hat, Inc.