
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICA1GK -------------------------------- Create a bpf iter target for the 'cpuinfo' interface, to which the bpf prog can attach. Signed-off-by: GONG Ruiqi <gongruiqi1@huawei.com> --- arch/x86/kernel/cpu/Makefile | 1 + arch/x86/kernel/cpu/bpf-rvi.c | 120 ++++++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/proc.c | 2 +- 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 arch/x86/kernel/cpu/bpf-rvi.c diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index e10099f4a0af..b96c8413bbc3 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o obj-$(CONFIG_HYPERVISOR_GUEST) += vmware.o hypervisor.o mshyperv.o obj-$(CONFIG_ACRN_GUEST) += acrn.o +obj-$(CONFIG_BPF_RVI) += bpf-rvi.o proc.o quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $@ $^ diff --git a/arch/x86/kernel/cpu/bpf-rvi.c b/arch/x86/kernel/cpu/bpf-rvi.c new file mode 100644 index 000000000000..d07d4cc758a9 --- /dev/null +++ b/arch/x86/kernel/cpu/bpf-rvi.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 Huawei Technologies Co., Ltd */ +#include <linux/cpumask.h> +#include <linux/bpf.h> +#include <linux/cpuset.h> +#include <linux/pid_namespace.h> + +struct cpuinfo_x86_bpf { + unsigned int cpu_khz; + unsigned int siblings; +}; + +struct bpf_iter__cpuinfo_x86 { + __bpf_md_ptr(struct bpf_iter_meta *, meta); + __bpf_md_ptr(struct cpuinfo_x86 *, cpuinfo); + __bpf_md_ptr(struct cpuinfo_x86_bpf *, cpuinfo_bpf); +}; + +struct cpuinfo_x86_seq_priv { + cpumask_t allowed_mask; +}; + +static void *bpf_c_start(struct seq_file *m, loff_t *pos) +{ + struct cpuinfo_x86_seq_priv *priv = m->private; + struct task_struct *reaper = get_current_level1_reaper(); + + task_effective_cpumask(reaper ?: current, &priv->allowed_mask); + if (reaper) + put_task_struct(reaper); + + /* + * DO NOT use cpumask_first() here: sys_read may start from somewhere in + * the middle of the file, and *pos may contain a value from the last + * read. + */ + *pos = cpumask_next(*pos - 1, &priv->allowed_mask); + if ((*pos) < nr_cpu_ids) + return &cpu_data(*pos); + return NULL; +} + +static void *bpf_c_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct cpuinfo_x86_seq_priv *priv = m->private; + + *pos = cpumask_next(*pos, &priv->allowed_mask); + if ((*pos) < nr_cpu_ids) + return &cpu_data(*pos); + return NULL; +} + +int show_cpuinfo(struct seq_file *m, void *v); + +static int bpf_show_cpuinfo(struct seq_file *m, void *v) +{ + struct bpf_iter__cpuinfo_x86 ctx; + struct bpf_iter_meta meta; + struct cpuinfo_x86_bpf cpuinfo_bpf; + struct bpf_prog *prog; + + meta.seq = m; + prog = bpf_iter_get_info(&meta, false); + if (!prog) + return show_cpuinfo(m, v); + + ctx.meta = &meta; + ctx.cpuinfo = (struct cpuinfo_x86 *)v; + + cpuinfo_bpf.cpu_khz = cpu_khz; + cpuinfo_bpf.siblings = cpumask_weight(topology_core_cpumask(ctx.cpuinfo->cpu_index)); + ctx.cpuinfo_bpf = &cpuinfo_bpf; + + return bpf_iter_run_prog(prog, &ctx); +} + +static void bpf_c_stop(struct seq_file *m, void *v) +{ +} + +const struct seq_operations bpf_cpuinfo_op = { + .start = bpf_c_start, + .next = bpf_c_next, + .stop = bpf_c_stop, + .show = bpf_show_cpuinfo, +}; + +DEFINE_BPF_ITER_FUNC(cpuinfo_x86, struct bpf_iter_meta *meta, struct cpuinfo_x86 *cpuinfo, + struct cpuinfo_x86_bpf *cpuinfo_bpf) + +BTF_ID_LIST(btf_cpuinfo_x86_id) +BTF_ID(struct, cpuinfo_x86) +BTF_ID(struct, cpuinfo_x86_bpf) + +static const struct bpf_iter_seq_info cpuinfo_x86_seq_info = { + .seq_ops = &bpf_cpuinfo_op, + .init_seq_private = NULL, + .fini_seq_private = NULL, + .seq_priv_size = sizeof(struct cpuinfo_x86_seq_priv), +}; + +static struct bpf_iter_reg cpuinfo_x86_reg_info = { + .target = "cpuinfo_x86", + .ctx_arg_info_size = 2, + .ctx_arg_info = { + { offsetof(struct bpf_iter__cpuinfo_x86, cpuinfo), + PTR_TO_BTF_ID, }, + { offsetof(struct bpf_iter__cpuinfo_x86, cpuinfo_bpf), + PTR_TO_BTF_ID, }, + }, + .seq_info = &cpuinfo_x86_seq_info, +}; + +static int __init cpuinfo_iter_init(void) +{ + cpuinfo_x86_reg_info.ctx_arg_info[0].btf_id = btf_cpuinfo_x86_id[0]; + cpuinfo_x86_reg_info.ctx_arg_info[1].btf_id = btf_cpuinfo_x86_id[1]; + return bpf_iter_reg_target(&cpuinfo_x86_reg_info); +} +late_initcall(cpuinfo_iter_init); diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index a0f81db51eac..1aaf5be60a82 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -60,7 +60,7 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) } #endif -static int show_cpuinfo(struct seq_file *m, void *v) +int show_cpuinfo(struct seq_file *m, void *v) { struct cpuinfo_x86 *c = v; unsigned int cpu; -- 2.25.1