This commit introduces eBPF program as backend to trigger AUX pause and resume. The eBPF programs are prepared for attaching kprobe, kretprobe and tracepoints. When a eBPF program is invoked, it calls the eBPF API bpf_perf_event_aux_pause() for controlling AUX pause and resume. Signed-off-by: Leo Yan <leo.yan@xxxxxxx> --- tools/perf/Makefile.perf | 1 + tools/perf/util/bpf_skel/auxtrace_pause.bpf.c | 135 ++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 tools/perf/util/bpf_skel/auxtrace_pause.bpf.c diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index d74241a15131..14ac29094eb5 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -1173,6 +1173,7 @@ SKELETONS += $(SKEL_OUT)/kwork_trace.skel.h $(SKEL_OUT)/sample_filter.skel.h SKELETONS += $(SKEL_OUT)/kwork_top.skel.h SKELETONS += $(SKEL_OUT)/bench_uprobe.skel.h SKELETONS += $(SKEL_OUT)/augmented_raw_syscalls.skel.h +SKELETONS += $(SKEL_OUT)/auxtrace_pause.skel.h $(SKEL_TMP_OUT) $(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT): $(Q)$(MKDIR) -p $@ diff --git a/tools/perf/util/bpf_skel/auxtrace_pause.bpf.c b/tools/perf/util/bpf_skel/auxtrace_pause.bpf.c new file mode 100644 index 000000000000..02c211e30e37 --- /dev/null +++ b/tools/perf/util/bpf_skel/auxtrace_pause.bpf.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +// Copyright 2024 Arm Limited +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} cpu_filter SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(__u8)); + __uint(max_entries, 1); +} task_filter SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(key_size, sizeof(__u32)); + __uint(value_size, sizeof(int)); + __uint(max_entries, 1); +} events SEC(".maps"); + +int enabled = 0; + +const volatile int has_cpu = 0; +const volatile int has_task = 0; + +static int event_aux_pause(void) +{ + __u64 key; + + if (!enabled) + return 0; + + if (has_cpu) { + __u32 cpu = bpf_get_smp_processor_id(); + __u8 *ok; + + ok = bpf_map_lookup_elem(&cpu_filter, &cpu); + if (!ok) + return 0; + + key = cpu; + } + + if (has_task) { + __u32 pid = bpf_get_current_pid_tgid() & 0xffffffff; + __u8 *ok; + + ok = bpf_map_lookup_elem(&task_filter, &pid); + if (!ok) + return 0; + + key = 0; + } + + bpf_perf_event_aux_pause(&events, key, 1); + return 0; +} + +static int event_aux_resume(void) +{ + __u64 key; + + if (!enabled) + return 0; + + if (has_cpu) { + __u32 cpu = bpf_get_smp_processor_id(); + __u8 *ok; + + ok = bpf_map_lookup_elem(&cpu_filter, &cpu); + if (!ok) + return 0; + + key = cpu; + } + + if (has_task) { + __u32 pid = bpf_get_current_pid_tgid() & 0xffffffff; + __u8 *ok; + + ok = bpf_map_lookup_elem(&task_filter, &pid); + if (!ok) + return 0; + + key = 0; + } + + bpf_perf_event_aux_pause(&events, key, 0); + return 0; +} + +SEC("kprobe/func_pause") +int BPF_PROG(kprobe_event_pause) +{ + return event_aux_pause(); +} + +SEC("kretprobe/func_pause") +int BPF_PROG(kretprobe_event_pause) +{ + return event_aux_pause(); +} + +SEC("tp/func_pause") +int BPF_PROG(tp_event_pause) +{ + return event_aux_pause(); +} + +SEC("kprobe/func_resume") +int BPF_PROG(kprobe_event_resume) +{ + return event_aux_resume(); +} + +SEC("kretprobe/func_resume") +int BPF_PROG(kretprobe_event_resume) +{ + return event_aux_resume(); +} + +SEC("tp/func_resume") +int BPF_PROG(tp_event_resume) +{ + return event_aux_resume(); +} + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; -- 2.34.1