xref: /linux/tools/sched_ext/scx_qmap.h (revision 11260c335ec6071af5543aef73000b28f041c124)
160a59eacSTejun Heo /* SPDX-License-Identifier: GPL-2.0 */
260a59eacSTejun Heo /*
360a59eacSTejun Heo  * Shared definitions between scx_qmap.bpf.c and scx_qmap.c.
460a59eacSTejun Heo  *
560a59eacSTejun Heo  * The scheduler keeps all state in a single BPF arena map. struct
660a59eacSTejun Heo  * qmap_arena is the one object that lives at the base of the arena and is
760a59eacSTejun Heo  * mmap'd into userspace so the loader can read counters directly.
860a59eacSTejun Heo  *
960a59eacSTejun Heo  * Copyright (c) 2026 Meta Platforms, Inc. and affiliates.
1060a59eacSTejun Heo  * Copyright (c) 2026 Tejun Heo <tj@kernel.org>
1160a59eacSTejun Heo  */
1260a59eacSTejun Heo #ifndef __SCX_QMAP_H
1360a59eacSTejun Heo #define __SCX_QMAP_H
1460a59eacSTejun Heo 
1560a59eacSTejun Heo #ifdef __BPF__
1660a59eacSTejun Heo #include <scx/bpf_arena_common.bpf.h>
1760a59eacSTejun Heo #else
1860a59eacSTejun Heo #include <linux/types.h>
1960a59eacSTejun Heo #include <scx/bpf_arena_common.h>
2060a59eacSTejun Heo #endif
2160a59eacSTejun Heo 
2260a59eacSTejun Heo #define MAX_SUB_SCHEDS		8
23e9151ed5STejun Heo #define MAX_PARTS		(MAX_SUB_SCHEDS + 1)	/* participants: children + self */
2460a59eacSTejun Heo 
2560a59eacSTejun Heo /*
2660a59eacSTejun Heo  * cpu_ctxs[] is sized to a fixed cap so the layout is shared between BPF and
2760a59eacSTejun Heo  * userspace. Keep this in sync with NR_CPUS used by the BPF side.
2860a59eacSTejun Heo  */
2960a59eacSTejun Heo #define SCX_QMAP_MAX_CPUS	1024
3060a59eacSTejun Heo 
31e9151ed5STejun Heo /*
32e9151ed5STejun Heo  * An owner id identifies who holds a cid: a child slot in [0, MAX_SUB_SCHEDS),
33e9151ed5STejun Heo  * CID_SELF for this node, CID_NONE for a cid not currently held, or CID_SHARED
34e9151ed5STejun Heo  * for a cid in the round-robin pool (its live holder is rr_slots[rr_pos]). Used
35e9151ed5STejun Heo  * by the partition's cid_owner[].
36e9151ed5STejun Heo  */
37e9151ed5STejun Heo #define CID_SELF	(-1)
38e9151ed5STejun Heo #define CID_NONE	(-2)
39e9151ed5STejun Heo #define CID_SHARED	(-3)
40e9151ed5STejun Heo 
41874fdc0eSTejun Heo /* -C cid-override test modes. Selects cid_override_mode in scx_qmap.bpf.c. */
42874fdc0eSTejun Heo enum qmap_cid_override {
43874fdc0eSTejun Heo 	QMAP_CID_OVR_OFF	= 0,	/* disabled */
44874fdc0eSTejun Heo 	QMAP_CID_OVR_SHUFFLE	= 1,	/* valid reversed cpu->cid mapping */
45874fdc0eSTejun Heo 	QMAP_CID_OVR_BAD_DUP	= 2,	/* invalid: duplicate cid assignment */
46874fdc0eSTejun Heo 	QMAP_CID_OVR_BAD_RANGE	= 3,	/* invalid: out-of-range cid */
4730067643STejun Heo 	QMAP_CID_OVR_BAD_MONO	= 4,	/* invalid: non-monotonic shard_start */
48874fdc0eSTejun Heo };
49874fdc0eSTejun Heo 
5060a59eacSTejun Heo struct cpu_ctx {
51c89b7a09STejun Heo 	u64 dsp_idx;		/* dispatch index */
52c89b7a09STejun Heo 	u64 dsp_cnt;		/* remaining count */
53c89b7a09STejun Heo 	u32 avg_weight;
54c89b7a09STejun Heo 	u32 cpuperf_target;
5560a59eacSTejun Heo };
5660a59eacSTejun Heo 
571d2c5353STejun Heo struct qmap_fifo {
581d2c5353STejun Heo 	struct task_ctx __arena *head;
591d2c5353STejun Heo 	struct task_ctx __arena *tail;
60c89b7a09STejun Heo 	s32 idx;
611d2c5353STejun Heo };
621d2c5353STejun Heo 
63eb00f4a3STejun Heo /* -J fault-injection modes. Selects inject_mode in struct qmap_arena. */
64eb00f4a3STejun Heo enum qmap_inject {
65eb00f4a3STejun Heo 	QMAP_INJ_OFF		= 0,
66eb00f4a3STejun Heo 	QMAP_INJ_WRONG_CID	= 1,	/* dispatch to a cid we don't hold */
6701cad830STejun Heo 	QMAP_INJ_INIT_FAIL	= 2,	/* fail init_task for "qmfail*" comms */
68b20dfde5STejun Heo 	QMAP_INJ_CGRP_INIT_FAIL	= 3,	/* fail cpuctl_init for "qmfail*" cgroups */
69eb00f4a3STejun Heo };
70eb00f4a3STejun Heo 
71e9151ed5STejun Heo /*
72e9151ed5STejun Heo  * scx_cmask's are embedded in struct qmap_arena with inline backing storage.
73e9151ed5STejun Heo  * The bpf side uses &field.mask with the normal cmask_* helpers. Userspace
74e9151ed5STejun Heo  * doesn't have access to the type definition and sees same-sized opaque words.
75e9151ed5STejun Heo  * _Static_assert()'s in .bpf.c ensure that they are in sync.
76e9151ed5STejun Heo  */
77e9151ed5STejun Heo #define QMAP_CMASK_WORDS	(((SCX_QMAP_MAX_CPUS) + 63) / 64 + 1)
78e9151ed5STejun Heo struct qmap_cmask {
79e9151ed5STejun Heo #ifdef __BPF__
80e9151ed5STejun Heo 	union {
81e9151ed5STejun Heo 		struct scx_cmask mask;
82e9151ed5STejun Heo 		u64 words[QMAP_CMASK_WORDS + 2];
83e9151ed5STejun Heo 	};
84e9151ed5STejun Heo #else
85e9151ed5STejun Heo 	u64 words[QMAP_CMASK_WORDS + 2];
86e9151ed5STejun Heo #endif
87e9151ed5STejun Heo };
88e9151ed5STejun Heo 
89e9151ed5STejun Heo /* Opaque to userspace; defined in scx_qmap.bpf.c. */
90e9151ed5STejun Heo struct task_ctx;
91e9151ed5STejun Heo 
92e9151ed5STejun Heo /* per-direct-child state for the sub-scheduler */
93e9151ed5STejun Heo struct sub_sched_ctx {
94e9151ed5STejun Heo 	u64 cgroup_id;
9529ac3ae9STejun Heo 	u32 weight;			/* cpu.weight, seeded at attach, then set_weight */
96e9151ed5STejun Heo 	u64 nr_dsps;
97e9151ed5STejun Heo 	struct qmap_cmask granted_cids;	/* cids granted excl to this child */
98e9151ed5STejun Heo 	struct qmap_cmask prev_granted;	/* last grant, for delta calculation */
99e9151ed5STejun Heo };
100e9151ed5STejun Heo 
101e9151ed5STejun Heo /*
102e9151ed5STejun Heo  * compute_partition() builds the following from this node's held caps, and
103e9151ed5STejun Heo  * apply_partition()/rr_advance() execute it. Userspace only reads for the
104e9151ed5STejun Heo  * hierarchy display.
105e9151ed5STejun Heo  */
106e9151ed5STejun Heo struct qmap_partition {
107e9151ed5STejun Heo 	u32 nr_excl;			/* number of excl-held (delegatable) cids */
108e9151ed5STejun Heo 	s32 cid_owner[SCX_QMAP_MAX_CPUS]; /* per cid: owner id, or CID_NONE */
109e9151ed5STejun Heo 	s32 shared_cids[MAX_PARTS];	/* the round-robin cid pool */
110e9151ed5STejun Heo 	u32 nr_shared;			/* number of shared_cids entries */
111e9151ed5STejun Heo 	u64 rr_slots[MAX_PARTS];	/* rotation order: holder cgroup_id, 0 = self */
112e9151ed5STejun Heo 	u32 nr_rr;			/* number of rr_slots entries */
113e9151ed5STejun Heo 	u32 rr_pos;			/* current rotation index */
114e9151ed5STejun Heo };
115e9151ed5STejun Heo 
11660a59eacSTejun Heo struct qmap_arena {
11760a59eacSTejun Heo 	/* userspace-visible stats */
118c89b7a09STejun Heo 	u64 nr_enqueued, nr_dispatched, nr_reenqueued, nr_reenqueued_cid0;
119c89b7a09STejun Heo 	u64 nr_dequeued, nr_ddsp_from_enq;
120c89b7a09STejun Heo 	u64 nr_core_sched_execed;
121c89b7a09STejun Heo 	u64 nr_expedited_local, nr_expedited_remote;
122c89b7a09STejun Heo 	u64 nr_expedited_lost, nr_expedited_from_timer;
123c89b7a09STejun Heo 	u64 nr_highpri_queued;
124c89b7a09STejun Heo 	u32 test_error_cnt;
125c89b7a09STejun Heo 	u32 cpuperf_min, cpuperf_avg, cpuperf_max;
126c89b7a09STejun Heo 	u32 cpuperf_target_min, cpuperf_target_avg, cpuperf_target_max;
12760a59eacSTejun Heo 
12860a59eacSTejun Heo 	/* kernel-side runtime state */
129c89b7a09STejun Heo 	u64 core_sched_head_seqs[5];
130c89b7a09STejun Heo 	u64 core_sched_tail_seqs[5];
13160a59eacSTejun Heo 
13260a59eacSTejun Heo 	struct cpu_ctx cpu_ctxs[SCX_QMAP_MAX_CPUS];
133a6628db4STejun Heo 
134*a05c5b5cSTejun Heo 	/* cid-override test input, populated by the loader before attach */
135*a05c5b5cSTejun Heo 	__s32 cid_override_cpu_to_cid[SCX_QMAP_MAX_CPUS];
136*a05c5b5cSTejun Heo 	__s32 cid_override_shard_start[SCX_QMAP_MAX_CPUS];
137*a05c5b5cSTejun Heo 
138a6628db4STejun Heo 	/* task_ctx slab; allocated and threaded by qmap_init() */
139a6628db4STejun Heo 	struct task_ctx __arena *task_ctxs;
140a6628db4STejun Heo 	struct task_ctx __arena *task_free_head;
1411d2c5353STejun Heo 
1421d2c5353STejun Heo 	/* five priority FIFOs, each a doubly-linked list through task_ctx */
1431d2c5353STejun Heo 	struct qmap_fifo fifos[5];
144e9151ed5STejun Heo 
145e9151ed5STejun Heo 	/*
146e9151ed5STejun Heo 	 * Hierarchical sub-scheduling state. See the design comment at the top
147e9151ed5STejun Heo 	 * of scx_qmap.bpf.c.
148e9151ed5STejun Heo 	 */
149e9151ed5STejun Heo 	u32 nr_cids;			/* cid count, cached at init */
150e9151ed5STejun Heo 
151e9151ed5STejun Heo 	/* bpf-owned partition: read by userspace for display */
152e9151ed5STejun Heo 	struct qmap_partition part;
153e9151ed5STejun Heo 
154e9151ed5STejun Heo 	struct sub_sched_ctx sub_sched_ctxs[MAX_SUB_SCHEDS]; /* per-child context */
155e9151ed5STejun Heo 	u64 nr_sub_scheds;		/* number of attached children */
156e9151ed5STejun Heo 
157e9151ed5STejun Heo 	/* bpf-internal per-cid state */
158e9151ed5STejun Heo 	u8 cid_shared[SCX_QMAP_MAX_CPUS]; /* per cid: 1 if held shared (ENQ_IMMED-only) */
159e9151ed5STejun Heo 
160e9151ed5STejun Heo 	/* allocated cid-time, charged per owner by account_alloc() */
161e9151ed5STejun Heo 	u64 alloc_ns[MAX_SUB_SCHEDS];	/* per child slot */
162e9151ed5STejun Heo 	u64 self_alloc_ns;
163e9151ed5STejun Heo 	u64 alloc_ts;			/* last accounting timestamp */
164e9151ed5STejun Heo 	u64 alloc_window_ns;		/* total accounted time, the alloc denominator */
165e9151ed5STejun Heo 
166e9151ed5STejun Heo 	/* bpf-internal cmasks (embedded, see struct qmap_cmask) */
167e9151ed5STejun Heo 	struct qmap_cmask self_cids;	/* cids this node runs its own tasks on */
168e9151ed5STejun Heo 	struct qmap_cmask idle_cids;	/* idle state of all cids regardless of delegation */
169e9151ed5STejun Heo 	struct qmap_cmask rr_cids;	/* the shared pool, as a mask for grant/revoke */
170e9151ed5STejun Heo 
171e9151ed5STejun Heo 	/* scratch cmasks */
172e9151ed5STejun Heo 	struct qmap_cmask to_revoke_cids; /* delta cids to revoke */
173e9151ed5STejun Heo 	struct qmap_cmask to_grant_cids; /* delta cids to grant */
174e9151ed5STejun Heo 	struct qmap_cmask prev_rr_cids; /* previous shared pool, to clear stale grants */
175e9151ed5STejun Heo 	struct qmap_cmask held_excl;	/* cids held excl (ENQ): delegatable */
176e9151ed5STejun Heo 	struct qmap_cmask held_shared;	/* cids held shared (ENQ_IMMED only): self-local */
177e9151ed5STejun Heo 
178e9151ed5STejun Heo 	/* bpf -> userspace: stats */
179e9151ed5STejun Heo 	u64 nr_reenq_cap;		/* SCX_TASK_REENQ_CAP bounces */
180e9151ed5STejun Heo 	u64 nr_reenq_immed;		/* SCX_TASK_REENQ_IMMED bounces */
181eb00f4a3STejun Heo 	u64 nr_inject_attempts;		/* fault-injection: dispatches to an unheld cid */
182e158e309STejun Heo 	u64 nr_rescue_dsp;		/* SCX_ENQ_RESCUE dispatch attempts */
183eb00f4a3STejun Heo 	u32 inject_mode;		/* fault-injection mode (QMAP_INJ_*) */
18460a59eacSTejun Heo };
18560a59eacSTejun Heo 
18660a59eacSTejun Heo #endif /* __SCX_QMAP_H */
187