diff options
| -rw-r--r-- | Documentation/admin-guide/kernel-parameters.txt | 7 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/bugs.c | 41 |
2 files changed, 38 insertions, 10 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index b6e5b33b9d75..a9b98a4e8789 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt | |||
| @@ -4236,9 +4236,14 @@ | |||
| 4236 | off - Unconditionally disable mitigations. Is | 4236 | off - Unconditionally disable mitigations. Is |
| 4237 | enforced by spectre_v2=off | 4237 | enforced by spectre_v2=off |
| 4238 | 4238 | ||
| 4239 | prctl - Indirect branch speculation is enabled, | ||
| 4240 | but mitigation can be enabled via prctl | ||
| 4241 | per thread. The mitigation control state | ||
| 4242 | is inherited on fork. | ||
| 4243 | |||
| 4239 | auto - Kernel selects the mitigation depending on | 4244 | auto - Kernel selects the mitigation depending on |
| 4240 | the available CPU features and vulnerability. | 4245 | the available CPU features and vulnerability. |
| 4241 | Default is off. | 4246 | Default is prctl. |
| 4242 | 4247 | ||
| 4243 | Not specifying this option is equivalent to | 4248 | Not specifying this option is equivalent to |
| 4244 | spectre_v2_user=auto. | 4249 | spectre_v2_user=auto. |
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 74359fff87fd..d0137d10f9a6 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c | |||
| @@ -255,11 +255,13 @@ enum spectre_v2_user_cmd { | |||
| 255 | SPECTRE_V2_USER_CMD_NONE, | 255 | SPECTRE_V2_USER_CMD_NONE, |
| 256 | SPECTRE_V2_USER_CMD_AUTO, | 256 | SPECTRE_V2_USER_CMD_AUTO, |
| 257 | SPECTRE_V2_USER_CMD_FORCE, | 257 | SPECTRE_V2_USER_CMD_FORCE, |
| 258 | SPECTRE_V2_USER_CMD_PRCTL, | ||
| 258 | }; | 259 | }; |
| 259 | 260 | ||
| 260 | static const char * const spectre_v2_user_strings[] = { | 261 | static const char * const spectre_v2_user_strings[] = { |
| 261 | [SPECTRE_V2_USER_NONE] = "User space: Vulnerable", | 262 | [SPECTRE_V2_USER_NONE] = "User space: Vulnerable", |
| 262 | [SPECTRE_V2_USER_STRICT] = "User space: Mitigation: STIBP protection", | 263 | [SPECTRE_V2_USER_STRICT] = "User space: Mitigation: STIBP protection", |
| 264 | [SPECTRE_V2_USER_PRCTL] = "User space: Mitigation: STIBP via prctl", | ||
| 263 | }; | 265 | }; |
| 264 | 266 | ||
| 265 | static const struct { | 267 | static const struct { |
| @@ -270,6 +272,7 @@ static const struct { | |||
| 270 | { "auto", SPECTRE_V2_USER_CMD_AUTO, false }, | 272 | { "auto", SPECTRE_V2_USER_CMD_AUTO, false }, |
| 271 | { "off", SPECTRE_V2_USER_CMD_NONE, false }, | 273 | { "off", SPECTRE_V2_USER_CMD_NONE, false }, |
| 272 | { "on", SPECTRE_V2_USER_CMD_FORCE, true }, | 274 | { "on", SPECTRE_V2_USER_CMD_FORCE, true }, |
| 275 | { "prctl", SPECTRE_V2_USER_CMD_PRCTL, false }, | ||
| 273 | }; | 276 | }; |
| 274 | 277 | ||
| 275 | static void __init spec_v2_user_print_cond(const char *reason, bool secure) | 278 | static void __init spec_v2_user_print_cond(const char *reason, bool secure) |
| @@ -324,12 +327,15 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd) | |||
| 324 | smt_possible = false; | 327 | smt_possible = false; |
| 325 | 328 | ||
| 326 | switch (spectre_v2_parse_user_cmdline(v2_cmd)) { | 329 | switch (spectre_v2_parse_user_cmdline(v2_cmd)) { |
| 327 | case SPECTRE_V2_USER_CMD_AUTO: | ||
| 328 | case SPECTRE_V2_USER_CMD_NONE: | 330 | case SPECTRE_V2_USER_CMD_NONE: |
| 329 | goto set_mode; | 331 | goto set_mode; |
| 330 | case SPECTRE_V2_USER_CMD_FORCE: | 332 | case SPECTRE_V2_USER_CMD_FORCE: |
| 331 | mode = SPECTRE_V2_USER_STRICT; | 333 | mode = SPECTRE_V2_USER_STRICT; |
| 332 | break; | 334 | break; |
| 335 | case SPECTRE_V2_USER_CMD_AUTO: | ||
| 336 | case SPECTRE_V2_USER_CMD_PRCTL: | ||
| 337 | mode = SPECTRE_V2_USER_PRCTL; | ||
| 338 | break; | ||
| 333 | } | 339 | } |
| 334 | 340 | ||
| 335 | /* Initialize Indirect Branch Prediction Barrier */ | 341 | /* Initialize Indirect Branch Prediction Barrier */ |
| @@ -340,6 +346,9 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd) | |||
| 340 | case SPECTRE_V2_USER_STRICT: | 346 | case SPECTRE_V2_USER_STRICT: |
| 341 | static_branch_enable(&switch_mm_always_ibpb); | 347 | static_branch_enable(&switch_mm_always_ibpb); |
| 342 | break; | 348 | break; |
| 349 | case SPECTRE_V2_USER_PRCTL: | ||
| 350 | static_branch_enable(&switch_mm_cond_ibpb); | ||
| 351 | break; | ||
| 343 | default: | 352 | default: |
| 344 | break; | 353 | break; |
| 345 | } | 354 | } |
| @@ -352,6 +361,12 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd) | |||
| 352 | if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED) | 361 | if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED) |
| 353 | return; | 362 | return; |
| 354 | 363 | ||
| 364 | /* | ||
| 365 | * If SMT is not possible or STIBP is not available clear the STIPB | ||
| 366 | * mode. | ||
| 367 | */ | ||
| 368 | if (!smt_possible || !boot_cpu_has(X86_FEATURE_STIBP)) | ||
| 369 | mode = SPECTRE_V2_USER_NONE; | ||
| 355 | set_mode: | 370 | set_mode: |
| 356 | spectre_v2_user = mode; | 371 | spectre_v2_user = mode; |
| 357 | /* Only print the STIBP mode when SMT possible */ | 372 | /* Only print the STIBP mode when SMT possible */ |
| @@ -552,6 +567,15 @@ static void update_stibp_strict(void) | |||
| 552 | on_each_cpu(update_stibp_msr, NULL, 1); | 567 | on_each_cpu(update_stibp_msr, NULL, 1); |
| 553 | } | 568 | } |
| 554 | 569 | ||
| 570 | /* Update the static key controlling the evaluation of TIF_SPEC_IB */ | ||
| 571 | static void update_indir_branch_cond(void) | ||
| 572 | { | ||
| 573 | if (sched_smt_active()) | ||
| 574 | static_branch_enable(&switch_to_cond_stibp); | ||
| 575 | else | ||
| 576 | static_branch_disable(&switch_to_cond_stibp); | ||
| 577 | } | ||
| 578 | |||
| 555 | void arch_smt_update(void) | 579 | void arch_smt_update(void) |
| 556 | { | 580 | { |
| 557 | /* Enhanced IBRS implies STIBP. No update required. */ | 581 | /* Enhanced IBRS implies STIBP. No update required. */ |
| @@ -567,6 +591,7 @@ void arch_smt_update(void) | |||
| 567 | update_stibp_strict(); | 591 | update_stibp_strict(); |
| 568 | break; | 592 | break; |
| 569 | case SPECTRE_V2_USER_PRCTL: | 593 | case SPECTRE_V2_USER_PRCTL: |
| 594 | update_indir_branch_cond(); | ||
| 570 | break; | 595 | break; |
| 571 | } | 596 | } |
| 572 | 597 | ||
| @@ -1038,7 +1063,8 @@ static char *stibp_state(void) | |||
| 1038 | case SPECTRE_V2_USER_STRICT: | 1063 | case SPECTRE_V2_USER_STRICT: |
| 1039 | return ", STIBP: forced"; | 1064 | return ", STIBP: forced"; |
| 1040 | case SPECTRE_V2_USER_PRCTL: | 1065 | case SPECTRE_V2_USER_PRCTL: |
| 1041 | return ""; | 1066 | if (static_key_enabled(&switch_to_cond_stibp)) |
| 1067 | return ", STIBP: conditional"; | ||
| 1042 | } | 1068 | } |
| 1043 | return ""; | 1069 | return ""; |
| 1044 | } | 1070 | } |
| @@ -1046,14 +1072,11 @@ static char *stibp_state(void) | |||
| 1046 | static char *ibpb_state(void) | 1072 | static char *ibpb_state(void) |
| 1047 | { | 1073 | { |
| 1048 | if (boot_cpu_has(X86_FEATURE_IBPB)) { | 1074 | if (boot_cpu_has(X86_FEATURE_IBPB)) { |
| 1049 | switch (spectre_v2_user) { | 1075 | if (static_key_enabled(&switch_mm_always_ibpb)) |
| 1050 | case SPECTRE_V2_USER_NONE: | ||
| 1051 | return ", IBPB: disabled"; | ||
| 1052 | case SPECTRE_V2_USER_STRICT: | ||
| 1053 | return ", IBPB: always-on"; | 1076 | return ", IBPB: always-on"; |
| 1054 | case SPECTRE_V2_USER_PRCTL: | 1077 | if (static_key_enabled(&switch_mm_cond_ibpb)) |
| 1055 | return ""; | 1078 | return ", IBPB: conditional"; |
| 1056 | } | 1079 | return ", IBPB: disabled"; |
| 1057 | } | 1080 | } |
| 1058 | return ""; | 1081 | return ""; |
| 1059 | } | 1082 | } |
