diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c index 81c2d8eeae41..fd88b4d4f12a 100644 --- a/kernel/sched/ext/ext.c +++ b/kernel/sched/ext/ext.c @@ -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; diff --git a/kernel/sched/ext/internal.h b/kernel/sched/ext/internal.h index a9a853a71061..1bdf34f3fc3c 100644 --- a/kernel/sched/ext/internal.h +++ b/kernel/sched/ext/internal.h @@ -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;