| From f15b01bd20d9d759f2f6cf061793aebf4f0363d8 Mon Sep 17 00:00:00 2001 |
| From: "Joel Fernandes (Google)" <joel@joelfernandes.org> |
| Date: Tue, 17 Nov 2020 18:20:01 -0500 |
| Subject: [PATCH] FROMLIST: sched: Add a coresched command line option |
| |
| Some hardware such as certain AMD variants don't have cross-HT MDS/L1TF |
| issues. Detect this and don't enable core scheduling as it can |
| needlessly slow those device down. |
| |
| However, some users may want core scheduling even if the hardware is |
| secure. To support them, add a coresched= option which defaults to |
| 'secure' and can be overridden to 'on' if the user wants to enable |
| coresched even if the HW is not vulnerable. 'off' would disable |
| core scheduling in any case. |
| |
| Also add a sched_debug entry to indicate if core scheduling is turned on |
| or not. |
| |
| (am from https://lore.kernel.org/patchwork/patch/1340786/) |
| |
| BUG=b:147685035 |
| TEST=build and boot for AMD device with 5.10 (grunt-kernelnext) |
| |
| Reviewed-by: Alexander Graf <graf@amazon.com> |
| Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org> |
| Change-Id: I392930ed0416656d009661f89f797082bf8ea5e9 |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2549724 |
| Reviewed-by: Joel Fernandes <joelaf@google.com> |
| Commit-Queue: Joel Fernandes <joelaf@google.com> |
| Tested-by: Joel Fernandes <joelaf@google.com> |
| (cherry picked from commit da34323f0c85a2e0ba780c33bbf83f917e080a0b) |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3067969 |
| Tested-by: Jacob Rasmussen <jacobraz@google.com> |
| Auto-Submit: Jacob Rasmussen <jacobraz@google.com> |
| Commit-Queue: Jacob Rasmussen <jacobraz@google.com> |
| --- |
| .../admin-guide/kernel-parameters.txt | 14 ++++++ |
| arch/x86/kernel/cpu/bugs.c | 19 ++++++++ |
| include/linux/cpu.h | 1 + |
| include/linux/sched/smt.h | 4 ++ |
| kernel/cpu.c | 45 +++++++++++++++++++ |
| kernel/sched/core.c | 7 ++- |
| kernel/sched/debug.c | 4 ++ |
| 7 files changed, 93 insertions(+), 1 deletion(-) |
| |
| diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt |
| --- a/Documentation/admin-guide/kernel-parameters.txt |
| +++ b/Documentation/admin-guide/kernel-parameters.txt |
| @@ -743,6 +743,20 @@ |
| /proc/<pid>/coredump_filter. |
| See also Documentation/filesystems/proc.rst. |
| |
| + coresched= [SCHED_CORE] This feature allows the Linux scheduler |
| + to force hyperthread siblings of a CPU to only execute tasks |
| + concurrently on all hyperthreads that are running within the |
| + same core scheduling group. |
| + Possible values are: |
| + 'on' - Enable scheduler capability to core schedule. |
| + By default, no tasks will be core scheduled, but the coresched |
| + interface can be used to form groups of tasks that are forced |
| + to share a core. |
| + 'off' - Disable scheduler capability to core schedule. |
| + 'secure' - Like 'on' but only enable on systems affected by |
| + MDS or L1TF vulnerabilities. 'off' otherwise. |
| + Default: 'secure'. |
| + |
| coresight_cpu_debug.enable |
| [ARM,ARM64] |
| Format: <bool> |
| diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c |
| --- a/arch/x86/kernel/cpu/bugs.c |
| +++ b/arch/x86/kernel/cpu/bugs.c |
| @@ -43,6 +43,7 @@ static void __init mds_select_mitigation(void); |
| static void __init mds_print_mitigation(void); |
| static void __init taa_select_mitigation(void); |
| static void __init srbds_select_mitigation(void); |
| +static void __init coresched_select(void); |
| static void __init l1d_flush_select_mitigation(void); |
| |
| /* The base value of the SPEC_CTRL MSR that always has to be preserved. */ |
| @@ -111,6 +112,9 @@ void __init check_bugs(void) |
| if (boot_cpu_has(X86_FEATURE_STIBP)) |
| x86_spec_ctrl_mask |= SPEC_CTRL_STIBP; |
| |
| + /* Update whether core-scheduling is needed. */ |
| + coresched_select(); |
| + |
| /* Select the proper CPU mitigations before patching alternatives: */ |
| spectre_v1_select_mitigation(); |
| spectre_v2_select_mitigation(); |
| @@ -1824,4 +1828,19 @@ ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char * |
| { |
| return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS); |
| } |
| + |
| +/* |
| + * When coresched=secure command line option is passed (default), disable core |
| + * scheduling if CPU does not have MDS/L1TF vulnerability. |
| + */ |
| +static void __init coresched_select(void) |
| +{ |
| +#ifdef CONFIG_SCHED_CORE |
| + if (coresched_cmd_secure() && |
| + !boot_cpu_has_bug(X86_BUG_MDS) && |
| + !boot_cpu_has_bug(X86_BUG_L1TF)) |
| + static_branch_disable(&sched_coresched_supported); |
| +#endif |
| +} |
| + |
| #endif |
| diff --git a/include/linux/cpu.h b/include/linux/cpu.h |
| --- a/include/linux/cpu.h |
| +++ b/include/linux/cpu.h |
| @@ -227,4 +227,5 @@ static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; |
| extern bool cpu_mitigations_off(void); |
| extern bool cpu_mitigations_auto_nosmt(void); |
| |
| +extern bool coresched_cmd_secure(void); |
| #endif /* _LINUX_CPU_H_ */ |
| diff --git a/include/linux/sched/smt.h b/include/linux/sched/smt.h |
| --- a/include/linux/sched/smt.h |
| +++ b/include/linux/sched/smt.h |
| @@ -17,4 +17,8 @@ static inline bool sched_smt_active(void) { return false; } |
| |
| void arch_smt_update(void); |
| |
| +#ifdef CONFIG_SCHED_CORE |
| +extern struct static_key_true sched_coresched_supported; |
| +#endif |
| + |
| #endif |
| diff --git a/kernel/cpu.c b/kernel/cpu.c |
| --- a/kernel/cpu.c |
| +++ b/kernel/cpu.c |
| @@ -2703,3 +2703,48 @@ bool cpu_mitigations_auto_nosmt(void) |
| return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT; |
| } |
| EXPORT_SYMBOL_GPL(cpu_mitigations_auto_nosmt); |
| + |
| +#ifdef CONFIG_SCHED_CORE |
| +/* |
| + * These are used for a global "coresched=" cmdline option for controlling |
| + * core scheduling. Note that core sched may be needed for usecases other |
| + * than security as well. |
| + */ |
| +enum coresched_cmds { |
| + CORE_SCHED_OFF, |
| + CORE_SCHED_SECURE, |
| + CORE_SCHED_ON, |
| +}; |
| + |
| +static enum coresched_cmds coresched_cmd __ro_after_init = CORE_SCHED_SECURE; |
| + |
| +static int __init coresched_parse_cmdline(char *arg) |
| +{ |
| + if (!strcmp(arg, "off")) |
| + coresched_cmd = CORE_SCHED_OFF; |
| + else if (!strcmp(arg, "on")) |
| + coresched_cmd = CORE_SCHED_ON; |
| + else if (!strcmp(arg, "secure")) |
| + /* |
| + * On x86, coresched=secure means coresched is enabled only if |
| + * system has MDS/L1TF vulnerability (see x86/bugs.c). |
| + */ |
| + coresched_cmd = CORE_SCHED_SECURE; |
| + else |
| + pr_crit("Unsupported coresched=%s, defaulting to secure.\n", |
| + arg); |
| + |
| + if (coresched_cmd == CORE_SCHED_OFF) |
| + static_branch_disable(&sched_coresched_supported); |
| + |
| + return 0; |
| +} |
| +early_param("coresched", coresched_parse_cmdline); |
| + |
| +/* coresched=secure */ |
| +bool coresched_cmd_secure(void) |
| +{ |
| + return coresched_cmd == CORE_SCHED_SECURE; |
| +} |
| +EXPORT_SYMBOL_GPL(coresched_cmd_secure); |
| +#endif |
| diff --git a/kernel/sched/core.c b/kernel/sched/core.c |
| --- a/kernel/sched/core.c |
| +++ b/kernel/sched/core.c |
| @@ -323,11 +323,14 @@ static void __sched_core_disable(void) |
| static_branch_disable(&__sched_core_enabled); |
| } |
| |
| +DEFINE_STATIC_KEY_TRUE(sched_coresched_supported); |
| + |
| void sched_core_get(void) |
| { |
| if (atomic_inc_not_zero(&sched_core_count)) |
| return; |
| - |
| + if (!static_branch_likely(&sched_coresched_supported)) |
| + return; |
| mutex_lock(&sched_core_mutex); |
| if (!atomic_read(&sched_core_count)) |
| __sched_core_enable(); |
| @@ -339,6 +342,8 @@ void sched_core_get(void) |
| |
| static void __sched_core_put(struct work_struct *work) |
| { |
| + if (!static_branch_likely(&sched_coresched_supported)) |
| + return; |
| if (atomic_dec_and_mutex_lock(&sched_core_count, &sched_core_mutex)) { |
| __sched_core_disable(); |
| mutex_unlock(&sched_core_mutex); |
| diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c |
| --- a/kernel/sched/debug.c |
| +++ b/kernel/sched/debug.c |
| @@ -814,6 +814,10 @@ static void sched_debug_header(struct seq_file *m) |
| "sysctl_sched_tunable_scaling", |
| sysctl_sched_tunable_scaling, |
| sched_tunable_scaling_names[sysctl_sched_tunable_scaling]); |
| +#ifdef CONFIG_SCHED_CORE |
| + SEQ_printf(m, " .%-40s: %d\n", "core_sched_enabled", |
| + !!static_branch_likely(&__sched_core_enabled)); |
| +#endif |
| SEQ_printf(m, "\n"); |
| } |
| |
| -- |
| 2.33.0.464.g1972c5931b-goog |
| |