diff options
| author | Tejun Heo <tj@kernel.org> | 2026-07-13 22:18:42 -1000 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2026-07-13 22:18:42 -1000 |
| commit | 30067643bce0d02cbeb512416372e93272e674f3 (patch) | |
| tree | 4077fced63ac2b0872b7197d832bd4b1ebf9631b /tools/sched_ext | |
| parent | e2c841b91bf960f5dd57aa9dd49b14a1d30f1a56 (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.h | 11 | ||||
| -rw-r--r-- | tools/sched_ext/scx_qmap.bpf.c | 16 | ||||
| -rw-r--r-- | tools/sched_ext/scx_qmap.c | 34 | ||||
| -rw-r--r-- | tools/sched_ext/scx_qmap.h | 1 |
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 { |
