Introduce a BPF program to trigger AUX pause and resume. Once a attached tracepoint is hit, the BPF program calls the bpf_perf_event_aux_pause() kfunc for controlling AUX trace. Signed-off-by: Leo Yan --- tools/perf/Makefile.perf | 1 + tools/perf/util/bpf_skel/auxtrace_pause.bpf.c | 156 ++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index d4c7031b01a77f4a42326e4c9a88d8a352143178..8fdd24ba4c25ff4a69925a8e0c85bc78dd4fda47 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -1179,6 +1179,7 @@ SKELETONS += $(SKEL_OUT)/kwork_trace.skel.h $(SKEL_OUT)/sample_filter.skel.h SKELETONS += $(SKEL_OUT)/kwork_top.skel.h $(SKEL_OUT)/syscall_summary.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 0000000000000000000000000000000000000000..37f8e1d096a3098415f6469014652dea948044d2 --- /dev/null +++ b/tools/perf/util/bpf_skel/auxtrace_pause.bpf.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +// Copyright 2025 Arm Limited +#include "vmlinux.h" +#include +#include + +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; +const volatile int per_thread = 0; + +int bpf_perf_event_aux_pause(void *map, u64 flags, bool pause) __ksym; + +static int event_aux_pause(void) +{ + __u64 flag; + __u32 cpu = bpf_get_smp_processor_id(); + + if (!enabled) + return 0; + + if (has_cpu) { + __u8 *ok; + + ok = bpf_map_lookup_elem(&cpu_filter, &cpu); + if (!ok) + return 0; + } + + 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; + } + + flag = per_thread ? 0 : BPF_F_CURRENT_CPU; + bpf_perf_event_aux_pause(&events, flag, true); + return 0; +} + +static int event_aux_resume(void) +{ + __u64 flag; + __u32 cpu = bpf_get_smp_processor_id(); + + if (!enabled) + return 0; + + if (has_cpu) { + __u8 *ok; + + ok = bpf_map_lookup_elem(&cpu_filter, &cpu); + if (!ok) + return 0; + } + + 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; + } + + flag = per_thread ? 0 : BPF_F_CURRENT_CPU; + bpf_perf_event_aux_pause(&events, flag, false); + return 0; +} + +SEC("kprobe/func_pause") +int BPF_PROG(kprobe_event_pause) +{ + return event_aux_pause(); +} + +SEC("kprobe/func_resume") +int BPF_PROG(kprobe_event_resume) +{ + return event_aux_resume(); +} + +SEC("kretprobe/func_pause") +int BPF_PROG(kretprobe_event_pause) +{ + return event_aux_pause(); +} + +SEC("kretprobe/func_resume") +int BPF_PROG(kretprobe_event_resume) +{ + return event_aux_resume(); +} + +SEC("uprobe/func_pause") +int BPF_PROG(uprobe_event_pause) +{ + return event_aux_pause(); +} + +SEC("uprobe/func_resume") +int BPF_PROG(uprobe_event_resume) +{ + return event_aux_resume(); +} + +SEC("uretprobe/func_pause") +int BPF_PROG(uretprobe_event_pause) +{ + return event_aux_pause(); +} + +SEC("uretprobe/func_resume") +int BPF_PROG(uretprobe_event_resume) +{ + return event_aux_resume(); +} + +SEC("tp/func_pause") +int BPF_PROG(tp_event_pause) +{ + return event_aux_pause(); +} + +SEC("tp/func_resume") +int BPF_PROG(tp_event_resume) +{ + return event_aux_resume(); +} + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; -- 2.34.1