sched_ext: Gate local DSQ reenq on baseline cid access

scx_bpf_dsq_reenq() with an SCX_DSQ_LOCAL_ON target schedules deferred reenq
work on the cid's cpu, raising an IPI when the target rq isn't the locked
one. Nothing checks caps along the way, so a sub-sched holding no cap at all
on a cid can force its cpu to take IPIs and rq lock cycles at will. The
analogous scx_bpf_kick_cid() path gates delivery on SCX_CAP_BASE in
kick_one_cpu() to prevent exactly this.

Apply the same rule at the reenq scheduling point: if the calling sched
lacks SCX_CAP_BASE on the target cid, drop the reenq and count it in the new
SCX_EV_SUB_REENQ_DENIED event. The check is lockless, which is fine: a reenq
slipping through right after a revoke is harmless, and a wrong denial can't
happen - if the caller has seen its ownership of the cpu, the check sees it
too.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Andrea Righi <arighi@nvidia.com>
This commit is contained in:
Tejun Heo 2026-07-24 09:09:28 -10:00
parent 457daba18e
commit f879519db8
2 changed files with 20 additions and 1 deletions

View File

@ -1071,6 +1071,18 @@ void schedule_dsq_reenq(struct scx_sched *sch, struct scx_dispatch_q *dsq,
if (dsq->id == SCX_DSQ_LOCAL) {
rq = container_of(dsq, struct rq, scx.local_dsq);
/*
* A sub-sched lacking baseline access on the target cid has no
* business triggering IPIs. The lockless test is fine: slipping
* through right after a revoke is harmless and a wrong denial
* can't happen - if the caller has seen its ownership, so does
* this test.
*/
if (unlikely(scx_missing_caps(sch, cpu_of(rq), SCX_CAP_BASE))) {
__scx_add_event(sch, SCX_EV_SUB_REENQ_DENIED, 1);
return;
}
struct scx_sched_pcpu *sch_pcpu = per_cpu_ptr(sch->pcpu, cpu_of(rq));
struct scx_deferred_reenq_local *drl = &sch_pcpu->deferred_reenq_local;

View File

@ -1193,6 +1193,12 @@ struct scx_event_stats {
* kick degrades to a plain reschedule.
*/
s64 SCX_EV_SUB_PREEMPT_DENIED;
/*
* The number of times a local DSQ reenq was dropped because the
* sub-sched lacked baseline access on the target cid.
*/
s64 SCX_EV_SUB_REENQ_DENIED;
};
#define SCX_EVENTS_LIST(SCX_EVENT) \
@ -1212,7 +1218,8 @@ struct scx_event_stats {
SCX_EVENT(SCX_EV_INSERT_NOT_OWNED); \
SCX_EVENT(SCX_EV_SUB_BYPASS_DISPATCH); \
SCX_EVENT(SCX_EV_SUB_FORCED_ADMIT); \
SCX_EVENT(SCX_EV_SUB_PREEMPT_DENIED)
SCX_EVENT(SCX_EV_SUB_PREEMPT_DENIED); \
SCX_EVENT(SCX_EV_SUB_REENQ_DENIED)
struct scx_sched;