Skip to content

Commit 8c19449

Browse files
bp3tk0vgregkh
authored andcommitted
x86/process: Move the buffer clearing before MONITOR
Commit 8e786a8 upstream. 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 <kim.phillips@amd.com>. Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 6fb766d commit 8c19449

2 files changed

Lines changed: 27 additions & 14 deletions

File tree

arch/x86/include/asm/mwait.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ static __always_inline void __monitorx(const void *eax, unsigned long ecx,
4444

4545
static __always_inline void __mwait(unsigned long eax, unsigned long ecx)
4646
{
47-
x86_idle_clear_cpu_buffers();
48-
4947
/* "mwait %eax, %ecx;" */
5048
asm volatile(".byte 0x0f, 0x01, 0xc9;"
5149
:: "a" (eax), "c" (ecx));
@@ -89,7 +87,6 @@ static __always_inline void __mwaitx(unsigned long eax, unsigned long ebx,
8987

9088
static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
9189
{
92-
x86_idle_clear_cpu_buffers();
9390

9491
/* "mwait %eax, %ecx;" */
9592
asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
@@ -108,21 +105,29 @@ static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
108105
*/
109106
static __always_inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
110107
{
108+
if (need_resched())
109+
return;
110+
111+
x86_idle_clear_cpu_buffers();
112+
111113
if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
112114
const void *addr = &current_thread_info()->flags;
113115

114116
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
115117
__monitor(addr, 0, 0);
116118

117-
if (!need_resched()) {
118-
if (ecx & 1) {
119-
__mwait(eax, ecx);
120-
} else {
121-
__sti_mwait(eax, ecx);
122-
raw_local_irq_disable();
123-
}
119+
if (need_resched())
120+
goto out;
121+
122+
if (ecx & 1) {
123+
__mwait(eax, ecx);
124+
} else {
125+
__sti_mwait(eax, ecx);
126+
raw_local_irq_disable();
124127
}
125128
}
129+
130+
out:
126131
current_clr_polling();
127132
}
128133

arch/x86/kernel/process.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -928,16 +928,24 @@ static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
928928
*/
929929
static __cpuidle void mwait_idle(void)
930930
{
931+
if (need_resched())
932+
return;
933+
934+
x86_idle_clear_cpu_buffers();
935+
931936
if (!current_set_polling_and_test()) {
932937
const void *addr = &current_thread_info()->flags;
933938

934939
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
935940
__monitor(addr, 0, 0);
936-
if (!need_resched()) {
937-
__sti_mwait(0, 0);
938-
raw_local_irq_disable();
939-
}
941+
if (need_resched())
942+
goto out;
943+
944+
__sti_mwait(0, 0);
945+
raw_local_irq_disable();
940946
}
947+
948+
out:
941949
__current_clr_polling();
942950
}
943951

0 commit comments

Comments
 (0)