summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/sched/ext/cid.c26
-rw-r--r--kernel/sched/ext/types.h4
-rw-r--r--tools/sched_ext/include/scx/common.bpf.h2
3 files changed, 21 insertions, 11 deletions
diff --git a/kernel/sched/ext/cid.c b/kernel/sched/ext/cid.c
index 39f88deb9..d4d5f5378 100644
--- a/kernel/sched/ext/cid.c
+++ b/kernel/sched/ext/cid.c
@@ -912,30 +912,36 @@ bool scx_cmask_empty(const struct scx_cmask *m)
/**
* scx_bpf_cid_topo - Copy out per-cid topology info
* @cid: cid to look up
- * @out__uninit: where to copy the topology info; fully written by this call
+ * @out: where to copy the topology info
+ * @out__sz: size of @out, the program's sizeof(struct scx_cid_topo)
* @aux: implicit BPF argument to access bpf_prog_aux hidden from BPF progs
*
- * Fill @out__uninit with the topology info for @cid. Trigger scx_error() if
- * @cid is out of range. If @cid is valid but in the no-topo section, all fields
- * are set to -1. All fields are also set to -1 when no cid tables have been
- * published yet, which a program may observe while racing the root enable.
+ * Fill @out with the topology info for @cid. Trigger scx_error() if @cid is out
+ * of range. If @cid is valid but in the no-topo section, all fields are set to
+ * -1. All fields are also set to -1 when no cid tables have been published yet,
+ * which a program may observe while racing the root enable.
+ *
+ * The program's struct may be older or newer than the kernel's. The smaller of
+ * @out__sz and the kernel's size is copied and the rest of @out is set to -1.
*/
-__bpf_kfunc void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out__uninit,
+__bpf_kfunc void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out, size_t out__sz,
const struct bpf_prog_aux *aux)
{
+ size_t len = min(out__sz, sizeof(*out));
struct scx_cid_topo *topo;
struct scx_sched *sch;
+ /* the error cases and fields the kernel lacks read as -1 */
+ memset(out, 0xff, out__sz);
+
guard(rcu)();
sch = scx_prog_sched(aux);
topo = rcu_dereference(scx_cid_topo);
- if (unlikely(!sch) || !cid_valid(sch, cid) || unlikely(!topo)) {
- *out__uninit = SCX_CID_TOPO_NEG;
+ if (unlikely(!sch) || !cid_valid(sch, cid) || unlikely(!topo))
return;
- }
- *out__uninit = topo[cid];
+ memcpy(out, &topo[cid], len);
}
__bpf_kfunc_end_defs();
diff --git a/kernel/sched/ext/types.h b/kernel/sched/ext/types.h
index 943d8d429..139176cf9 100644
--- a/kernel/sched/ext/types.h
+++ b/kernel/sched/ext/types.h
@@ -70,6 +70,10 @@ enum scx_consts {
* smaller shards if the LLC exceeds the target size. No-topo cids are packed
* into their own max-sized shards.
*
+ * New fields are appended, never inserted: scx_bpf_cid_topo() copies this
+ * struct out sized by the program's own layout, and an older program's copy
+ * must stay a prefix of the kernel's.
+ *
* @core_cid: first cid of this cid's core (smt-sibling group)
* @core_idx: global index of that core, in [0, nr_cores_at_init)
* @llc_cid: first cid of this cid's LLC
diff --git a/tools/sched_ext/include/scx/common.bpf.h b/tools/sched_ext/include/scx/common.bpf.h
index 2ddb01a05..22f24ebef 100644
--- a/tools/sched_ext/include/scx/common.bpf.h
+++ b/tools/sched_ext/include/scx/common.bpf.h
@@ -106,7 +106,7 @@ u64 scx_bpf_now(void) __ksym __weak;
void scx_bpf_events(struct scx_event_stats *events, size_t events__sz) __ksym __weak;
s32 scx_bpf_cpu_to_cid(s32 cpu) __ksym __weak;
s32 scx_bpf_cid_to_cpu(s32 cid) __ksym __weak;
-void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out) __ksym __weak;
+void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out, size_t out__sz) __ksym __weak;
void scx_bpf_kick_cid(s32 cid, u64 flags) __ksym __weak;
s32 scx_bpf_task_cid(const struct task_struct *p) __ksym __weak;
s32 scx_bpf_this_cid(void) __ksym __weak;