diff options
author | yu-cheng yu <yu-cheng.yu@intel.com> | 2016-01-06 17:24:53 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-01-12 05:51:21 -0500 |
commit | a5fe93a549c54838063d2952dd9643b0b18aa67f (patch) | |
tree | 21f291bf9c27b7e62182b4ced5be5696f0b5396b | |
parent | eb7c5f872e697b0aebd846cf3a3328d71e9decb2 (diff) |
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>
-rw-r--r-- | arch/x86/include/asm/fpu/internal.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/fpu/init.c | 56 | ||||
-rw-r--r-- | arch/x86/kernel/fpu/xstate.c | 3 |
3 files changed, 46 insertions, 14 deletions
diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index eadcdd5bb946..0fd440df63f1 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h | |||
@@ -42,6 +42,7 @@ extern void fpu__init_cpu_xstate(void); | |||
42 | extern void fpu__init_system(struct cpuinfo_x86 *c); | 42 | extern void fpu__init_system(struct cpuinfo_x86 *c); |
43 | extern void fpu__init_check_bugs(void); | 43 | extern void fpu__init_check_bugs(void); |
44 | extern void fpu__resume_cpu(void); | 44 | extern void fpu__resume_cpu(void); |
45 | extern u64 fpu__get_supported_xfeatures_mask(void); | ||
45 | 46 | ||
46 | /* | 47 | /* |
47 | * Debugging facility: | 48 | * Debugging facility: |
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 3a45fcd0b924..f0ab36844a6d 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c | |||
@@ -274,7 +274,45 @@ static void __init fpu__init_system_xstate_size_legacy(void) | |||
274 | static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO; | 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 | * Pick the FPU context switching strategy: | 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 | static void __init fpu__init_system_ctx_switch(void) | 317 | static void __init fpu__init_system_ctx_switch(void) |
280 | { | 318 | { |
@@ -286,19 +324,11 @@ static void __init fpu__init_system_ctx_switch(void) | |||
286 | WARN_ON_FPU(current->thread.fpu.fpstate_active); | 324 | WARN_ON_FPU(current->thread.fpu.fpstate_active); |
287 | current_thread_info()->status = 0; | 325 | current_thread_info()->status = 0; |
288 | 326 | ||
289 | /* Auto enable eagerfpu for xsaveopt */ | ||
290 | if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE) | 327 | if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE) |
291 | eagerfpu = ENABLE; | 328 | eagerfpu = ENABLE; |
292 | 329 | ||
293 | if (xfeatures_mask & XFEATURE_MASK_EAGER) { | 330 | if (xfeatures_mask & XFEATURE_MASK_EAGER) |
294 | if (eagerfpu == DISABLE) { | 331 | eagerfpu = ENABLE; |
295 | pr_err("x86/fpu: eagerfpu switching disabled, disabling the following xstate features: 0x%llx.\n", | ||
296 | xfeatures_mask & XFEATURE_MASK_EAGER); | ||
297 | xfeatures_mask &= ~XFEATURE_MASK_EAGER; | ||
298 | } else { | ||
299 | eagerfpu = ENABLE; | ||
300 | } | ||
301 | } | ||
302 | 332 | ||
303 | if (eagerfpu == ENABLE) | 333 | if (eagerfpu == ENABLE) |
304 | setup_force_cpu_cap(X86_FEATURE_EAGER_FPU); | 334 | setup_force_cpu_cap(X86_FEATURE_EAGER_FPU); |
@@ -316,10 +346,12 @@ static void __init fpu__init_parse_early_param(void) | |||
316 | * No need to check "eagerfpu=auto" again, since it is the | 346 | * No need to check "eagerfpu=auto" again, since it is the |
317 | * initial default. | 347 | * initial default. |
318 | */ | 348 | */ |
319 | if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) | 349 | if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) { |
320 | eagerfpu = DISABLE; | 350 | eagerfpu = DISABLE; |
321 | else if (cmdline_find_option_bool(boot_command_line, "eagerfpu=on")) | 351 | fpu__clear_eager_fpu_features(); |
352 | } else if (cmdline_find_option_bool(boot_command_line, "eagerfpu=on")) { | ||
322 | eagerfpu = ENABLE; | 353 | eagerfpu = ENABLE; |
354 | } | ||
323 | 355 | ||
324 | if (cmdline_find_option_bool(boot_command_line, "no387")) | 356 | if (cmdline_find_option_bool(boot_command_line, "no387")) |
325 | setup_clear_cpu_cap(X86_FEATURE_FPU); | 357 | setup_clear_cpu_cap(X86_FEATURE_FPU); |
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index d489f277a8a0..d425cda5ae6d 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c | |||
@@ -633,8 +633,7 @@ void __init fpu__init_system_xstate(void) | |||
633 | BUG(); | 633 | BUG(); |
634 | } | 634 | } |
635 | 635 | ||
636 | /* Support only the state known to the OS: */ | 636 | xfeatures_mask &= fpu__get_supported_xfeatures_mask(); |
637 | xfeatures_mask = xfeatures_mask & XCNTXT_MASK; | ||
638 | 637 | ||
639 | /* Enable xstate instructions to be able to continue with initialization: */ | 638 | /* Enable xstate instructions to be able to continue with initialization: */ |
640 | fpu__init_cpu_xstate(); | 639 | fpu__init_cpu_xstate(); |