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