Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/fpu: Disable MPX when eagerfpu is off

This issue is a fallout from the command-line parsing move.

When "eagerfpu=off" is given as a command-line input, the kernel
should disable MPX support. The decision for turning off MPX was
made in fpu__init_system_ctx_switch(), which is after the
selection of the XSAVE format. This patch fixes it by getting
that decision done earlier in fpu__init_system_xstate().

Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Cc: Ravi V. Shankar <ravi.v.shankar@intel.com>
Cc: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: yu-cheng yu <yu-cheng.yu@intel.com>
Link: http://lkml.kernel.org/r/1452119094-7252-4-git-send-email-yu-cheng.yu@intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

yu-cheng yu and committed by
Ingo Molnar
a5fe93a5 eb7c5f87

+46 -14
+1
arch/x86/include/asm/fpu/internal.h
··· 42 42 extern void fpu__init_system(struct cpuinfo_x86 *c); 43 43 extern void fpu__init_check_bugs(void); 44 44 extern void fpu__resume_cpu(void); 45 + extern u64 fpu__get_supported_xfeatures_mask(void); 45 46 46 47 /* 47 48 * Debugging facility:
+44 -12
arch/x86/kernel/fpu/init.c
··· 274 274 static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO; 275 275 276 276 /* 277 + * Find supported xfeatures based on cpu features and command-line input. 278 + * This must be called after fpu__init_parse_early_param() is called and 279 + * xfeatures_mask is enumerated. 280 + */ 281 + u64 __init fpu__get_supported_xfeatures_mask(void) 282 + { 283 + /* Support all xfeatures known to us */ 284 + if (eagerfpu != DISABLE) 285 + return XCNTXT_MASK; 286 + 287 + /* Warning of xfeatures being disabled for no eagerfpu mode */ 288 + if (xfeatures_mask & XFEATURE_MASK_EAGER) { 289 + pr_err("x86/fpu: eagerfpu switching disabled, disabling the following xstate features: 0x%llx.\n", 290 + xfeatures_mask & XFEATURE_MASK_EAGER); 291 + } 292 + 293 + /* Return a mask that masks out all features requiring eagerfpu mode */ 294 + return ~XFEATURE_MASK_EAGER; 295 + } 296 + 297 + /* 298 + * Disable features dependent on eagerfpu. 299 + */ 300 + static void __init fpu__clear_eager_fpu_features(void) 301 + { 302 + setup_clear_cpu_cap(X86_FEATURE_MPX); 303 + } 304 + 305 + /* 277 306 * Pick the FPU context switching strategy: 307 + * 308 + * When eagerfpu is AUTO or ENABLE, we ensure it is ENABLE if either of 309 + * the following is true: 310 + * 311 + * (1) the cpu has xsaveopt, as it has the optimization and doing eager 312 + * FPU switching has a relatively low cost compared to a plain xsave; 313 + * (2) the cpu has xsave features (e.g. MPX) that depend on eager FPU 314 + * switching. Should the kernel boot with noxsaveopt, we support MPX 315 + * with eager FPU switching at a higher cost. 278 316 */ 279 317 static void __init fpu__init_system_ctx_switch(void) 280 318 { ··· 324 286 WARN_ON_FPU(current->thread.fpu.fpstate_active); 325 287 current_thread_info()->status = 0; 326 288 327 - /* Auto enable eagerfpu for xsaveopt */ 328 289 if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE) 329 290 eagerfpu = ENABLE; 330 291 331 - if (xfeatures_mask & XFEATURE_MASK_EAGER) { 332 - if (eagerfpu == DISABLE) { 333 - pr_err("x86/fpu: eagerfpu switching disabled, disabling the following xstate features: 0x%llx.\n", 334 - xfeatures_mask & XFEATURE_MASK_EAGER); 335 - xfeatures_mask &= ~XFEATURE_MASK_EAGER; 336 - } else { 337 - eagerfpu = ENABLE; 338 - } 339 - } 292 + if (xfeatures_mask & XFEATURE_MASK_EAGER) 293 + eagerfpu = ENABLE; 340 294 341 295 if (eagerfpu == ENABLE) 342 296 setup_force_cpu_cap(X86_FEATURE_EAGER_FPU); ··· 346 316 * No need to check "eagerfpu=auto" again, since it is the 347 317 * initial default. 348 318 */ 349 - if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) 319 + if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) { 350 320 eagerfpu = DISABLE; 351 - else if (cmdline_find_option_bool(boot_command_line, "eagerfpu=on")) 321 + fpu__clear_eager_fpu_features(); 322 + } else if (cmdline_find_option_bool(boot_command_line, "eagerfpu=on")) { 352 323 eagerfpu = ENABLE; 324 + } 353 325 354 326 if (cmdline_find_option_bool(boot_command_line, "no387")) 355 327 setup_clear_cpu_cap(X86_FEATURE_FPU);
+1 -2
arch/x86/kernel/fpu/xstate.c
··· 633 633 BUG(); 634 634 } 635 635 636 - /* Support only the state known to the OS: */ 637 - xfeatures_mask = xfeatures_mask & XCNTXT_MASK; 636 + xfeatures_mask &= fpu__get_supported_xfeatures_mask(); 638 637 639 638 /* Enable xstate instructions to be able to continue with initialization: */ 640 639 fpu__init_cpu_xstate();