summaryrefslogtreecommitdiff
path: root/tools/sched_ext
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-07-13 22:18:42 -1000
committerTejun Heo <tj@kernel.org>2026-07-13 22:18:42 -1000
commit30067643bce0d02cbeb512416372e93272e674f3 (patch)
tree4077fced63ac2b0872b7197d832bd4b1ebf9631b /tools/sched_ext
parente2c841b91bf960f5dd57aa9dd49b14a1d30f1a56 (diff)
sched_ext: Add shard boundaries to scx_bpf_cid_override()
An overridden cid mapping invalidates the auto-generated shard layout, so the override call has to provide both. Extend scx_bpf_cid_override() with a shard_start[] array that lists the first cid of each shard (starting at 0, strictly increasing, last shard implicitly extends to num_possible_cpus()). A scheduler that wants only custom shards with the auto-generated cid mapping can read the current mapping and pass it back unchanged. Overridden shards can span NUMA nodes, so scx_shard_node[] is rebuilt by majority count: each shard is assigned to the node that owns the most cpus in it. v2: Snapshot the caller's cpu_to_cid/shard_start arrays before validating. (sashiko AI) Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
Diffstat (limited to 'tools/sched_ext')
-rw-r--r--tools/sched_ext/include/scx/compat.bpf.h11
-rw-r--r--tools/sched_ext/scx_qmap.bpf.c16
-rw-r--r--tools/sched_ext/scx_qmap.c34
-rw-r--r--tools/sched_ext/scx_qmap.h1
4 files changed, 50 insertions, 12 deletions
diff --git a/tools/sched_ext/include/scx/compat.bpf.h b/tools/sched_ext/include/scx/compat.bpf.h
index 133058578668..cf469d5ff9ca 100644
--- a/tools/sched_ext/include/scx/compat.bpf.h
+++ b/tools/sched_ext/include/scx/compat.bpf.h
@@ -122,15 +122,18 @@ static inline bool scx_bpf_sub_dispatch(u64 cgroup_id)
}
/*
- * v7.2: scx_bpf_cid_override() for explicit cpu->cid mapping. Ignore if
+ * v7.3: scx_bpf_cid_override() for explicit cid and shard mapping. Ignore if
* missing.
*/
-void scx_bpf_cid_override___compat(const s32 *cpu_to_cid, u32 cpu_to_cid__sz) __ksym __weak;
+void scx_bpf_cid_override___compat(const s32 *cpu_to_cid, u32 cpu_to_cid__sz,
+ const s32 *shard_start, u32 shard_start__sz) __ksym __weak;
-static inline void scx_bpf_cid_override(const s32 *cpu_to_cid, u32 cpu_to_cid__sz)
+static inline void scx_bpf_cid_override(const s32 *cpu_to_cid, u32 cpu_to_cid__sz,
+ const s32 *shard_start, u32 shard_start__sz)
{
if (bpf_ksym_exists(scx_bpf_cid_override___compat))
- return scx_bpf_cid_override___compat(cpu_to_cid, cpu_to_cid__sz);
+ scx_bpf_cid_override___compat(cpu_to_cid, cpu_to_cid__sz,
+ shard_start, shard_start__sz);
}
/**
diff --git a/tools/sched_ext/scx_qmap.bpf.c b/tools/sched_ext/scx_qmap.bpf.c
index 2df7c53992dc..f6cfe63425d3 100644
--- a/tools/sched_ext/scx_qmap.bpf.c
+++ b/tools/sched_ext/scx_qmap.bpf.c
@@ -54,18 +54,20 @@ const volatile u32 max_tasks;
/*
* Optional cid-override test harness. When cid_override_mode is non-zero,
- * qmap_init_cids() calls scx_bpf_cid_override() with the caller-supplied
- * cpu_to_cid array to exercise the kfunc's acceptance and error paths. See enum
+ * qmap_init_cids() calls scx_bpf_cid_override() with the caller-supplied arrays
+ * to exercise the kfunc's acceptance and error paths. See enum
* qmap_cid_override for the modes.
*/
const volatile u32 cid_override_mode;
+const volatile u32 cid_override_nr_shards;
/*
- * Array lives in bss (writable) because scx_bpf_cid_override()'s BPF
- * verifier signature treats its len-paired pointer as read/write - rodata
+ * Arrays live in bss (writable) because scx_bpf_cid_override()'s BPF
+ * verifier signature treats its len-paired pointers as read/write - rodata
* fails verification with "write into map forbidden". Userspace populates
- * it before SCX_OPS_LOAD, same as rodata, and nothing writes it after.
+ * them before SCX_OPS_LOAD, same as rodata, and nothing writes them after.
*/
s32 cid_override_cpu_to_cid[SCX_QMAP_MAX_CPUS];
+s32 cid_override_shard_start[SCX_QMAP_MAX_CPUS];
UEI_DEFINE(uei);
@@ -1082,7 +1084,9 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(qmap_init_cids)
}
scx_bpf_cid_override((const s32 *)cid_override_cpu_to_cid,
- nr_cpu_ids * sizeof(s32));
+ nr_cpu_ids * sizeof(s32),
+ (const s32 *)cid_override_shard_start,
+ cid_override_nr_shards * sizeof(s32));
return 0;
}
diff --git a/tools/sched_ext/scx_qmap.c b/tools/sched_ext/scx_qmap.c
index c0b5cab579d6..9124183bffec 100644
--- a/tools/sched_ext/scx_qmap.c
+++ b/tools/sched_ext/scx_qmap.c
@@ -43,7 +43,7 @@ const char help_fmt[] =
" -p Switch only tasks on SCHED_EXT policy instead of all\n"
" -I Turn on SCX_OPS_ALWAYS_ENQ_IMMED\n"
" -F COUNT IMMED stress: force every COUNT'th enqueue to a busy local DSQ (use with -I)\n"
-" -C MODE cid-override test (shuffle|bad-dup|bad-range)\n"
+" -C MODE cid-override test (shuffle|bad-dup|bad-range|bad-mono)\n"
" -v Print libbpf debug messages\n"
" -h Display this help and exit\n";
@@ -155,6 +155,7 @@ restart:
case 'C': {
u32 nr_cpus = libbpf_num_possible_cpus();
u32 mode, i;
+ s32 shard_sz = 4;
if (!strcmp(optarg, "shuffle"))
mode = QMAP_CID_OVR_SHUFFLE;
@@ -162,13 +163,15 @@ restart:
mode = QMAP_CID_OVR_BAD_DUP;
else if (!strcmp(optarg, "bad-range"))
mode = QMAP_CID_OVR_BAD_RANGE;
+ else if (!strcmp(optarg, "bad-mono"))
+ mode = QMAP_CID_OVR_BAD_MONO;
else {
fprintf(stderr, "unknown cid-override mode '%s'\n", optarg);
return 1;
}
skel->rodata->cid_override_mode = mode;
- /* shuffle: reversed cpu_to_cid, bad-dup: dup cid 0, bad-range: identity */
+ /* shuffle: reversed cpu_to_cid; others: identity */
for (i = 0; i < nr_cpus; i++) {
if (mode == QMAP_CID_OVR_SHUFFLE)
skel->bss->cid_override_cpu_to_cid[i] = nr_cpus - 1 - i;
@@ -179,6 +182,33 @@ restart:
skel->bss->cid_override_cpu_to_cid[1] = 0;
if (mode == QMAP_CID_OVR_BAD_RANGE)
skel->bss->cid_override_cpu_to_cid[0] = (s32)nr_cpus;
+
+ /*
+ * bad-mono needs >= 3 shards to build a 0-based but
+ * non-monotonic shard_start. Shrink the shard size so
+ * the test runs on any machine with >= 3 cpus.
+ */
+ if (mode == QMAP_CID_OVR_BAD_MONO) {
+ if (nr_cpus < 3) {
+ fprintf(stderr, "bad-mono needs >= 3 cpus (have %u)\n",
+ nr_cpus);
+ return 1;
+ }
+ shard_sz = nr_cpus / 3;
+ }
+
+ /* shards of shard_sz each */
+ skel->rodata->cid_override_nr_shards = (nr_cpus + shard_sz - 1) / shard_sz;
+ for (i = 0; i < skel->rodata->cid_override_nr_shards; i++)
+ skel->bss->cid_override_shard_start[i] = i * shard_sz;
+
+ if (mode == QMAP_CID_OVR_BAD_MONO) {
+ /* swap [1] and [2] to break monotonicity */
+ s32 tmp = skel->bss->cid_override_shard_start[1];
+ skel->bss->cid_override_shard_start[1] =
+ skel->bss->cid_override_shard_start[2];
+ skel->bss->cid_override_shard_start[2] = tmp;
+ }
break;
}
case 'v':
diff --git a/tools/sched_ext/scx_qmap.h b/tools/sched_ext/scx_qmap.h
index 3bcc3579839d..6c3ea1fc74ed 100644
--- a/tools/sched_ext/scx_qmap.h
+++ b/tools/sched_ext/scx_qmap.h
@@ -33,6 +33,7 @@ enum qmap_cid_override {
QMAP_CID_OVR_SHUFFLE = 1, /* valid reversed cpu->cid mapping */
QMAP_CID_OVR_BAD_DUP = 2, /* invalid: duplicate cid assignment */
QMAP_CID_OVR_BAD_RANGE = 3, /* invalid: out-of-range cid */
+ QMAP_CID_OVR_BAD_MONO = 4, /* invalid: non-monotonic shard_start */
};
struct cpu_ctx {