Skip to content

Commit bb78c14

Browse files
committed
Merge tag 'x86_core_for_v6.17_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 cpu updates from Borislav Petkov: - Add helpers for WB{NO,}INVD with the purpose of using them in KVM and thus diminish the number of invalidations needed. With preceding cleanups, as always * tag 'x86_core_for_v6.17_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/lib: Add WBINVD and WBNOINVD helpers to target multiple CPUs x86/lib: Add WBNOINVD helper functions x86/lib: Drop the unused return value from wbinvd_on_all_cpus() drm/gpu: Remove dead checks on wbinvd_on_all_cpus()'s return value
2 parents 04d29e3 + 4fdc343 commit bb78c14

File tree

5 files changed

+76
-14
lines changed

5 files changed

+76
-14
lines changed

arch/x86/include/asm/smp.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ void __noreturn hlt_play_dead(void);
112112
void native_play_dead(void);
113113
void play_dead_common(void);
114114
void wbinvd_on_cpu(int cpu);
115-
int wbinvd_on_all_cpus(void);
115+
void wbinvd_on_all_cpus(void);
116+
void wbinvd_on_cpus_mask(struct cpumask *cpus);
117+
void wbnoinvd_on_all_cpus(void);
118+
void wbnoinvd_on_cpus_mask(struct cpumask *cpus);
116119

117120
void smp_kick_mwait_play_dead(void);
118121
void __noreturn mwait_play_dead(unsigned int eax_hint);
@@ -148,10 +151,24 @@ static inline struct cpumask *cpu_l2c_shared_mask(int cpu)
148151

149152
#else /* !CONFIG_SMP */
150153
#define wbinvd_on_cpu(cpu) wbinvd()
151-
static inline int wbinvd_on_all_cpus(void)
154+
static inline void wbinvd_on_all_cpus(void)
152155
{
153156
wbinvd();
154-
return 0;
157+
}
158+
159+
static inline void wbinvd_on_cpus_mask(struct cpumask *cpus)
160+
{
161+
wbinvd();
162+
}
163+
164+
static inline void wbnoinvd_on_all_cpus(void)
165+
{
166+
wbnoinvd();
167+
}
168+
169+
static inline void wbnoinvd_on_cpus_mask(struct cpumask *cpus)
170+
{
171+
wbnoinvd();
155172
}
156173

157174
static inline struct cpumask *cpu_llc_shared_mask(int cpu)

arch/x86/include/asm/special_insns.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,36 @@ static inline void wrpkru(u32 pkru)
104104
}
105105
#endif
106106

107+
/*
108+
* Write back all modified lines in all levels of cache associated with this
109+
* logical processor to main memory, and then invalidate all caches. Depending
110+
* on the micro-architecture, WBINVD (and WBNOINVD below) may or may not affect
111+
* lower level caches associated with another logical processor that shares any
112+
* level of this processor's cache hierarchy.
113+
*/
107114
static __always_inline void wbinvd(void)
108115
{
109-
asm volatile("wbinvd": : :"memory");
116+
asm volatile("wbinvd" : : : "memory");
117+
}
118+
119+
/* Instruction encoding provided for binutils backwards compatibility. */
120+
#define ASM_WBNOINVD _ASM_BYTES(0xf3,0x0f,0x09)
121+
122+
/*
123+
* Write back all modified lines in all levels of cache associated with this
124+
* logical processor to main memory, but do NOT explicitly invalidate caches,
125+
* i.e. leave all/most cache lines in the hierarchy in non-modified state.
126+
*/
127+
static __always_inline void wbnoinvd(void)
128+
{
129+
/*
130+
* Explicitly encode WBINVD if X86_FEATURE_WBNOINVD is unavailable even
131+
* though WBNOINVD is backwards compatible (it's simply WBINVD with an
132+
* ignored REP prefix), to guarantee that WBNOINVD isn't used if it
133+
* needs to be avoided for any reason. For all supported usage in the
134+
* kernel, WBINVD is functionally a superset of WBNOINVD.
135+
*/
136+
alternative("wbinvd", ASM_WBNOINVD, X86_FEATURE_WBNOINVD);
110137
}
111138

112139
static inline unsigned long __read_cr4(void)

arch/x86/kvm/x86.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8295,8 +8295,7 @@ static int kvm_emulate_wbinvd_noskip(struct kvm_vcpu *vcpu)
82958295
int cpu = get_cpu();
82968296

82978297
cpumask_set_cpu(cpu, vcpu->arch.wbinvd_dirty_mask);
8298-
on_each_cpu_mask(vcpu->arch.wbinvd_dirty_mask,
8299-
wbinvd_ipi, NULL, 1);
8298+
wbinvd_on_cpus_mask(vcpu->arch.wbinvd_dirty_mask);
83008299
put_cpu();
83018300
cpumask_clear(vcpu->arch.wbinvd_dirty_mask);
83028301
} else

arch/x86/lib/cache-smp.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,31 @@ void wbinvd_on_cpu(int cpu)
1414
}
1515
EXPORT_SYMBOL(wbinvd_on_cpu);
1616

17-
int wbinvd_on_all_cpus(void)
17+
void wbinvd_on_all_cpus(void)
1818
{
1919
on_each_cpu(__wbinvd, NULL, 1);
20-
return 0;
2120
}
2221
EXPORT_SYMBOL(wbinvd_on_all_cpus);
22+
23+
void wbinvd_on_cpus_mask(struct cpumask *cpus)
24+
{
25+
on_each_cpu_mask(cpus, __wbinvd, NULL, 1);
26+
}
27+
EXPORT_SYMBOL_GPL(wbinvd_on_cpus_mask);
28+
29+
static void __wbnoinvd(void *dummy)
30+
{
31+
wbnoinvd();
32+
}
33+
34+
void wbnoinvd_on_all_cpus(void)
35+
{
36+
on_each_cpu(__wbnoinvd, NULL, 1);
37+
}
38+
EXPORT_SYMBOL_GPL(wbnoinvd_on_all_cpus);
39+
40+
void wbnoinvd_on_cpus_mask(struct cpumask *cpus)
41+
{
42+
on_each_cpu_mask(cpus, __wbnoinvd, NULL, 1);
43+
}
44+
EXPORT_SYMBOL_GPL(wbnoinvd_on_cpus_mask);

drivers/gpu/drm/drm_cache.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)
9393
return;
9494
}
9595

96-
if (wbinvd_on_all_cpus())
97-
pr_err("Timed out waiting for cache flush\n");
96+
wbinvd_on_all_cpus();
9897

9998
#elif defined(__powerpc__)
10099
unsigned long i;
@@ -139,8 +138,7 @@ drm_clflush_sg(struct sg_table *st)
139138
return;
140139
}
141140

142-
if (wbinvd_on_all_cpus())
143-
pr_err("Timed out waiting for cache flush\n");
141+
wbinvd_on_all_cpus();
144142
#else
145143
WARN_ONCE(1, "Architecture has no drm_cache.c support\n");
146144
#endif
@@ -172,8 +170,7 @@ drm_clflush_virt_range(void *addr, unsigned long length)
172170
return;
173171
}
174172

175-
if (wbinvd_on_all_cpus())
176-
pr_err("Timed out waiting for cache flush\n");
173+
wbinvd_on_all_cpus();
177174
#else
178175
WARN_ONCE(1, "Architecture has no drm_cache.c support\n");
179176
#endif

0 commit comments

Comments
 (0)