Skip to content

Commit 6290103

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 <[email protected]>. Suggested-by: Andrew Cooper <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 9456069 commit 6290103

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
@@ -43,8 +43,6 @@ static __always_inline void __monitorx(const void *eax, unsigned long ecx,
4343

4444
static __always_inline void __mwait(unsigned long eax, unsigned long ecx)
4545
{
46-
x86_idle_clear_cpu_buffers();
47-
4846
/* "mwait %eax, %ecx;" */
4947
asm volatile(".byte 0x0f, 0x01, 0xc9;"
5048
:: "a" (eax), "c" (ecx));
@@ -97,7 +95,6 @@ static __always_inline void __mwaitx(unsigned long eax, unsigned long ebx,
9795
*/
9896
static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
9997
{
100-
x86_idle_clear_cpu_buffers();
10198

10299
/* "mwait %eax, %ecx;" */
103100
asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
@@ -116,21 +113,29 @@ static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
116113
*/
117114
static __always_inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
118115
{
116+
if (need_resched())
117+
return;
118+
119+
x86_idle_clear_cpu_buffers();
120+
119121
if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
120122
const void *addr = &current_thread_info()->flags;
121123

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

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

arch/x86/kernel/process.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -912,16 +912,24 @@ static __init bool prefer_mwait_c1_over_halt(void)
912912
*/
913913
static __cpuidle void mwait_idle(void)
914914
{
915+
if (need_resched())
916+
return;
917+
918+
x86_idle_clear_cpu_buffers();
919+
915920
if (!current_set_polling_and_test()) {
916921
const void *addr = &current_thread_info()->flags;
917922

918923
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
919924
__monitor(addr, 0, 0);
920-
if (!need_resched()) {
921-
__sti_mwait(0, 0);
922-
raw_local_irq_disable();
923-
}
925+
if (need_resched())
926+
goto out;
927+
928+
__sti_mwait(0, 0);
929+
raw_local_irq_disable();
924930
}
931+
932+
out:
925933
__current_clr_polling();
926934
}
927935

0 commit comments

Comments
 (0)