blob: 56849bb5c4eb8e95293b60e089fd00f9658c5eb9 [file] [log] [blame]
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