Skip to content

Commit 8e786a8

Browse files
committed
x86/process: Move the buffer clearing before MONITOR
Move the VERW clearing before the MONITOR so that VERW doesn't disarm it and the machine never enters C1. Original idea by Kim Phillips <[email protected]>. Suggested-by: Andrew Cooper <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]>
1 parent 2329f25 commit 8e786a8

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

arch/x86/include/asm/mwait.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ static __always_inline void __monitorx(const void *eax, u32 ecx, u32 edx)
4343

4444
static __always_inline void __mwait(u32 eax, u32 ecx)
4545
{
46-
x86_idle_clear_cpu_buffers();
47-
4846
/*
4947
* Use the instruction mnemonic with implicit operands, as the LLVM
5048
* assembler fails to assemble the mnemonic with explicit operands:
@@ -98,7 +96,6 @@ static __always_inline void __mwaitx(u32 eax, u32 ebx, u32 ecx)
9896
*/
9997
static __always_inline void __sti_mwait(u32 eax, u32 ecx)
10098
{
101-
x86_idle_clear_cpu_buffers();
10299

103100
asm volatile("sti; mwait" :: "a" (eax), "c" (ecx));
104101
}
@@ -115,21 +112,29 @@ static __always_inline void __sti_mwait(u32 eax, u32 ecx)
115112
*/
116113
static __always_inline void mwait_idle_with_hints(u32 eax, u32 ecx)
117114
{
115+
if (need_resched())
116+
return;
117+
118+
x86_idle_clear_cpu_buffers();
119+
118120
if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
119121
const void *addr = &current_thread_info()->flags;
120122

121123
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
122124
__monitor(addr, 0, 0);
123125

124-
if (!need_resched()) {
125-
if (ecx & 1) {
126-
__mwait(eax, ecx);
127-
} else {
128-
__sti_mwait(eax, ecx);
129-
raw_local_irq_disable();
130-
}
126+
if (need_resched())
127+
goto out;
128+
129+
if (ecx & 1) {
130+
__mwait(eax, ecx);
131+
} else {
132+
__sti_mwait(eax, ecx);
133+
raw_local_irq_disable();
131134
}
132135
}
136+
137+
out:
133138
current_clr_polling();
134139
}
135140

arch/x86/kernel/process.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -907,16 +907,24 @@ static __init bool prefer_mwait_c1_over_halt(void)
907907
*/
908908
static __cpuidle void mwait_idle(void)
909909
{
910+
if (need_resched())
911+
return;
912+
913+
x86_idle_clear_cpu_buffers();
914+
910915
if (!current_set_polling_and_test()) {
911916
const void *addr = &current_thread_info()->flags;
912917

913918
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
914919
__monitor(addr, 0, 0);
915-
if (!need_resched()) {
916-
__sti_mwait(0, 0);
917-
raw_local_irq_disable();
918-
}
920+
if (need_resched())
921+
goto out;
922+
923+
__sti_mwait(0, 0);
924+
raw_local_irq_disable();
919925
}
926+
927+
out:
920928
__current_clr_polling();
921929
}
922930

0 commit comments

Comments
 (0)