summaryrefslogtreecommitdiff
path: root/kernel/sched/ext/cid.c
AgeCommit message (Collapse)Author
3 daysMerge tag 'sched_ext-for-7.4-fixes' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext Pull sched_ext fixes from Tejun Heo: "This is a big pull for fixes, but much of it was in the works before the merge window. Most of these fixes are in sub-scheduler support, which nests BPF schedulers under a parent that hands them CPUs. It was heavily reworked over recent cycles and is now functionally complete. Porting real schedulers on it drove the latest additions and keeps finding corner cases. For example, once CPUs are shared and can be taken back, the kernel must keep every task moving when its scheduler can't run it or is failing, and those fallbacks interact subtly with each other and with other new core features. - The fallback paths meant to keep a task moving when its scheduler can't run it or is failing could themselves leave it stuck - The stall watchdog could blame a scheduler for time it wasn't responsible for, even taking down all of sched_ext - Sub-schedulers were told late, or not at all, which CPUs they could use - Deferred callbacks could stay queued or be dropped under core scheduling and proxy execution, with a sched/core fix to the duplicate check - Hardening: tracing programs can no longer call kfuncs that could deadlock the CPU" * tag 'sched_ext-for-7.4-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext: (34 commits) sched_ext: Reject scx_bpf_sub_grant/revoke() in tracing programs sched_ext: Fix the rescue overload pick ejecting the wrong sub under bypass sched_ext: Fix use-after-free of a NONE rescuee leaving its sched while running sched_ext: Fix a lone IMMED task waiting behind a kept prev sched_ext: Fix queued bypassed tasks stalling when the host loses SCX_CAP_BASE sched_ext: Let the bypass load balancer move tasks homed on other cpus sched_ext: Factor out bypass_lb_move() and insert with the donor DSQ unlocked sched_ext: Fix the bypass load balancer stranding tasks on cpus where the host lacks SCX_CAP_BASE sched_ext: Fix bypassed tasks stalling when the host lacks SCX_CAP_BASE sched_ext: Expire prev's slice in dispatch_one() under bypass sched_ext: Fix a cpu idling after put_prev_task_scx() queues its task on the local DSQ sched_ext: Refuse extending a kernel slice sched_ext: Mark the rescue grant as a kernel slice with SCX_TASK_KERNEL_SLICE sched_ext: Fix a cpu idling with a runnable rescuee sched_ext: Restore a rescuee's slice after ops.stopping() sched_ext: Fix rescue served time disagreeing with the slice under proxy execution sched_ext: Move refill_task_slice_dfl() below apply_slice_vtime() sched_ext: Fix bypassed tasks looping on a host without SCX_CAP_ENQ sched_ext: Fix bypassed tasks stranded by the reenqueue limit sched_ext: Clear holding_cpu where the claim is confirmed ...
10 daysMerge tag 'sched_ext-for-7.4' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext Pull sched_ext updates from Tejun Heo: - Proxy execution can now be enabled together with sched_ext. A BPF scheduler can opt in to receive mutex-blocked tasks that donate their scheduling context to the lock owner and place them itself. - Lazy preemption: a BPF scheduler can preempt or kick a CPU lazily, deferring the switch to the next return to user space or tick, as the fair class can. - Sub-schedulers: a parent now learns which child runs on each CPU it delegated and when a cap change takes effect. A detaching child loses its caps before the parent restores the CPUs. - New kfuncs re-enqueue single tasks from a dispatch queue iteration and report a cgroup's CPU count and a CID's NUMA node. The CID topology now includes clusters. - Hot path optimizations: dispatch queue and task lookups compare keys inline, remote task moves no longer take a dispatch queue lock twice, and sub-scheduler hooks cost nothing without sub-schedulers. - Kfuncs callable from tracing programs are hardened against NMI and IRQ nesting, which could hard-lock the CPU or pick a wrong idle CPU. - Built-in dispatch queues no longer allocate per-CPU state that grew with the square of the CPU count. - Header syncs with the scx repo, a BTF workaround for pahole 1.32, and selftest fixes and coverage. * tag 'sched_ext-for-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext: (69 commits) sched_ext: Drop the locks periodically while walking a user DSQ for re-enqueue sched_ext: scx_qmap: Also re-enqueue stranded tasks with scx_bpf_dsq_reenq_task() sched_ext: Add scx_bpf_dsq_reenq_task() to re-enqueue single tasks from a DSQ iteration sched_ext: Factor out the rq lock switch of scx_dsq_move() sched_ext: Don't queue balance callbacks from a core-sched pick sched_ext: Don't leave balance callbacks queued across a pick retry sched_ext: Fix a bypassed task stalling on a cpu its scheduler has no caps on sched_ext: Fix the running task keeping its protection into bypass sched_ext: Fix use-after-free of a local reenq node left on an inactive cpu sched_ext: Keep proxy donors with slice left on the local DSQ selftests/sched_ext: Report reload_loop attach failures selftests/sched_ext: Bound exit waits selftests/sched_ext: Add SCX_ASSERT_ALIVE and adopt it selftests/sched_ext: Fail loudly when EXIT_KIND is missing from BTF sched_ext: Add SCX_ECODE_RSN_CGROUP_OFFLINE to user_exit_info.h selftests/sched_ext: Fix reload_loop error-path use-after-free selftests/sched_ext: Fix build error in dequeue_remote selftest sched_ext: scx_qmap: Reset a child's cpuperf targets once its PERF revoke takes effect sched_ext: Add ops.sub_child_ecaps_updated() to report a child's effective cap changes sched_ext: scx_qmap: Show actual cid use per participant ...
11 dayssched_ext: Reject oversized automatic CID shardsHui Su
Automatic topology packing starts a new shard before adding a core when the current shard would exceed its target size. However, a first core is always accepted so that cores remain indivisible. An indivisible core with more than SCX_CID_SHARD_MAX_CPUS CPUs cannot be represented without exceeding the hard shard limit. Per-shard state uses fixed-size inline cmask storage sized for SCX_CID_SHARD_MAX_CPUS. Passing an oversized shard to alloc_pshard() can therefore make cmask initialization overwrite the following fields. Reject an indivisible core larger than SCX_CID_SHARD_MAX_CPUS before adding it to a shard. Existing non-empty shard splitting already keeps the total within the hard cap, while an indivisible core may still exceed cid_shard_size when it fits within the hard limit. Report the oversized core and the hard limit with scx_error() so that the rejection is diagnosable. tj: The bug is only reproducible with artificial VM topologies. It can't happen on real hardware. Fixes: e2c841b91bf9 ("sched_ext: Add CID sharding") Reviewed-by: Andrea Righi <arighi@nvidia.com> Tested-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Hui Su <sh_def@163.com> Signed-off-by: Tejun Heo <tj@kernel.org>
2026-09-28sched_ext: cid: Represent clusters explicitlyAndrea Righi
The sched_ext CID topology gives each core, LLC and NUMA node a contiguous CID range. Without cluster entries, schedulers cannot obtain their CID range or global index. Walk cores by cache-sharing cluster and add cluster_cid and cluster_idx to scx_cid_topo. Treat the level inclusively: a core without a wider cluster forms one of its own, while an LLC-wide cache-sharing group forms one cluster. This gives every cluster a contiguous CID range and a dense index. The walk now takes cores in cluster order rather than LLC order. Shards are still cut on core boundaries, so a shard doesn't need to contain a whole cluster; only core, cluster, LLC and node are nested, in that order. The level follows whatever the arch reports through topology_cluster_cpumask(), which on x86 is the L2 sharing mask and is populated independently of CONFIG_SCHED_CLUSTER. Tested on a 13th Gen Intel Core i7-13800H: six SMT P-cores occupy CPUs 0-11, eight E-cores occupy CPUs 12-19 in two four-core L2 modules, and all 20 CPUs share one LLC; the P-core pairs form two-CID clusters, the E-core modules form four-CID clusters, and cluster_idx is dense across all eight clusters. Signed-off-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org>
2026-09-27Merge tag 'sched_ext-for-7.3-rc4-fixes-2' of ↵Linus Torvalds
git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext Pull sched_ext fix from Tejun Heo: - The CPU topology helper for BPF schedulers took no buffer size, so its structure couldn't grow without breaking schedulers built against the older layout. Add a size argument. * tag 'sched_ext-for-7.3-rc4-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext: sched_ext: Add a size argument to scx_bpf_cid_topo() so struct scx_cid_topo can grow
2026-09-26sched_ext: Merge branch 'for-7.3-fixes' into for-7.4Tejun Heo
Pull to receive 94480606a677 ("sched_ext: Add a size argument to scx_bpf_cid_topo() so struct scx_cid_topo can grow") for the upcoming cluster level. Conflicts: kept both declarations where 5cadf7545cc6 ("sched_ext: Add a CID NUMA node lookup kfunc") added one next to the changed scx_bpf_cid_topo() line, and pointed 29871903f3a3 ("sched_ext: Don't deliver duplicate ops.cgroup_set_idle() for same value") at the renamed tg->scx.sched_idle. Signed-off-by: Tejun Heo <tj@kernel.org>
2026-09-26sched_ext: Add a size argument to scx_bpf_cid_topo() so struct scx_cid_topo ↵Tejun Heo
can grow scx_bpf_cid_topo() copies struct scx_cid_topo into a buffer the BPF program sized from its own vmlinux.h while the verifier sizes the write from the running kernel's BTF. The struct may grow and each growth then breaks every scheduler built against the older layout, rejected at load or written past its buffer. This is the usual hole for a struct handed to BPF, closed elsewhere with a size argument, and it was missed here. Take the buffer size, copy the smaller of it and the kernel's struct and set the rest to -1. Accesses to the copy are CO-RE relocated, so the struct can grow by appending fields, which its comment now states. The kfunc changes in place: the cid interface is still being finalized and no released scheduler uses the current form. Fixes: e9b55af47edf ("sched_ext: Add topological CPU IDs (cids)") Cc: stable@vger.kernel.org # v7.2+ Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-09-26sched_ext: Add a CID NUMA node lookup kfuncAndrea Righi
CID-form schedulers may need the physical NUMA node for a CID, for example to allocate arena memory on that node. The CID topology's node index is not a physical NUMA node ID, and scx_bpf_cpu_node() is restricted to CPU-form schedulers. Add scx_bpf_cid_node() to return the physical NUMA node for a CID and provide a compatibility helper that returns NUMA_NO_NODE on kernels without this kfunc. Signed-off-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org>
2026-09-04treewide: refresh kmalloc_obj() conversionsKees Cook
This is another run of the Coccinelle script for converting kmalloc() family of allocations to kmalloc_obj() via the existing rules in scripts/coccinelle/api/kmalloc_objs.cocci This catches both the set of kmalloc() uses added since the first kmalloc_obj() conversions in v7.0 and adds a large group missed in the first pass due to Coccinelle not interacting well with the cleanup.h scoped_...() family of macros[1]. I worked around this with spatch's "--macro-file" argument to a file with all the scoped_...() macros mapped to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control flow indicator I could find. Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc, riscv, and s390 with no new warnings. Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1] Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2] Signed-off-by: Kees Cook <kees+treewide@kernel.org>
2026-08-12sched_ext: Convert scx_bpf_cid_override() to __arena array argumentsTejun Heo
scx_bpf_cid_override() predates the cid-form arena transition and takes its arrays as verifier-checked mem+size buffers, forcing scx_qmap to keep the cpu_to_cid and shard_start arrays in writable bss while the rest of its state lives in the arena. Unify on arena arguments before cid-form schedulers start seeing real use. BPF now translates between BPF and kernel arena addresses for __arena arguments. Take the arrays as __arena arguments, with the counts passed in entries. The counts now size the snapshot copies and are bounds-checked before them. scx_qmap moves the arrays into struct qmap_arena. As the arena is mmapped at load, the loader populates them between load and attach instead of before load. The arena argument address translation is currently implemented only on x86-64. Schedulers calling this kfunc load only there for now. Signed-off-by: Tejun Heo <tj@kernel.org>
2026-08-12sched_ext: Convert sub-cap kfuncs to __arena cmask argumentsTejun Heo
The sub-cap kfuncs take their cmask arguments as __ign pointers. The values cross the kfunc boundary as unchecked scalars and scx_cmask_ref_init() rebases them into the arena by hand. BPF now translates between BPF and kernel arena addresses for __arena arguments. Tag the cmask arguments __arena so the kfuncs receive kernel addresses and scx_cmask_ref_init() loses the hand-rolled conversion. The optional denied_out keeps its NULL not-provided signal via __arena__nullable. The mandatory masks use plain __arena. scx_qmap's call sites drop the (void *)(long) casts since the BPF-side declarations type the cmask arguments __arena and take arena pointers directly. The arena argument address translation is currently implemented only on x86-64. Schedulers calling these kfuncs load only there for now. Signed-off-by: Tejun Heo <tj@kernel.org>
2026-07-21sched_ext: Build the cid tables privately and publish them with RCUTejun Heo
The cid tables are visible to the cid kfuncs while being modified: the first enable publishes the global pointers before filling them, ops.init_cids() overrides rewrite them in place, and re-enables rebuild them in place. A racing TRACING or SYSCALL program can read unfilled entries, including uninitialized memory in the kmalloc'd tables, or torn topo updates. Tie the tables' lifetimes to the root sched instead: each root enable builds a fresh set privately and publishes the per-table __rcu globals once the layout is final, and root disable unpublishes and RCU-frees the set. A non-NULL global is now always a fully built table which stays valid for the reader's RCU read section, and lookups stay two loads. Kfuncs treat NULL as no-mapping, also after the scheduler exits instead of reporting the stale last mapping. The cid kfuncs are available whether the root scheduler is cid-form or cpu-form, the latter to allow gradual migration to cids. Every root therefore builds and publishes a default mapping. Every reader must either be gated on scheduler liveness or NULL-check inside an RCU read section. Fix the two kfuncs that were neither: scx_bpf_this_cid() read the table with no RCU or preemption protection and scx_bpf_task_cid() relied on KF_RCU, which doesn't put a sleepable program in an RCU read section. The hotplug callbacks are instead serialized by retiring the tables inside the cpus_read_lock() section that clears scx_root. v2: Document why every root builds the tables (desc + cid.c comment). Reported-by: Andrea Righi <arighi@nvidia.com> Closes: https://lore.kernel.org/r/al3tLtPZZkFjMveK@gpd4 Reviewed-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org>
2026-07-21sched_ext: Drop unused scx_cpumask_to_cmask()Tejun Heo
scx_cpumask_to_cmask() has no callers. Reviewed-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org>
2026-07-13sched_ext: Build the set_cmask scratch from trusted geometryTejun Heo
scx_call_op_set_cpumask() builds a per-cpu cmask in the set_cmask scratch, which lives in BPF-writable arena. A scheduler can corrupt the scratch's inline header (base, nr_cids, alloc_words) from another cpu, so sizing and indexing the write from it risks an out-of-bounds write. Drive the build from kernel-known geometry instead. scx_cmask_ref_init_kern() imposes base and nr_cids rather than reading them, and scx_cmask_ref_from_cpumask() fills the scratch from the ref. Neither reads the header back. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-07-13sched_ext: Add scx_cmask_ref for validated arena cmask accessTejun Heo
kfuncs taking struct scx_cmask * from BPF arena memory have two problems. The pointer can be any value the BPF prog hands in, and the header (@base, @nr_cids, @alloc_words) can be mutated by the prog concurrently with kernel access. Add scx_cmask_ref, a validated handle. _init() normalizes the input pointer into the arena's kern_vm range via scx_arena_to_kaddr() and snapshots the header, rejecting a range outside the machine or a nr_cids whose words exceed the declared @alloc_words. Downstream sizing uses the snapshot, not the live header. _shard() reads slices while _or() and _copy() write back, all bounded by the snapshot. No callers yet. struct scx_cmask's bits[] carried __counted_by(alloc_words), so UBSAN_BOUNDS and FORTIFY_SOURCE bound accesses to the array. That bound is read from @alloc_words at the access. For an arena cmask @alloc_words is BPF-writable. A prog that sets it larger than the real allocation makes the check pass on a genuine overrun, so the annotation catches nothing, and it only runs under those debug configs. Drop it - _init() validates @alloc_words explicitly, and kernel-owned cmasks set it themselves. v2: Validate @alloc_words in _init(), drop __counted_by. (Andrea, sashiko AI) Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-07-13sched_ext: Add shard boundaries to scx_bpf_cid_override()Tejun Heo
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>
2026-07-13sched_ext: Add CID shardingTejun Heo
Sub-sched operations need a scalable locking / work domain smaller than the whole cid space. Carve the cid space into topology-respecting shards: each shard is a contiguous cid range that stays within one LLC, and LLCs larger than the per-shard cap (default 24 cids, configurable via ops.cid_shard_size) split into enough shards to fit. A hard cap of SCX_CID_SHARD_MAX_CPUS prevents pathological sizes under custom configurations. No-topo cids pack into their own shards so every cid has a shard assignment. Also build scx_cid_shard_ranges[] for O(1) shard-to-cid-range lookup and scx_shard_node[] so callers can size or place work by NUMA without walking cids. Auto-built shards inherit their LLC's node. No-topo shards carry NUMA_NO_NODE. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-07-13sched_ext: Add ops.init_cids() to finalize the cid layout before initTejun Heo
A cid-form scheduler that calls scx_bpf_cid_override() to install a custom cid layout can only do so from ops.init(). Enable-path setup that depends on the cid layout thus has to run after ops.init(), and ops.init() itself can't use anything derived from the final layout, which turned out to be too restrictive. Add an ops.init_cids() callback dedicated to finalizing the cid layout. It runs before the rest of the enable-path setup, so the final layout is in effect for everything that follows including ops.init(), which now runs after the arena pool and cmask scratch allocations. scx_bpf_cid_override() is restricted to ops.init_cids() at load time. It sits in a kfunc set gated by SCX_KF_ALLOW_INIT_CIDS, a flag set only on the init_cids op, so the verifier rejects a call from any other context. The runtime root-only check is dropped as ops.init_cids() only runs during root enable. The qmap demo moves its override into a dedicated qmap_init_cids() and, while at it, introduces an enum for the cid override modes instead of hard-coded integers. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-07-09sched_ext: Use READ_ONCE/WRITE_ONCE in cmask word ops and drop _RACY variantsTejun Heo
The cmask ops can operate on BPF-arena cmasks which BPF programs may read and write concurrently. The _RACY op variants existed to make such lockless reads explicit but this turned out to be too restrictive. Mark the word accesses in all the two-cmask ops with READ_ONCE/WRITE_ONCE instead and drop the _RACY variants. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-06-22sched_ext: Make kernel/sched/ext/ sources self-contained for clangdTejun Heo
The sources under kernel/sched/ext/ build as a single translation unit: build_policy.c includes the source files and headers. An LSP/clangd editor parses each as a standalone unit, sees no types, and reports a flood of errors. Give each header its dependencies and include guard, and have each source include the headers it uses. ext.c, arena.c and the ext headers now parse clean standalone. idle.c and cid.c still reference a few macros and helpers defined in ext.c. The next patch moves those to shared headers. Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
2026-06-22sched_ext: Move sources under kernel/sched/ext/Tejun Heo
The sched_ext sources had grown to ten ext* files directly under kernel/sched/. Move them into a new kernel/sched/ext/ subdirectory and drop the now-redundant ext_ prefix. ext.c/h keep their names. kernel/sched/ext.{c,h} -> kernel/sched/ext/ext.{c,h} kernel/sched/ext_internal.h -> kernel/sched/ext/internal.h kernel/sched/ext_types.h -> kernel/sched/ext/types.h kernel/sched/ext_idle.{c,h} -> kernel/sched/ext/idle.{c,h} kernel/sched/ext_cid.{c,h} -> kernel/sched/ext/cid.{c,h} kernel/sched/ext_arena.{c,h} -> kernel/sched/ext/arena.{c,h} The include paths in build_policy.c and sched.h, the MAINTAINERS glob, and a few documentation and comment references are updated to match. No code or symbol changes. Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Reviewed-by: Andrea Righi <arighi@nvidia.com> Signed-off-by: Tejun Heo <tj@kernel.org>