diff options
| author | Tejun Heo <tj@kernel.org> | 2026-05-22 07:06:01 -1000 |
|---|---|---|
| committer | Tejun Heo <tj@kernel.org> | 2026-05-25 09:44:07 -1000 |
| commit | abdc2516f100d8f9e637a49e4fdfd2d09a318680 (patch) | |
| tree | 65641f72ea7535bdabddb600bdea3b8fee8d7a79 /tools/sched_ext | |
| parent | 9eca087deb0b35f3170109a9630a6c5c06c2e222 (diff) | |
sched_ext: Convert ops.set_cmask() to arena-resident cmask
ops_cid.set_cmask() expects a cmask. The kernel couldn't write into the
arena, so it translated cpumask -> cmask in kernel memory and passed the
result as a trusted pointer. The BPF cmask helpers all operate on arena
cmasks though, so the BPF side had to word-by-word probe-read the kernel
cmask into an arena cmask via cmask_copy_from_kernel() before any helper
could touch it. It works, but is clumsy.
With direct kernel-side arena access now in place, build the cmask in the
arena. The kernel writes to it through the kern_va side of the dual mapping.
BPF directly dereferences it via an __arena pointer like any other arena
struct.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Diffstat (limited to 'tools/sched_ext')
| -rw-r--r-- | tools/sched_ext/include/scx/cid.bpf.h | 52 | ||||
| -rw-r--r-- | tools/sched_ext/scx_qmap.bpf.c | 5 |
2 files changed, 3 insertions, 54 deletions
diff --git a/tools/sched_ext/include/scx/cid.bpf.h b/tools/sched_ext/include/scx/cid.bpf.h index e281c88fa824..70f2a3829af4 100644 --- a/tools/sched_ext/include/scx/cid.bpf.h +++ b/tools/sched_ext/include/scx/cid.bpf.h @@ -675,56 +675,4 @@ static __always_inline void cmask_from_cpumask(struct scx_cmask __arena *m, } } -/** - * cmask_copy_from_kernel - probe-read a kernel cmask into an arena cmask - * @dst: arena cmask to fill; must have @dst->base == 0 and be sized for @src. - * @src: kernel-memory cmask (e.g. ops.set_cmask() arg); @src->base must be 0. - * - * Word-for-word copy; @src and @dst must share base 0 alignment. Triggers - * scx_bpf_error() on probe failure or precondition violation. - */ -static __always_inline void cmask_copy_from_kernel(struct scx_cmask __arena *dst, - const struct scx_cmask *src) -{ - u32 base = 0, nr_cids = 0, nr_words, wi; - - if (dst->base != 0) { - scx_bpf_error("cmask_copy_from_kernel requires dst->base == 0"); - return; - } - - if (bpf_probe_read_kernel(&base, sizeof(base), &src->base)) { - scx_bpf_error("probe-read cmask->base failed"); - return; - } - if (base != 0) { - scx_bpf_error("cmask_copy_from_kernel requires src->base == 0"); - return; - } - - if (bpf_probe_read_kernel(&nr_cids, sizeof(nr_cids), &src->nr_cids)) { - scx_bpf_error("probe-read cmask->nr_cids failed"); - return; - } - - if (nr_cids > dst->nr_cids) { - scx_bpf_error("src cmask nr_cids=%u exceeds dst nr_cids=%u", - nr_cids, dst->nr_cids); - return; - } - - nr_words = CMASK_NR_WORDS(nr_cids); - cmask_zero(dst); - bpf_for(wi, 0, CMASK_MAX_WORDS) { - u64 word = 0; - if (wi >= nr_words) - break; - if (bpf_probe_read_kernel(&word, sizeof(u64), &src->bits[wi])) { - scx_bpf_error("probe-read cmask->bits[%u] failed", wi); - return; - } - dst->bits[wi] = word; - } -} - #endif /* __SCX_CID_BPF_H */ diff --git a/tools/sched_ext/scx_qmap.bpf.c b/tools/sched_ext/scx_qmap.bpf.c index 7e77f22674ea..8a2d6a8ebd8e 100644 --- a/tools/sched_ext/scx_qmap.bpf.c +++ b/tools/sched_ext/scx_qmap.bpf.c @@ -919,14 +919,15 @@ void BPF_STRUCT_OPS(qmap_update_idle, s32 cid, bool idle) } void BPF_STRUCT_OPS(qmap_set_cmask, struct task_struct *p, - const struct scx_cmask *cmask) + const struct scx_cmask *cmask_in) { + struct scx_cmask __arena *cmask = (struct scx_cmask __arena *)(long)cmask_in; task_ctx_t *taskc; taskc = lookup_task_ctx(p); if (!taskc) return; - cmask_copy_from_kernel(&taskc->cpus_allowed, cmask); + cmask_copy(&taskc->cpus_allowed, cmask); } struct monitor_timer { |
