]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/lib: Add WBINVD and WBNOINVD helpers to target multiple CPUs
authorZheyun Shen <szy0127@sjtu.edu.cn>
Thu, 22 May 2025 23:37:28 +0000 (16:37 -0700)
committerBorislav Petkov (AMD) <bp@alien8.de>
Thu, 10 Jul 2025 11:30:17 +0000 (13:30 +0200)
Extract KVM's open-coded calls to do writeback caches on multiple CPUs to
common library helpers for both WBINVD and WBNOINVD (KVM will use both).
Put the onus on the caller to check for a non-empty mask to simplify the
SMP=n implementation, e.g. so that it doesn't need to check that the one
and only CPU in the system is present in the mask.

  [sean: move to lib, add SMP=n helpers, clarify usage]

Signed-off-by: Zheyun Shen <szy0127@sjtu.edu.cn>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Acked-by: Kai Huang <kai.huang@intel.com>
Link: https://lore.kernel.org/r/20250128015345.7929-2-szy0127@sjtu.edu.cn
Link: https://lore.kernel.org/20250522233733.3176144-5-seanjc@google.com
arch/x86/include/asm/smp.h
arch/x86/kvm/x86.c
arch/x86/lib/cache-smp.c

index e08f1ae25401060b20cf3635656807d7e67e12df..22bfebe6776dab24bb301e055ee9fd1bf514d0cd 100644 (file)
@@ -113,7 +113,9 @@ void native_play_dead(void);
 void play_dead_common(void);
 void wbinvd_on_cpu(int cpu);
 void wbinvd_on_all_cpus(void);
+void wbinvd_on_cpus_mask(struct cpumask *cpus);
 void wbnoinvd_on_all_cpus(void);
+void wbnoinvd_on_cpus_mask(struct cpumask *cpus);
 
 void smp_kick_mwait_play_dead(void);
 void __noreturn mwait_play_dead(unsigned int eax_hint);
@@ -154,11 +156,21 @@ static inline void wbinvd_on_all_cpus(void)
        wbinvd();
 }
 
+static inline void wbinvd_on_cpus_mask(struct cpumask *cpus)
+{
+       wbinvd();
+}
+
 static inline void wbnoinvd_on_all_cpus(void)
 {
        wbnoinvd();
 }
 
+static inline void wbnoinvd_on_cpus_mask(struct cpumask *cpus)
+{
+       wbnoinvd();
+}
+
 static inline struct cpumask *cpu_llc_shared_mask(int cpu)
 {
        return (struct cpumask *)cpumask_of(0);
index a9d992d5652fa0fa2cba6874eb64c7cc6356c1a8..5a2160f449e0ebe200e76353097d66ced989ac83 100644 (file)
@@ -8289,8 +8289,7 @@ static int kvm_emulate_wbinvd_noskip(struct kvm_vcpu *vcpu)
                int cpu = get_cpu();
 
                cpumask_set_cpu(cpu, vcpu->arch.wbinvd_dirty_mask);
-               on_each_cpu_mask(vcpu->arch.wbinvd_dirty_mask,
-                               wbinvd_ipi, NULL, 1);
+               wbinvd_on_cpus_mask(vcpu->arch.wbinvd_dirty_mask);
                put_cpu();
                cpumask_clear(vcpu->arch.wbinvd_dirty_mask);
        } else
index 74e0d5ba867da19fc79779a383a8108238a3d904..c5c60d07308c04c256bff54190def3039b87f497 100644 (file)
@@ -20,6 +20,12 @@ void wbinvd_on_all_cpus(void)
 }
 EXPORT_SYMBOL(wbinvd_on_all_cpus);
 
+void wbinvd_on_cpus_mask(struct cpumask *cpus)
+{
+       on_each_cpu_mask(cpus, __wbinvd, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(wbinvd_on_cpus_mask);
+
 static void __wbnoinvd(void *dummy)
 {
        wbnoinvd();
@@ -30,3 +36,9 @@ void wbnoinvd_on_all_cpus(void)
        on_each_cpu(__wbnoinvd, NULL, 1);
 }
 EXPORT_SYMBOL_GPL(wbnoinvd_on_all_cpus);
+
+void wbnoinvd_on_cpus_mask(struct cpumask *cpus)
+{
+       on_each_cpu_mask(cpus, __wbnoinvd, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(wbnoinvd_on_cpus_mask);