scx_bpf_compat/
lib.rs

1// Copyright (c) Meta Platforms, Inc. and affiliates.
2//
3// This software may be used and distributed according to the terms of the
4// GNU General Public License version 2.
5mod bpf_skel;
6
7use crate::bpf_skel::BpfSkelBuilder;
8
9use std::mem::MaybeUninit;
10
11use anyhow::Result;
12use libbpf_rs::skel::{OpenSkel, SkelBuilder};
13use libbpf_rs::ProgramType;
14use once_cell::sync::OnceCell;
15use scx_utils::compat::ksym_exists;
16
17/// Check if kernel supports calling kfuncs from SYSCALL programs.
18/// This was introduced in kernel commit a8e03b6bbb2c
19/// "bpf: Allow invoking kfuncs from BPF_PROG_TYPE_SYSCALL progs"
20pub fn kfuncs_supported_in_syscall() -> Result<bool> {
21    static MEMO: OnceCell<bool> = OnceCell::new();
22
23    MEMO.get_or_try_init(|| {
24        if !ProgramType::Syscall.is_supported()? {
25            return Ok(false);
26        }
27        if !ksym_exists("bpf_cpumask_create")? {
28            return Ok(false);
29        }
30        if !ksym_exists("bpf_cpumask_release")? {
31            return Ok(false);
32        }
33
34        let skel_builder = BpfSkelBuilder::default();
35        let mut open_object = MaybeUninit::uninit();
36
37        let mut open_skel = skel_builder.open(&mut open_object)?;
38        for mut prog in open_skel.open_object_mut().progs_mut() {
39            prog.set_autoload(prog.name() == "kfuncs_test_syscall");
40        }
41
42        let ret = match open_skel.load() {
43            Ok(_) => true,
44            Err(e) => {
45                log::trace!("rejecting program for `kfuncs_supported_in_syscall` with error: {e}");
46                false
47            }
48        };
49
50        Ok(ret)
51    })
52    .copied()
53}