@@ -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+ */
107114static __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
112139static inline unsigned long __read_cr4 (void )
0 commit comments