Skip to content

Commit 0029b3c

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 331cfdd commit 0029b3c

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
@@ -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));
@@ -98,7 +96,6 @@ static __always_inline void __mwaitx(unsigned long eax, unsigned long ebx,
9896
*/
9997
static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
10098
{
101-
x86_idle_clear_cpu_buffers();
10299

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

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

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

arch/x86/kernel/process.c

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

917922
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
918923
__monitor(addr, 0, 0);
919-
if (!need_resched()) {
920-
__sti_mwait(0, 0);
921-
raw_local_irq_disable();
922-
}
924+
if (need_resched())
925+
goto out;
926+
927+
__sti_mwait(0, 0);
928+
raw_local_irq_disable();
923929
}
930+
931+
out:
924932
__current_clr_polling();
925933
}
926934

0 commit comments

Comments
 (0)