Skip to content

Commit bf9c912

Browse files
ricardonsuryasaimadhu
authored andcommitted
x86/cpu: Use SERIALIZE in sync_core() when available
The SERIALIZE instruction gives software a way to force the processor to complete all modifications to flags, registers and memory from previous instructions and drain all buffered writes to memory before the next instruction is fetched and executed. Thus, it serves the purpose of sync_core(). Use it when available. Suggested-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Tony Luck <tony.luck@intel.com> Link: https://lkml.kernel.org/r/20200807032833.17484-1-ricardo.neri-calderon@linux.intel.com
1 parent 9123e3a commit bf9c912

2 files changed

Lines changed: 24 additions & 8 deletions

File tree

arch/x86/include/asm/special_insns.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ static inline void clwb(volatile void *__p)
234234

235235
#define nop() asm volatile ("nop")
236236

237+
static inline void serialize(void)
238+
{
239+
/* Instruction opcode for SERIALIZE; supported in binutils >= 2.35. */
240+
asm volatile(".byte 0xf, 0x1, 0xe8" ::: "memory");
241+
}
242+
237243
#endif /* __KERNEL__ */
238244

239245
#endif /* _ASM_X86_SPECIAL_INSNS_H */

arch/x86/include/asm/sync_core.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/preempt.h>
66
#include <asm/processor.h>
77
#include <asm/cpufeature.h>
8+
#include <asm/special_insns.h>
89

910
#ifdef CONFIG_X86_32
1011
static inline void iret_to_self(void)
@@ -54,14 +55,23 @@ static inline void iret_to_self(void)
5455
static inline void sync_core(void)
5556
{
5657
/*
57-
* There are quite a few ways to do this. IRET-to-self is nice
58-
* because it works on every CPU, at any CPL (so it's compatible
59-
* with paravirtualization), and it never exits to a hypervisor.
60-
* The only down sides are that it's a bit slow (it seems to be
61-
* a bit more than 2x slower than the fastest options) and that
62-
* it unmasks NMIs. The "push %cs" is needed because, in
63-
* paravirtual environments, __KERNEL_CS may not be a valid CS
64-
* value when we do IRET directly.
58+
* The SERIALIZE instruction is the most straightforward way to
59+
* do this but it not universally available.
60+
*/
61+
if (static_cpu_has(X86_FEATURE_SERIALIZE)) {
62+
serialize();
63+
return;
64+
}
65+
66+
/*
67+
* For all other processors, there are quite a few ways to do this.
68+
* IRET-to-self is nice because it works on every CPU, at any CPL
69+
* (so it's compatible with paravirtualization), and it never exits
70+
* to a hypervisor. The only down sides are that it's a bit slow
71+
* (it seems to be a bit more than 2x slower than the fastest
72+
* options) and that it unmasks NMIs. The "push %cs" is needed
73+
* because, in paravirtual environments, __KERNEL_CS may not be a
74+
* valid CS value when we do IRET directly.
6575
*
6676
* In case NMI unmasking or performance ever becomes a problem,
6777
* the next best option appears to be MOV-to-CR2 and an

0 commit comments

Comments
 (0)