summaryrefslogtreecommitdiff
path: root/tools/testing
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-15 14:50:18 +0530
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-15 14:50:18 +0530
commit2cbf335f8ccc7a6418159858dc03e36df8e3e5cf (patch)
tree1ff36263ce50da08cf0f078d398f3f398ee5a015 /tools/testing
parent0bcc2dc22f38e57fa97d8238b2e0bcdde5376f33 (diff)
parentc095741713d1bc317b53e2da2b222e7448b6021f (diff)
Merge tag 'sched-core-2026-06-14' of gitolite.kernel.org:pub/scm/linux/kernel/git/tip/tip
Pull scheduler updates from Ingo Molnar: "SMP load-balancing updates: - A large series to introduce infrastructure for cache-aware load balancing, with the goal of co-locating tasks that share data within the same Last Level Cache (LLC) domain. By improving cache locality, the scheduler can reduce cache bouncing and cache misses, ultimately improving data access efficiency. Implemented by Chen Yu and Tim Chen, based on early prototype work by Peter Zijlstra, with fixes by Jianyong Wu, Peter Zijlstra and Shrikanth Hegde. - A series to simplify CONFIG_SCHED_SMT ifdef usage (Shrikanth Hegde) Fair scheduler updates: - A series to improve SD_ASYM_CPUCAPACITY scheduling by introducing SMT awareness (Andrea Righi, K Prateek Nayak) - A series to optimize cfs_rq and sched_entity allocation for better data locality (Zecheng Li) - A preparatory series to change fair/cgroup scheduling to a single runqueue, without the final change (Peter Zijlstra) - Auto-manage ext/fair dl_server bandwidth (Andrea Righi) - Fix cpu_util runnable_avg arithmetic (Hongyan Xia) - Optimize update_tg_load_avg()'s rate-limiting code (Rik van Riel) - Allow account_cfs_rq_runtime() to throttle current hierarchy (K Prateek Nayak) - Update util_est after updating util_avg during dequeue, to fix the util signal update logic, which reduces signal noise (Vincent Guittot) Scheduler topology updates: - Allow multiple domains to claim sched_domain_shared (K Prateek Nayak) - Add parameter to split LLC (Peter Zijlstra) Core scheduler updates: - Use trace_call__<tp>() to save a static branch (Gabriele Monaco) Scheduler statistics updates: - Drop now-stale mul_u64_u64_div_u64() cputime over-approximation guard (Nicolas Pitre) Deadline scheduler updates: - Reject debugfs dl_server writes for offline CPUs (Andrea Righi) - Fix replenishment logic for non-deferred servers (Yuri Andriaccio) RT scheduling updates: - Turn RT_PUSH_IPI default off for non PREEMPT_RT (Steven Rostedt) - Update default bandwidth for real-time tasks to 1.0 (Yuri Andriaccio) Proxy scheduling updates: - A series to implement Optimized Donor Migration for Proxy Execution (John Stultz, Peter Zijlstra) - Various proxy scheduling cleanups and fixes (Peter Zijlstra, K Prateek Nayak) Misc fixes, improvements and cleanups by Aaron Lu, Andrea Righi, Zenghui Yu, Chen Yu, Guanyou.Chen, John Stultz, Shrikanth Hegde, Peter Zijlstra, Liang Luo and Yiyang Chen" * tag 'sched-core-2026-06-14' of gitolite.kernel.org:pub/scm/linux/kernel/git/tip/tip: (91 commits) sched/fair: Fix newidle vs core-sched sched/deadline: Use task_on_rq_migrating() helper sched/core: Combine separate 'else' and 'if' statements sched/fair: Fix cpu_util runnable_avg arithmetic sched/fair: Unify cfs_rq throttling via account_cfs_rq_runtime() sched/fair: Move the throttled tasks to a local list in tg_unthrottle_up() sched/fair: Call update_curr() before unthrottling the hierarchy sched/fair: Use throttled_csd_list for local unthrottle sched/fair: Convert cfs bandwidth throttling to use guards sched/fair: Allocate cfs_tg_state with percpu allocator sched/fair: Remove task_group->se pointer array sched/fair: Co-locate cfs_rq and sched_entity in cfs_tg_state sched: restore timer_slack_ns when resetting RT policy on fork MAINTAINERS: Fix spelling mistake in Peter's name sched: Simplify ttwu_runnable() sched/proxy: Remove superfluous clear_task_blocked_in() sched/proxy: Remove PROXY_WAKING sched/proxy: Switch proxy to use p->is_blocked sched/proxy: Only return migrate when needed sched: Be more strict about p->is_blocked ...
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/selftests/sched_ext/total_bw.c201
1 files changed, 200 insertions, 1 deletions
diff --git a/tools/testing/selftests/sched_ext/total_bw.c b/tools/testing/selftests/sched_ext/total_bw.c
index 5b0a619bab86..2af01cee90cc 100644
--- a/tools/testing/selftests/sched_ext/total_bw.c
+++ b/tools/testing/selftests/sched_ext/total_bw.c
@@ -100,6 +100,98 @@ static int read_total_bw_values(long *bw_values, int max_cpus)
return cpu_count;
}
+/*
+ * Read a per-CPU dl_server param (runtime or period) from debugfs.
+ * Returns the value in nanoseconds, or -1 on failure.
+ */
+static long read_server_param(const char *server, const char *param, int cpu)
+{
+ char path[128];
+ long value = -1;
+ FILE *fp;
+
+ snprintf(path, sizeof(path),
+ "/sys/kernel/debug/sched/%s_server/cpu%d/%s",
+ server, cpu, param);
+ fp = fopen(path, "r");
+ if (!fp)
+ return -1;
+ if (fscanf(fp, "%ld", &value) != 1)
+ value = -1;
+ fclose(fp);
+
+ return value;
+}
+
+/*
+ * Write a per-CPU dl_server param to debugfs. Returns 0 on success.
+ */
+static int write_server_param(const char *server, const char *param,
+ int cpu, long value)
+{
+ char path[128];
+ FILE *fp;
+ int ret = 0;
+
+ snprintf(path, sizeof(path),
+ "/sys/kernel/debug/sched/%s_server/cpu%d/%s",
+ server, cpu, param);
+ fp = fopen(path, "w");
+ if (!fp)
+ return -1;
+ if (fprintf(fp, "%ld", value) < 0)
+ ret = -1;
+ if (fclose(fp) != 0)
+ ret = -1;
+
+ return ret;
+}
+
+static int read_fair_runtime_all(int nr_cpus, long *runtimes)
+{
+ int i;
+
+ for (i = 0; i < nr_cpus; i++) {
+ runtimes[i] = read_server_param("fair", "runtime", i);
+ if (runtimes[i] <= 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int write_fair_runtime_all(int nr_cpus, long value)
+{
+ int i;
+
+ for (i = 0; i < nr_cpus; i++) {
+ if (write_server_param("fair", "runtime", i, value) < 0) {
+ SCX_ERR("Failed to write fair_server runtime on CPU %d", i);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Restore per-CPU fair_server runtimes.
+ */
+static int restore_fair_runtime_all(int nr_cpus, const long *runtimes)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < nr_cpus; i++) {
+ if (write_server_param("fair", "runtime", i, runtimes[i]) < 0) {
+ SCX_ERR("Failed to restore fair_server runtime on CPU %d", i);
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
static bool verify_total_bw_consistency(long *bw_values, int count)
{
int i;
@@ -217,6 +309,9 @@ static enum scx_test_status run(void *ctx)
struct bpf_link *link;
long loaded_bw[MAX_CPUS];
long unloaded_bw[MAX_CPUS];
+ long doubled_bw[MAX_CPUS];
+ long original_runtime[MAX_CPUS], doubled_runtime;
+ enum scx_test_status ret;
int i;
/* Test scenario 2: BPF program loaded */
@@ -257,7 +352,111 @@ static enum scx_test_status run(void *ctx)
}
fprintf(stderr, "All total_bw values are consistent across all scenarios\n");
- return SCX_TEST_PASS;
+
+ /*
+ * Validate auto-register/unregister of dl_server bandwidth reservations.
+ *
+ * Doubling fair_server's runtime doubles its bw contribution. With a
+ * full-mode BPF scheduler (minimal_ops), the kernel should detach
+ * fair_server and attach ext_server, dropping total_bw back to its
+ * pre-customization (default ext_server-only) value. On unload, the
+ * fair_server reservation should come back with its customized runtime
+ * preserved, so total_bw doubles again.
+ */
+ if (read_fair_runtime_all(test_ctx->nr_cpus, original_runtime) < 0) {
+ fprintf(stderr, "Skipping attach/detach validation: debugfs not accessible\n");
+ return SCX_TEST_PASS;
+ }
+ doubled_runtime = original_runtime[0] * 2;
+
+ fprintf(stderr,
+ "Setting fair_server runtime to %ld ns on all CPUs (orig %ld)\n",
+ doubled_runtime, original_runtime[0]);
+
+ if (write_fair_runtime_all(test_ctx->nr_cpus, doubled_runtime) < 0) {
+ ret = SCX_TEST_FAIL;
+ goto restore;
+ }
+
+ if (fetch_verify_total_bw(doubled_bw, test_ctx->nr_cpus) < 0) {
+ SCX_ERR("Failed to get stable values after doubling fair runtime");
+ ret = SCX_TEST_FAIL;
+ goto restore;
+ }
+
+ /*
+ * After doubling the runtime, fair_server's bw contribution must grow.
+ * We don't assert exactly 2x, because the kernel's to_ratio() truncates
+ * the value, so 2 * to_ratio(period, runtime) and
+ * to_ratio(period, 2 * runtime) can differ.
+ */
+ for (i = 0; i < test_ctx->nr_cpus; i++) {
+ if (doubled_bw[i] <= test_ctx->baseline_bw[i]) {
+ SCX_ERR("CPU%d: fair did not increase total_bw (baseline=%ld, doubled=%ld)",
+ i, test_ctx->baseline_bw[i], doubled_bw[i]);
+ ret = SCX_TEST_FAIL;
+ goto restore;
+ }
+ }
+
+ link = bpf_map__attach_struct_ops(test_ctx->skel->maps.minimal_ops);
+ if (!link) {
+ SCX_ERR("Failed to attach scheduler for detach test");
+ ret = SCX_TEST_FAIL;
+ goto restore;
+ }
+
+ if (fetch_verify_total_bw(loaded_bw, test_ctx->nr_cpus) < 0) {
+ SCX_ERR("Failed to get stable values with BPF loaded (detach test)");
+ bpf_link__destroy(link);
+ ret = SCX_TEST_FAIL;
+ goto restore;
+ }
+
+ /*
+ * In full mode the customized fair_server is detached and ext_server is
+ * attached at its default runtime, total_bw must match baseline.
+ */
+ for (i = 0; i < test_ctx->nr_cpus; i++) {
+ if (loaded_bw[i] != test_ctx->baseline_bw[i]) {
+ SCX_ERR("CPU%d: expected bw %ld (fair detached, ext default), got %ld",
+ i, test_ctx->baseline_bw[i], loaded_bw[i]);
+ bpf_link__destroy(link);
+ ret = SCX_TEST_FAIL;
+ goto restore;
+ }
+ }
+
+ bpf_link__destroy(link);
+
+ if (fetch_verify_total_bw(unloaded_bw, test_ctx->nr_cpus) < 0) {
+ SCX_ERR("Failed to get stable values after BPF unload (detach test)");
+ ret = SCX_TEST_FAIL;
+ goto restore;
+ }
+
+ /*
+ * After unload, fair_server is re-attached with its preserved 2x
+ * runtime, so total_bw should return to the doubled value.
+ */
+ for (i = 0; i < test_ctx->nr_cpus; i++) {
+ if (unloaded_bw[i] != doubled_bw[i]) {
+ SCX_ERR("CPU%d: BPF unloaded: expected %ld (fair restored at 2x), got %ld",
+ i, doubled_bw[i], unloaded_bw[i]);
+ ret = SCX_TEST_FAIL;
+ goto restore;
+ }
+ }
+
+ fprintf(stderr,
+ "dl_server attach/detach with customized fair runtime verified\n");
+ ret = SCX_TEST_PASS;
+
+restore:
+ if (restore_fair_runtime_all(test_ctx->nr_cpus, original_runtime) < 0)
+ SCX_ERR("Failed to fully restore per-CPU fair_server runtimes");
+
+ return ret;
}
static void cleanup(void *ctx)