x86/process: Move the buffer clearing before MONITOR
Commit 8e786a85c0a3c0fffae6244733fb576eeabd9dec 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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
6fb766d53f
commit
8c19449058
@@ -44,8 +44,6 @@ static __always_inline void __monitorx(const void *eax, unsigned long ecx,
|
|||||||
|
|
||||||
static __always_inline void __mwait(unsigned long eax, unsigned long ecx)
|
static __always_inline void __mwait(unsigned long eax, unsigned long ecx)
|
||||||
{
|
{
|
||||||
x86_idle_clear_cpu_buffers();
|
|
||||||
|
|
||||||
/* "mwait %eax, %ecx;" */
|
/* "mwait %eax, %ecx;" */
|
||||||
asm volatile(".byte 0x0f, 0x01, 0xc9;"
|
asm volatile(".byte 0x0f, 0x01, 0xc9;"
|
||||||
:: "a" (eax), "c" (ecx));
|
:: "a" (eax), "c" (ecx));
|
||||||
@@ -89,7 +87,6 @@ static __always_inline void __mwaitx(unsigned long eax, unsigned long ebx,
|
|||||||
|
|
||||||
static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
|
static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
|
||||||
{
|
{
|
||||||
x86_idle_clear_cpu_buffers();
|
|
||||||
|
|
||||||
/* "mwait %eax, %ecx;" */
|
/* "mwait %eax, %ecx;" */
|
||||||
asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
|
asm volatile("sti; .byte 0x0f, 0x01, 0xc9;"
|
||||||
@@ -108,21 +105,29 @@ static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx)
|
|||||||
*/
|
*/
|
||||||
static __always_inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
|
static __always_inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
|
||||||
{
|
{
|
||||||
|
if (need_resched())
|
||||||
|
return;
|
||||||
|
|
||||||
|
x86_idle_clear_cpu_buffers();
|
||||||
|
|
||||||
if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
|
if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) {
|
||||||
const void *addr = ¤t_thread_info()->flags;
|
const void *addr = ¤t_thread_info()->flags;
|
||||||
|
|
||||||
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
|
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
|
||||||
__monitor(addr, 0, 0);
|
__monitor(addr, 0, 0);
|
||||||
|
|
||||||
if (!need_resched()) {
|
if (need_resched())
|
||||||
if (ecx & 1) {
|
goto out;
|
||||||
__mwait(eax, ecx);
|
|
||||||
} else {
|
if (ecx & 1) {
|
||||||
__sti_mwait(eax, ecx);
|
__mwait(eax, ecx);
|
||||||
raw_local_irq_disable();
|
} else {
|
||||||
}
|
__sti_mwait(eax, ecx);
|
||||||
|
raw_local_irq_disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
current_clr_polling();
|
current_clr_polling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -928,16 +928,24 @@ static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
|
|||||||
*/
|
*/
|
||||||
static __cpuidle void mwait_idle(void)
|
static __cpuidle void mwait_idle(void)
|
||||||
{
|
{
|
||||||
|
if (need_resched())
|
||||||
|
return;
|
||||||
|
|
||||||
|
x86_idle_clear_cpu_buffers();
|
||||||
|
|
||||||
if (!current_set_polling_and_test()) {
|
if (!current_set_polling_and_test()) {
|
||||||
const void *addr = ¤t_thread_info()->flags;
|
const void *addr = ¤t_thread_info()->flags;
|
||||||
|
|
||||||
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
|
alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr));
|
||||||
__monitor(addr, 0, 0);
|
__monitor(addr, 0, 0);
|
||||||
if (!need_resched()) {
|
if (need_resched())
|
||||||
__sti_mwait(0, 0);
|
goto out;
|
||||||
raw_local_irq_disable();
|
|
||||||
}
|
__sti_mwait(0, 0);
|
||||||
|
raw_local_irq_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
__current_clr_polling();
|
__current_clr_polling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user