From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Tim Chen Date: Mon, 6 Nov 2017 18:19:14 -0800 Subject: [PATCH] x86/idle: Disable IBRS entering idle and enable it on wakeup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CVE-2017-5753 CVE-2017-5715 Clear IBRS on idle entry and set it on idle exit into kernel on mwait. Signed-off-by: Tim Chen Signed-off-by: Andy Whitcroft Signed-off-by: Kleber Sacilotto de Souza (cherry picked from commit 5521b04afda1d683c1ebad6c25c2529a88e6f061) Signed-off-by: Fabian Grünbichler --- arch/x86/include/asm/mwait.h | 8 ++++++++ arch/x86/kernel/process.c | 12 ++++++++++-- arch/x86/lib/delay.c | 10 ++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h index bda3c27f0da0..f15120ada161 100644 --- a/arch/x86/include/asm/mwait.h +++ b/arch/x86/include/asm/mwait.h @@ -5,6 +5,8 @@ #include #include +#include +#include #define MWAIT_SUBSTATE_MASK 0xf #define MWAIT_CSTATE_MASK 0xf @@ -105,9 +107,15 @@ static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) mb(); } + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + native_wrmsrl(MSR_IA32_SPEC_CTRL, 0); + __monitor((void *)¤t_thread_info()->flags, 0, 0); if (!need_resched()) __mwait(eax, ecx); + + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + native_wrmsrl(MSR_IA32_SPEC_CTRL, FEATURE_ENABLE_IBRS); } current_clr_polling(); } diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 07e6218ad7d9..3adb3806a284 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -447,11 +447,19 @@ static __cpuidle void mwait_idle(void) mb(); /* quirk */ } + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + native_wrmsrl(MSR_IA32_SPEC_CTRL, 0); + __monitor((void *)¤t_thread_info()->flags, 0, 0); - if (!need_resched()) + if (!need_resched()) { __sti_mwait(0, 0); - else + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + native_wrmsrl(MSR_IA32_SPEC_CTRL, FEATURE_ENABLE_IBRS); + } else { + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + native_wrmsrl(MSR_IA32_SPEC_CTRL, FEATURE_ENABLE_IBRS); local_irq_enable(); + } trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id()); } else { local_irq_enable(); diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index cf2ac227c2ac..b088463973e4 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c @@ -26,6 +26,8 @@ # include #endif +#define IBRS_DISABLE_THRESHOLD 1000 + /* simple loop based delay: */ static void delay_loop(unsigned long loops) { @@ -105,6 +107,10 @@ static void delay_mwaitx(unsigned long __loops) for (;;) { delay = min_t(u64, MWAITX_MAX_LOOPS, loops); + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL) && + (delay > IBRS_DISABLE_THRESHOLD)) + native_wrmsrl(MSR_IA32_SPEC_CTRL, 0); + /* * Use cpu_tss_rw as a cacheline-aligned, seldomly * accessed per-cpu variable as the monitor target. @@ -118,6 +124,10 @@ static void delay_mwaitx(unsigned long __loops) */ __mwaitx(MWAITX_DISABLE_CSTATES, delay, MWAITX_ECX_TIMER_ENABLE); + if (boot_cpu_has(X86_FEATURE_SPEC_CTRL) && + (delay > IBRS_DISABLE_THRESHOLD)) + native_wrmsrl(MSR_IA32_SPEC_CTRL, FEATURE_ENABLE_IBRS); + end = rdtsc_ordered(); if (loops <= end - start) -- 2.14.2