Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP3:GA
xen.8425
5a6b36cd-9-x86-clear-SPEC_CTRL-while-idle.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 5a6b36cd-9-x86-clear-SPEC_CTRL-while-idle.patch of Package xen.8425
# Commit 4c7e478d597b0346eef3a256cfd6794ac778b608 # Date 2018-01-26 14:10:21 +0000 # Author Andrew Cooper <andrew.cooper3@citrix.com> # Committer Andrew Cooper <andrew.cooper3@citrix.com> x86/idle: Clear SPEC_CTRL while idle On contemporary hardware, setting IBRS/STIBP has a performance impact on adjacent hyperthreads. It is therefore recommended to clear the setting before becoming idle, to avoid an idle core preventing adjacent userspace execution from running at full performance. Care must be taken to ensure there are no ret or indirect branch instructions between spec_ctrl_{enter,exit}_idle() invocations, which are forced always inline. Care must also be taken to avoid using spec_ctrl_enter_idle() between flushing caches and becoming idle, in cases where that matters. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/acpi/cpu_idle.c +++ b/xen/arch/x86/acpi/cpu_idle.c @@ -57,6 +57,7 @@ #include <asm/mwait.h> #include <xen/notifier.h> #include <xen/cpu.h> +#include <asm/spec_ctrl.h> /*#define DEBUG_PM_CX*/ @@ -349,8 +350,14 @@ void mwait_idle_with_hints(unsigned int */ if ( (expires > NOW() || expires == 0) && !softirq_pending(cpu) ) { + struct cpu_info *info = get_cpu_info(); + cpumask_set_cpu(cpu, &cpuidle_mwait_flags); + + spec_ctrl_enter_idle(info); __mwait(eax, ecx); + spec_ctrl_exit_idle(info); + cpumask_clear_cpu(cpu, &cpuidle_mwait_flags); } @@ -365,6 +372,8 @@ static void acpi_processor_ffh_cstate_en static void acpi_idle_do_entry(struct acpi_processor_cx *cx) { + struct cpu_info *info = get_cpu_info(); + switch ( cx->entry_method ) { case ACPI_CSTATE_EM_FFH: @@ -372,15 +381,19 @@ static void acpi_idle_do_entry(struct ac acpi_processor_ffh_cstate_enter(cx); return; case ACPI_CSTATE_EM_SYSIO: + spec_ctrl_enter_idle(info); /* IO port based C-state */ inb(cx->address); /* Dummy wait op - must do something useless after P_LVL2 read because chipsets cannot guarantee that STPCLK# signal gets asserted in time to freeze execution properly. */ inl(pmtmr_ioport); + spec_ctrl_exit_idle(info); return; case ACPI_CSTATE_EM_HALT: + spec_ctrl_enter_idle(info); safe_halt(); + spec_ctrl_exit_idle(info); local_irq_disable(); return; } @@ -495,7 +508,13 @@ static void acpi_processor_idle(void) if ( pm_idle_save ) pm_idle_save(); else + { + struct cpu_info *info = get_cpu_info(); + + spec_ctrl_enter_idle(info); safe_halt(); + spec_ctrl_exit_idle(info); + } return; } @@ -670,6 +689,7 @@ void acpi_dead_idle(void) * Otherwise, CPU may still hold dirty data, breaking cache coherency, * leading to strange errors. */ + spec_ctrl_enter_idle(get_cpu_info()); wbinvd(); while ( 1 ) @@ -699,6 +719,7 @@ void acpi_dead_idle(void) u32 address = cx->address; u32 pmtmr_ioport_local = pmtmr_ioport; + spec_ctrl_enter_idle(get_cpu_info()); wbinvd(); while ( 1 ) --- a/xen/arch/x86/cpu/mwait-idle.c +++ b/xen/arch/x86/cpu/mwait-idle.c @@ -59,6 +59,7 @@ #include <asm/hpet.h> #include <asm/mwait.h> #include <asm/msr.h> +#include <asm/spec_ctrl.h> #include <acpi/cpufreq/cpufreq.h> #define MWAIT_IDLE_VERSION "0.4" @@ -375,7 +376,13 @@ static void mwait_idle(void) if (pm_idle_save) pm_idle_save(); else + { + struct cpu_info *info = get_cpu_info(); + + spec_ctrl_enter_idle(info); safe_halt(); + spec_ctrl_exit_idle(info); + } return; } --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -53,6 +53,7 @@ #include <asm/hvm/support.h> #include <asm/debugreg.h> #include <asm/msr.h> +#include <asm/spec_ctrl.h> #include <asm/traps.h> #include <asm/nmi.h> #include <asm/mce.h> @@ -74,9 +75,15 @@ static void paravirt_ctxt_switch_to(stru static void default_idle(void) { + struct cpu_info *info = get_cpu_info(); + local_irq_disable(); if ( cpu_is_haltable(smp_processor_id()) ) + { + spec_ctrl_enter_idle(info); safe_halt(); + spec_ctrl_exit_idle(info); + } else local_irq_enable(); } @@ -88,6 +95,7 @@ void default_dead_idle(void) * held by the CPUs spinning here indefinitely, and get discarded by * a subsequent INIT. */ + spec_ctrl_enter_idle(get_cpu_info()); wbinvd(); for ( ; ; ) halt(); --- a/xen/include/asm-x86/spec_ctrl.h +++ b/xen/include/asm-x86/spec_ctrl.h @@ -21,6 +21,7 @@ #define __X86_SPEC_CTRL_H__ #include <asm/current.h> +#include <asm/msr.h> void init_speculation_mitigations(void); @@ -37,6 +38,38 @@ static inline void init_shadow_spec_ctrl info->xen_rsb = default_xen_rsb; } +/* WARNING! `ret`, `call *`, `jmp *` not safe after this call. */ +static always_inline void spec_ctrl_enter_idle(struct cpu_info *info) +{ + if ( info->xen_ibrs <= 0 ) + return; + + /* + * Latch the new shadow value, then enable shadowing, then update the MSR. + * There are no SMP issues here; only local processor ordering concerns. + */ + info->shadow_spec_ctrl = 0; + barrier(); + info->use_shadow_spec_ctrl = 1; + barrier(); + wrmsr(MSR_SPEC_CTRL, 0, 0); +} + +/* WARNING! `ret`, `call *`, `jmp *` not safe before this call. */ +static always_inline void spec_ctrl_exit_idle(struct cpu_info *info) +{ + if ( info->xen_ibrs <= 0 ) + return; + + /* + * Disable shadowing before updating the MSR. There are no SMP issues + * here; only local processor ordering concerns. + */ + info->use_shadow_spec_ctrl = 0; + barrier(); + wrmsr(MSR_SPEC_CTRL, SPEC_CTRL_IBRS, 0); +} + #endif /* !__X86_SPEC_CTRL_H__ */ /*
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor