2022-05-18 15:47:21 -07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include "util/bpf_counter.h"
|
|
|
|
#include "util/debug.h"
|
|
|
|
#include "util/evsel.h"
|
|
|
|
#include "util/evlist.h"
|
|
|
|
#include "util/off_cpu.h"
|
|
|
|
#include "util/perf-hooks.h"
|
2022-05-18 15:47:24 -07:00
|
|
|
#include "util/record.h"
|
2022-05-18 15:47:21 -07:00
|
|
|
#include "util/session.h"
|
2022-05-18 15:47:22 -07:00
|
|
|
#include "util/target.h"
|
|
|
|
#include "util/cpumap.h"
|
|
|
|
#include "util/thread_map.h"
|
2022-05-18 15:47:24 -07:00
|
|
|
#include "util/cgroup.h"
|
2022-08-11 11:54:54 -07:00
|
|
|
#include "util/strlist.h"
|
2022-05-18 15:47:21 -07:00
|
|
|
#include <bpf/bpf.h>
|
2025-04-30 19:28:01 -07:00
|
|
|
#include <internal/xyarray.h>
|
2025-04-30 19:28:07 -07:00
|
|
|
#include <linux/time64.h>
|
2022-05-18 15:47:21 -07:00
|
|
|
|
|
|
|
#include "bpf_skel/off_cpu.skel.h"
|
|
|
|
|
|
|
|
#define MAX_STACKS 32
|
2022-08-11 11:54:55 -07:00
|
|
|
#define MAX_PROC 4096
|
2022-05-18 15:47:21 -07:00
|
|
|
/* we don't need actual timestamp, just want to put the samples at last */
|
|
|
|
#define OFF_CPU_TIMESTAMP (~0ull << 32)
|
|
|
|
|
|
|
|
static struct off_cpu_bpf *skel;
|
|
|
|
|
|
|
|
struct off_cpu_key {
|
|
|
|
u32 pid;
|
|
|
|
u32 tgid;
|
|
|
|
u32 stack_id;
|
|
|
|
u32 state;
|
2022-05-18 15:47:24 -07:00
|
|
|
u64 cgroup_id;
|
2022-05-18 15:47:21 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
union off_cpu_data {
|
|
|
|
struct perf_event_header hdr;
|
|
|
|
u64 array[1024 / sizeof(u64)];
|
|
|
|
};
|
|
|
|
|
2025-04-30 19:28:06 -07:00
|
|
|
u64 off_cpu_raw[MAX_STACKS + 5];
|
|
|
|
|
2022-05-18 15:47:21 -07:00
|
|
|
static int off_cpu_config(struct evlist *evlist)
|
|
|
|
{
|
perf record --off-cpu: Parse off-cpu event
Parse the off-cpu event using parse_event(), as bpf-output.
Call evlist__enable_evsel() on off-cpu event. This fixes the inability
to collect direct off-cpu samples on a workload, as reported by Arnaldo
Carvalho de Melo <acme@redhat.com>.
The reason being, workload sets enable_on_exec instead of calling
evlist__enable(), but off-cpu event does not attach to an executable and
execve won't be called, so the fds from perf_event_open() are not
enabled.
no-inherit should be set to 1, here's the reason:
We update the BPF perf_event map for direct off-cpu sample dumping (in
following patches), it executes as follows:
bpf_map_update_value()
bpf_fd_array_map_update_elem()
perf_event_fd_array_get_ptr()
perf_event_read_local()
In perf_event_read_local(), there is:
int perf_event_read_local(struct perf_event *event, u64 *value,
u64 *enabled, u64 *running)
{
...
/*
* It must not be an event with inherit set, we cannot read
* all child counters from atomic context.
*/
if (event->attr.inherit) {
ret = -EOPNOTSUPP;
goto out;
}
Which means no-inherit has to be true for updating the BPF perf_event
map.
Moreover, for bpf-output events, we primarily want a system-wide event
instead of a per-task event.
The reason is that in BPF's bpf_perf_event_output(), BPF uses the CPU
index to retrieve the perf_event file descriptor it outputs to.
Making a bpf-output event system-wide naturally satisfies this
requirement by mapping CPU appropriately.
Suggested-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Howard Chu <howardchu95@gmail.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Gautam Menghani <gautam@linux.ibm.com>
Tested-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20241108204137.2444151-4-howardchu95@gmail.com
Link: https://lore.kernel.org/r/20250501022809.449767-3-howardchu95@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2025-04-30 19:28:00 -07:00
|
|
|
char off_cpu_event[64];
|
2022-05-18 15:47:21 -07:00
|
|
|
struct evsel *evsel;
|
|
|
|
|
perf record --off-cpu: Parse off-cpu event
Parse the off-cpu event using parse_event(), as bpf-output.
Call evlist__enable_evsel() on off-cpu event. This fixes the inability
to collect direct off-cpu samples on a workload, as reported by Arnaldo
Carvalho de Melo <acme@redhat.com>.
The reason being, workload sets enable_on_exec instead of calling
evlist__enable(), but off-cpu event does not attach to an executable and
execve won't be called, so the fds from perf_event_open() are not
enabled.
no-inherit should be set to 1, here's the reason:
We update the BPF perf_event map for direct off-cpu sample dumping (in
following patches), it executes as follows:
bpf_map_update_value()
bpf_fd_array_map_update_elem()
perf_event_fd_array_get_ptr()
perf_event_read_local()
In perf_event_read_local(), there is:
int perf_event_read_local(struct perf_event *event, u64 *value,
u64 *enabled, u64 *running)
{
...
/*
* It must not be an event with inherit set, we cannot read
* all child counters from atomic context.
*/
if (event->attr.inherit) {
ret = -EOPNOTSUPP;
goto out;
}
Which means no-inherit has to be true for updating the BPF perf_event
map.
Moreover, for bpf-output events, we primarily want a system-wide event
instead of a per-task event.
The reason is that in BPF's bpf_perf_event_output(), BPF uses the CPU
index to retrieve the perf_event file descriptor it outputs to.
Making a bpf-output event system-wide naturally satisfies this
requirement by mapping CPU appropriately.
Suggested-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Howard Chu <howardchu95@gmail.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Gautam Menghani <gautam@linux.ibm.com>
Tested-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20241108204137.2444151-4-howardchu95@gmail.com
Link: https://lore.kernel.org/r/20250501022809.449767-3-howardchu95@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2025-04-30 19:28:00 -07:00
|
|
|
scnprintf(off_cpu_event, sizeof(off_cpu_event), "bpf-output/name=%s/", OFFCPU_EVENT);
|
|
|
|
if (parse_event(evlist, off_cpu_event)) {
|
|
|
|
pr_err("Failed to open off-cpu event\n");
|
|
|
|
return -1;
|
2022-05-18 15:47:21 -07:00
|
|
|
}
|
|
|
|
|
perf record --off-cpu: Parse off-cpu event
Parse the off-cpu event using parse_event(), as bpf-output.
Call evlist__enable_evsel() on off-cpu event. This fixes the inability
to collect direct off-cpu samples on a workload, as reported by Arnaldo
Carvalho de Melo <acme@redhat.com>.
The reason being, workload sets enable_on_exec instead of calling
evlist__enable(), but off-cpu event does not attach to an executable and
execve won't be called, so the fds from perf_event_open() are not
enabled.
no-inherit should be set to 1, here's the reason:
We update the BPF perf_event map for direct off-cpu sample dumping (in
following patches), it executes as follows:
bpf_map_update_value()
bpf_fd_array_map_update_elem()
perf_event_fd_array_get_ptr()
perf_event_read_local()
In perf_event_read_local(), there is:
int perf_event_read_local(struct perf_event *event, u64 *value,
u64 *enabled, u64 *running)
{
...
/*
* It must not be an event with inherit set, we cannot read
* all child counters from atomic context.
*/
if (event->attr.inherit) {
ret = -EOPNOTSUPP;
goto out;
}
Which means no-inherit has to be true for updating the BPF perf_event
map.
Moreover, for bpf-output events, we primarily want a system-wide event
instead of a per-task event.
The reason is that in BPF's bpf_perf_event_output(), BPF uses the CPU
index to retrieve the perf_event file descriptor it outputs to.
Making a bpf-output event system-wide naturally satisfies this
requirement by mapping CPU appropriately.
Suggested-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Howard Chu <howardchu95@gmail.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Gautam Menghani <gautam@linux.ibm.com>
Tested-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20241108204137.2444151-4-howardchu95@gmail.com
Link: https://lore.kernel.org/r/20250501022809.449767-3-howardchu95@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2025-04-30 19:28:00 -07:00
|
|
|
evlist__for_each_entry(evlist, evsel) {
|
|
|
|
if (evsel__is_offcpu_event(evsel)) {
|
|
|
|
evsel->core.system_wide = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-05-18 15:47:21 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:22 -07:00
|
|
|
static void off_cpu_start(void *arg)
|
2022-05-18 15:47:21 -07:00
|
|
|
{
|
2022-05-18 15:47:22 -07:00
|
|
|
struct evlist *evlist = arg;
|
2025-04-30 19:28:01 -07:00
|
|
|
struct evsel *evsel;
|
|
|
|
struct perf_cpu pcpu;
|
|
|
|
int i;
|
2022-05-18 15:47:22 -07:00
|
|
|
|
|
|
|
/* update task filter for the given workload */
|
perf record offcpu: Constify control data for BPF
The control knobs set before loading BPF programs should be declared as
'const volatile' so that it can be optimized by the BPF core.
Committer testing:
root@x1:~# perf record --off-cpu
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.807 MB perf.data (5645 samples) ]
root@x1:~# perf evlist
cpu_atom/cycles/P
cpu_core/cycles/P
offcpu-time
dummy:u
root@x1:~# perf evlist -v
cpu_atom/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0xa00000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
cpu_core/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0x400000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
offcpu-time: type: 1 (software), size: 136, config: 0xa (PERF_COUNT_SW_BPF_OUTPUT), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, sample_id_all: 1
dummy:u: type: 1 (software), size: 136, config: 0x9 (PERF_COUNT_SW_DUMMY), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|IDENTIFIER, read_format: ID|LOST, inherit: 1, exclude_kernel: 1, exclude_hv: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, ksymbol: 1, bpf_event: 1
root@x1:~# perf trace -e bpf --max-events 5 perf record --off-cpu
0.000 ( 0.015 ms): :2949124/2949124 bpf(cmd: 36, uattr: 0x7ffefc6dbe30, size: 8) = -1 EOPNOTSUPP (Operation not supported)
0.031 ( 0.115 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbb60, size: 148) = 14
0.159 ( 0.037 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbc20, size: 148) = 14
23.868 ( 0.144 ms): perf/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbad0, size: 148) = 14
24.027 ( 0.014 ms): perf/2949124 bpf(uattr: 0x7ffefc6dbc80, size: 80) = 14
root@x1:~#
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240902200515.2103769-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-09-02 13:05:15 -07:00
|
|
|
if (skel->rodata->has_task && skel->rodata->uses_tgid &&
|
2022-05-18 15:47:22 -07:00
|
|
|
perf_thread_map__pid(evlist->core.threads, 0) != -1) {
|
|
|
|
int fd;
|
|
|
|
u32 pid;
|
|
|
|
u8 val = 1;
|
|
|
|
|
|
|
|
fd = bpf_map__fd(skel->maps.task_filter);
|
|
|
|
pid = perf_thread_map__pid(evlist->core.threads, 0);
|
|
|
|
bpf_map_update_elem(fd, &pid, &val, BPF_ANY);
|
|
|
|
}
|
|
|
|
|
2025-04-30 19:28:01 -07:00
|
|
|
/* update BPF perf_event map */
|
|
|
|
evsel = evlist__find_evsel_by_str(evlist, OFFCPU_EVENT);
|
|
|
|
if (evsel == NULL) {
|
|
|
|
pr_err("%s evsel not found\n", OFFCPU_EVENT);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
perf_cpu_map__for_each_cpu(pcpu, i, evsel->core.cpus) {
|
|
|
|
int err;
|
|
|
|
int cpu_nr = pcpu.cpu;
|
|
|
|
|
|
|
|
err = bpf_map__update_elem(skel->maps.offcpu_output, &cpu_nr, sizeof(int),
|
|
|
|
xyarray__entry(evsel->core.fd, cpu_nr, 0),
|
|
|
|
sizeof(int), BPF_ANY);
|
|
|
|
if (err) {
|
|
|
|
pr_err("Failed to update perf event map for direct off-cpu dumping\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:21 -07:00
|
|
|
skel->bss->enabled = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void off_cpu_finish(void *arg __maybe_unused)
|
|
|
|
{
|
|
|
|
skel->bss->enabled = 0;
|
|
|
|
off_cpu_bpf__destroy(skel);
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:23 -07:00
|
|
|
/* v5.18 kernel added prev_state arg, so it needs to check the signature */
|
|
|
|
static void check_sched_switch_args(void)
|
|
|
|
{
|
2023-10-24 15:23:10 -07:00
|
|
|
struct btf *btf = btf__load_vmlinux_btf();
|
2022-05-18 15:47:23 -07:00
|
|
|
const struct btf_type *t1, *t2, *t3;
|
|
|
|
u32 type_id;
|
|
|
|
|
2024-12-23 19:28:13 +05:30
|
|
|
if (!btf) {
|
|
|
|
pr_debug("Missing btf, check if CONFIG_DEBUG_INFO_BTF is enabled\n");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2022-12-08 10:26:36 -08:00
|
|
|
type_id = btf__find_by_name_kind(btf, "btf_trace_sched_switch",
|
2022-05-18 15:47:23 -07:00
|
|
|
BTF_KIND_TYPEDEF);
|
|
|
|
if ((s32)type_id < 0)
|
2023-10-24 15:23:10 -07:00
|
|
|
goto cleanup;
|
2022-05-18 15:47:23 -07:00
|
|
|
|
|
|
|
t1 = btf__type_by_id(btf, type_id);
|
|
|
|
if (t1 == NULL)
|
2023-10-24 15:23:10 -07:00
|
|
|
goto cleanup;
|
2022-05-18 15:47:23 -07:00
|
|
|
|
|
|
|
t2 = btf__type_by_id(btf, t1->type);
|
|
|
|
if (t2 == NULL || !btf_is_ptr(t2))
|
2023-10-24 15:23:10 -07:00
|
|
|
goto cleanup;
|
2022-05-18 15:47:23 -07:00
|
|
|
|
|
|
|
t3 = btf__type_by_id(btf, t2->type);
|
2023-09-22 16:44:44 -07:00
|
|
|
/* btf_trace func proto has one more argument for the context */
|
|
|
|
if (t3 && btf_is_func_proto(t3) && btf_vlen(t3) == 5) {
|
2022-05-18 15:47:23 -07:00
|
|
|
/* new format: pass prev_state as 4th arg */
|
|
|
|
skel->rodata->has_prev_state = true;
|
|
|
|
}
|
2023-10-24 15:23:10 -07:00
|
|
|
cleanup:
|
|
|
|
btf__free(btf);
|
2022-05-18 15:47:23 -07:00
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:24 -07:00
|
|
|
int off_cpu_prepare(struct evlist *evlist, struct target *target,
|
|
|
|
struct record_opts *opts)
|
2022-05-18 15:47:21 -07:00
|
|
|
{
|
2022-05-18 15:47:22 -07:00
|
|
|
int err, fd, i;
|
2022-05-18 15:47:24 -07:00
|
|
|
int ncpus = 1, ntasks = 1, ncgrps = 1;
|
2022-08-11 11:54:54 -07:00
|
|
|
struct strlist *pid_slist = NULL;
|
|
|
|
struct str_node *pos;
|
2022-05-18 15:47:21 -07:00
|
|
|
|
|
|
|
if (off_cpu_config(evlist) < 0) {
|
|
|
|
pr_err("Failed to config off-cpu BPF event\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:22 -07:00
|
|
|
skel = off_cpu_bpf__open();
|
2022-05-18 15:47:21 -07:00
|
|
|
if (!skel) {
|
|
|
|
pr_err("Failed to open off-cpu BPF skeleton\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:22 -07:00
|
|
|
/* don't need to set cpu filter for system-wide mode */
|
|
|
|
if (target->cpu_list) {
|
|
|
|
ncpus = perf_cpu_map__nr(evlist->core.user_requested_cpus);
|
|
|
|
bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus);
|
perf record offcpu: Constify control data for BPF
The control knobs set before loading BPF programs should be declared as
'const volatile' so that it can be optimized by the BPF core.
Committer testing:
root@x1:~# perf record --off-cpu
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.807 MB perf.data (5645 samples) ]
root@x1:~# perf evlist
cpu_atom/cycles/P
cpu_core/cycles/P
offcpu-time
dummy:u
root@x1:~# perf evlist -v
cpu_atom/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0xa00000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
cpu_core/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0x400000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
offcpu-time: type: 1 (software), size: 136, config: 0xa (PERF_COUNT_SW_BPF_OUTPUT), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, sample_id_all: 1
dummy:u: type: 1 (software), size: 136, config: 0x9 (PERF_COUNT_SW_DUMMY), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|IDENTIFIER, read_format: ID|LOST, inherit: 1, exclude_kernel: 1, exclude_hv: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, ksymbol: 1, bpf_event: 1
root@x1:~# perf trace -e bpf --max-events 5 perf record --off-cpu
0.000 ( 0.015 ms): :2949124/2949124 bpf(cmd: 36, uattr: 0x7ffefc6dbe30, size: 8) = -1 EOPNOTSUPP (Operation not supported)
0.031 ( 0.115 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbb60, size: 148) = 14
0.159 ( 0.037 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbc20, size: 148) = 14
23.868 ( 0.144 ms): perf/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbad0, size: 148) = 14
24.027 ( 0.014 ms): perf/2949124 bpf(uattr: 0x7ffefc6dbc80, size: 80) = 14
root@x1:~#
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240902200515.2103769-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-09-02 13:05:15 -07:00
|
|
|
skel->rodata->has_cpu = 1;
|
2022-05-18 15:47:22 -07:00
|
|
|
}
|
|
|
|
|
2022-08-11 11:54:54 -07:00
|
|
|
if (target->pid) {
|
|
|
|
pid_slist = strlist__new(target->pid, NULL);
|
|
|
|
if (!pid_slist) {
|
|
|
|
pr_err("Failed to create a strlist for pid\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ntasks = 0;
|
|
|
|
strlist__for_each_entry(pos, pid_slist) {
|
|
|
|
char *end_ptr;
|
|
|
|
int pid = strtol(pos->s, &end_ptr, 10);
|
|
|
|
|
|
|
|
if (pid == INT_MIN || pid == INT_MAX ||
|
|
|
|
(*end_ptr != '\0' && *end_ptr != ','))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ntasks++;
|
|
|
|
}
|
2022-08-11 11:54:55 -07:00
|
|
|
|
|
|
|
if (ntasks < MAX_PROC)
|
|
|
|
ntasks = MAX_PROC;
|
|
|
|
|
2022-08-11 11:54:54 -07:00
|
|
|
bpf_map__set_max_entries(skel->maps.task_filter, ntasks);
|
perf record offcpu: Constify control data for BPF
The control knobs set before loading BPF programs should be declared as
'const volatile' so that it can be optimized by the BPF core.
Committer testing:
root@x1:~# perf record --off-cpu
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.807 MB perf.data (5645 samples) ]
root@x1:~# perf evlist
cpu_atom/cycles/P
cpu_core/cycles/P
offcpu-time
dummy:u
root@x1:~# perf evlist -v
cpu_atom/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0xa00000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
cpu_core/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0x400000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
offcpu-time: type: 1 (software), size: 136, config: 0xa (PERF_COUNT_SW_BPF_OUTPUT), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, sample_id_all: 1
dummy:u: type: 1 (software), size: 136, config: 0x9 (PERF_COUNT_SW_DUMMY), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|IDENTIFIER, read_format: ID|LOST, inherit: 1, exclude_kernel: 1, exclude_hv: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, ksymbol: 1, bpf_event: 1
root@x1:~# perf trace -e bpf --max-events 5 perf record --off-cpu
0.000 ( 0.015 ms): :2949124/2949124 bpf(cmd: 36, uattr: 0x7ffefc6dbe30, size: 8) = -1 EOPNOTSUPP (Operation not supported)
0.031 ( 0.115 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbb60, size: 148) = 14
0.159 ( 0.037 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbc20, size: 148) = 14
23.868 ( 0.144 ms): perf/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbad0, size: 148) = 14
24.027 ( 0.014 ms): perf/2949124 bpf(uattr: 0x7ffefc6dbc80, size: 80) = 14
root@x1:~#
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240902200515.2103769-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-09-02 13:05:15 -07:00
|
|
|
skel->rodata->has_task = 1;
|
|
|
|
skel->rodata->uses_tgid = 1;
|
2022-08-11 11:54:54 -07:00
|
|
|
} else if (target__has_task(target)) {
|
2022-05-18 15:47:22 -07:00
|
|
|
ntasks = perf_thread_map__nr(evlist->core.threads);
|
|
|
|
bpf_map__set_max_entries(skel->maps.task_filter, ntasks);
|
perf record offcpu: Constify control data for BPF
The control knobs set before loading BPF programs should be declared as
'const volatile' so that it can be optimized by the BPF core.
Committer testing:
root@x1:~# perf record --off-cpu
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.807 MB perf.data (5645 samples) ]
root@x1:~# perf evlist
cpu_atom/cycles/P
cpu_core/cycles/P
offcpu-time
dummy:u
root@x1:~# perf evlist -v
cpu_atom/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0xa00000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
cpu_core/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0x400000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
offcpu-time: type: 1 (software), size: 136, config: 0xa (PERF_COUNT_SW_BPF_OUTPUT), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, sample_id_all: 1
dummy:u: type: 1 (software), size: 136, config: 0x9 (PERF_COUNT_SW_DUMMY), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|IDENTIFIER, read_format: ID|LOST, inherit: 1, exclude_kernel: 1, exclude_hv: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, ksymbol: 1, bpf_event: 1
root@x1:~# perf trace -e bpf --max-events 5 perf record --off-cpu
0.000 ( 0.015 ms): :2949124/2949124 bpf(cmd: 36, uattr: 0x7ffefc6dbe30, size: 8) = -1 EOPNOTSUPP (Operation not supported)
0.031 ( 0.115 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbb60, size: 148) = 14
0.159 ( 0.037 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbc20, size: 148) = 14
23.868 ( 0.144 ms): perf/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbad0, size: 148) = 14
24.027 ( 0.014 ms): perf/2949124 bpf(uattr: 0x7ffefc6dbc80, size: 80) = 14
root@x1:~#
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240902200515.2103769-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-09-02 13:05:15 -07:00
|
|
|
skel->rodata->has_task = 1;
|
2022-08-11 11:54:55 -07:00
|
|
|
} else if (target__none(target)) {
|
|
|
|
bpf_map__set_max_entries(skel->maps.task_filter, MAX_PROC);
|
perf record offcpu: Constify control data for BPF
The control knobs set before loading BPF programs should be declared as
'const volatile' so that it can be optimized by the BPF core.
Committer testing:
root@x1:~# perf record --off-cpu
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.807 MB perf.data (5645 samples) ]
root@x1:~# perf evlist
cpu_atom/cycles/P
cpu_core/cycles/P
offcpu-time
dummy:u
root@x1:~# perf evlist -v
cpu_atom/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0xa00000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
cpu_core/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0x400000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
offcpu-time: type: 1 (software), size: 136, config: 0xa (PERF_COUNT_SW_BPF_OUTPUT), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, sample_id_all: 1
dummy:u: type: 1 (software), size: 136, config: 0x9 (PERF_COUNT_SW_DUMMY), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|IDENTIFIER, read_format: ID|LOST, inherit: 1, exclude_kernel: 1, exclude_hv: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, ksymbol: 1, bpf_event: 1
root@x1:~# perf trace -e bpf --max-events 5 perf record --off-cpu
0.000 ( 0.015 ms): :2949124/2949124 bpf(cmd: 36, uattr: 0x7ffefc6dbe30, size: 8) = -1 EOPNOTSUPP (Operation not supported)
0.031 ( 0.115 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbb60, size: 148) = 14
0.159 ( 0.037 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbc20, size: 148) = 14
23.868 ( 0.144 ms): perf/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbad0, size: 148) = 14
24.027 ( 0.014 ms): perf/2949124 bpf(uattr: 0x7ffefc6dbc80, size: 80) = 14
root@x1:~#
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240902200515.2103769-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-09-02 13:05:15 -07:00
|
|
|
skel->rodata->has_task = 1;
|
|
|
|
skel->rodata->uses_tgid = 1;
|
2022-05-18 15:47:22 -07:00
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:24 -07:00
|
|
|
if (evlist__first(evlist)->cgrp) {
|
|
|
|
ncgrps = evlist->core.nr_entries - 1; /* excluding a dummy */
|
|
|
|
bpf_map__set_max_entries(skel->maps.cgroup_filter, ncgrps);
|
|
|
|
|
|
|
|
if (!cgroup_is_v2("perf_event"))
|
|
|
|
skel->rodata->uses_cgroup_v1 = true;
|
perf record offcpu: Constify control data for BPF
The control knobs set before loading BPF programs should be declared as
'const volatile' so that it can be optimized by the BPF core.
Committer testing:
root@x1:~# perf record --off-cpu
^C[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.807 MB perf.data (5645 samples) ]
root@x1:~# perf evlist
cpu_atom/cycles/P
cpu_core/cycles/P
offcpu-time
dummy:u
root@x1:~# perf evlist -v
cpu_atom/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0xa00000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
cpu_core/cycles/P: type: 0 (PERF_TYPE_HARDWARE), size: 136, config: 0x400000000, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, precise_ip: 3, sample_id_all: 1
offcpu-time: type: 1 (software), size: 136, config: 0xa (PERF_COUNT_SW_BPF_OUTPUT), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CALLCHAIN|CPU|PERIOD|IDENTIFIER, read_format: ID|LOST, disabled: 1, inherit: 1, freq: 1, sample_id_all: 1
dummy:u: type: 1 (software), size: 136, config: 0x9 (PERF_COUNT_SW_DUMMY), { sample_period, sample_freq }: 1, sample_type: IP|TID|TIME|CPU|IDENTIFIER, read_format: ID|LOST, inherit: 1, exclude_kernel: 1, exclude_hv: 1, mmap: 1, comm: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1, ksymbol: 1, bpf_event: 1
root@x1:~# perf trace -e bpf --max-events 5 perf record --off-cpu
0.000 ( 0.015 ms): :2949124/2949124 bpf(cmd: 36, uattr: 0x7ffefc6dbe30, size: 8) = -1 EOPNOTSUPP (Operation not supported)
0.031 ( 0.115 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbb60, size: 148) = 14
0.159 ( 0.037 ms): :2949124/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbc20, size: 148) = 14
23.868 ( 0.144 ms): perf/2949124 bpf(cmd: PROG_LOAD, uattr: 0x7ffefc6dbad0, size: 148) = 14
24.027 ( 0.014 ms): perf/2949124 bpf(uattr: 0x7ffefc6dbc80, size: 80) = 14
root@x1:~#
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240902200515.2103769-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-09-02 13:05:15 -07:00
|
|
|
skel->rodata->has_cgroup = 1;
|
2022-05-18 15:47:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (opts->record_cgroup) {
|
|
|
|
skel->rodata->needs_cgroup = true;
|
|
|
|
|
|
|
|
if (!cgroup_is_v2("perf_event"))
|
|
|
|
skel->rodata->uses_cgroup_v1 = true;
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:22 -07:00
|
|
|
set_max_rlimit();
|
2022-05-18 15:47:23 -07:00
|
|
|
check_sched_switch_args();
|
2022-05-18 15:47:22 -07:00
|
|
|
|
|
|
|
err = off_cpu_bpf__load(skel);
|
|
|
|
if (err) {
|
|
|
|
pr_err("Failed to load off-cpu skeleton\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target->cpu_list) {
|
|
|
|
u32 cpu;
|
|
|
|
u8 val = 1;
|
|
|
|
|
|
|
|
fd = bpf_map__fd(skel->maps.cpu_filter);
|
|
|
|
|
|
|
|
for (i = 0; i < ncpus; i++) {
|
|
|
|
cpu = perf_cpu_map__cpu(evlist->core.user_requested_cpus, i).cpu;
|
|
|
|
bpf_map_update_elem(fd, &cpu, &val, BPF_ANY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-11 11:54:54 -07:00
|
|
|
if (target->pid) {
|
|
|
|
u8 val = 1;
|
|
|
|
|
|
|
|
fd = bpf_map__fd(skel->maps.task_filter);
|
|
|
|
|
|
|
|
strlist__for_each_entry(pos, pid_slist) {
|
|
|
|
char *end_ptr;
|
|
|
|
u32 tgid;
|
|
|
|
int pid = strtol(pos->s, &end_ptr, 10);
|
|
|
|
|
|
|
|
if (pid == INT_MIN || pid == INT_MAX ||
|
|
|
|
(*end_ptr != '\0' && *end_ptr != ','))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
tgid = pid;
|
|
|
|
bpf_map_update_elem(fd, &tgid, &val, BPF_ANY);
|
|
|
|
}
|
|
|
|
} else if (target__has_task(target)) {
|
2022-05-18 15:47:22 -07:00
|
|
|
u32 pid;
|
|
|
|
u8 val = 1;
|
|
|
|
|
|
|
|
fd = bpf_map__fd(skel->maps.task_filter);
|
|
|
|
|
|
|
|
for (i = 0; i < ntasks; i++) {
|
|
|
|
pid = perf_thread_map__pid(evlist->core.threads, i);
|
|
|
|
bpf_map_update_elem(fd, &pid, &val, BPF_ANY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:24 -07:00
|
|
|
if (evlist__first(evlist)->cgrp) {
|
|
|
|
struct evsel *evsel;
|
|
|
|
u8 val = 1;
|
|
|
|
|
|
|
|
fd = bpf_map__fd(skel->maps.cgroup_filter);
|
|
|
|
|
|
|
|
evlist__for_each_entry(evlist, evsel) {
|
|
|
|
struct cgroup *cgrp = evsel->cgrp;
|
|
|
|
|
|
|
|
if (cgrp == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!cgrp->id && read_cgroup_id(cgrp) < 0) {
|
|
|
|
pr_err("Failed to read cgroup id of %s\n",
|
|
|
|
cgrp->name);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
bpf_map_update_elem(fd, &cgrp->id, &val, BPF_ANY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-30 19:28:07 -07:00
|
|
|
skel->bss->offcpu_thresh_ns = opts->off_cpu_thresh_ns;
|
|
|
|
|
2022-05-18 15:47:21 -07:00
|
|
|
err = off_cpu_bpf__attach(skel);
|
|
|
|
if (err) {
|
|
|
|
pr_err("Failed to attach off-cpu BPF skeleton\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:22 -07:00
|
|
|
if (perf_hooks__set_hook("record_start", off_cpu_start, evlist) ||
|
|
|
|
perf_hooks__set_hook("record_end", off_cpu_finish, evlist)) {
|
2022-05-18 15:47:21 -07:00
|
|
|
pr_err("Failed to attach off-cpu skeleton\n");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
out:
|
|
|
|
off_cpu_bpf__destroy(skel);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int off_cpu_write(struct perf_session *session)
|
|
|
|
{
|
|
|
|
int bytes = 0, size;
|
|
|
|
int fd, stack;
|
2025-04-30 19:28:06 -07:00
|
|
|
u32 raw_size;
|
2022-05-18 15:47:21 -07:00
|
|
|
u64 sample_type, val, sid = 0;
|
|
|
|
struct evsel *evsel;
|
|
|
|
struct perf_data_file *file = &session->data->file;
|
|
|
|
struct off_cpu_key prev, key;
|
|
|
|
union off_cpu_data data = {
|
|
|
|
.hdr = {
|
|
|
|
.type = PERF_RECORD_SAMPLE,
|
|
|
|
.misc = PERF_RECORD_MISC_USER,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
u64 tstamp = OFF_CPU_TIMESTAMP;
|
|
|
|
|
|
|
|
skel->bss->enabled = 0;
|
|
|
|
|
|
|
|
evsel = evlist__find_evsel_by_str(session->evlist, OFFCPU_EVENT);
|
|
|
|
if (evsel == NULL) {
|
|
|
|
pr_err("%s evsel not found\n", OFFCPU_EVENT);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sample_type = evsel->core.attr.sample_type;
|
|
|
|
|
2022-06-24 16:13:09 -07:00
|
|
|
if (sample_type & ~OFFCPU_SAMPLE_TYPES) {
|
|
|
|
pr_err("not supported sample type: %llx\n",
|
|
|
|
(unsigned long long)sample_type);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-05-18 15:47:21 -07:00
|
|
|
if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) {
|
|
|
|
if (evsel->core.id)
|
|
|
|
sid = evsel->core.id[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
fd = bpf_map__fd(skel->maps.off_cpu);
|
|
|
|
stack = bpf_map__fd(skel->maps.stacks);
|
|
|
|
memset(&prev, 0, sizeof(prev));
|
|
|
|
|
|
|
|
while (!bpf_map_get_next_key(fd, &prev, &key)) {
|
|
|
|
int n = 1; /* start from perf_event_header */
|
|
|
|
|
|
|
|
bpf_map_lookup_elem(fd, &key, &val);
|
|
|
|
|
2025-04-30 19:28:06 -07:00
|
|
|
/* zero-fill some of the fields, will be overwritten by raw_data when parsing */
|
2022-05-18 15:47:21 -07:00
|
|
|
if (sample_type & PERF_SAMPLE_IDENTIFIER)
|
|
|
|
data.array[n++] = sid;
|
2025-04-30 19:28:06 -07:00
|
|
|
if (sample_type & PERF_SAMPLE_IP)
|
2022-05-18 15:47:21 -07:00
|
|
|
data.array[n++] = 0; /* will be updated */
|
|
|
|
if (sample_type & PERF_SAMPLE_TID)
|
2025-04-30 19:28:06 -07:00
|
|
|
data.array[n++] = 0;
|
2022-05-18 15:47:21 -07:00
|
|
|
if (sample_type & PERF_SAMPLE_TIME)
|
|
|
|
data.array[n++] = tstamp;
|
|
|
|
if (sample_type & PERF_SAMPLE_CPU)
|
|
|
|
data.array[n++] = 0;
|
|
|
|
if (sample_type & PERF_SAMPLE_PERIOD)
|
2025-04-30 19:28:06 -07:00
|
|
|
data.array[n++] = 0;
|
|
|
|
if (sample_type & PERF_SAMPLE_RAW) {
|
|
|
|
/*
|
|
|
|
* [ size ][ data ]
|
|
|
|
* [ data ]
|
|
|
|
* [ data ]
|
|
|
|
* [ data ]
|
|
|
|
* [ data ][ empty]
|
|
|
|
*/
|
|
|
|
int len = 0, i = 0;
|
|
|
|
void *raw_data = (void *)data.array + n * sizeof(u64);
|
|
|
|
|
|
|
|
off_cpu_raw[i++] = (u64)key.pid << 32 | key.tgid;
|
|
|
|
off_cpu_raw[i++] = val;
|
|
|
|
|
|
|
|
/* off_cpu_raw[i] is callchain->nr (updated later) */
|
|
|
|
off_cpu_raw[i + 1] = PERF_CONTEXT_USER;
|
|
|
|
off_cpu_raw[i + 2] = 0;
|
|
|
|
|
|
|
|
bpf_map_lookup_elem(stack, &key.stack_id, &off_cpu_raw[i + 2]);
|
|
|
|
while (off_cpu_raw[i + 2 + len])
|
2022-05-18 15:47:21 -07:00
|
|
|
len++;
|
|
|
|
|
2025-04-30 19:28:06 -07:00
|
|
|
off_cpu_raw[i] = len + 1;
|
|
|
|
i += len + 2;
|
|
|
|
|
|
|
|
off_cpu_raw[i++] = key.cgroup_id;
|
2022-05-18 15:47:21 -07:00
|
|
|
|
2025-04-30 19:28:06 -07:00
|
|
|
raw_size = i * sizeof(u64) + sizeof(u32); /* 4 bytes for alignment */
|
|
|
|
memcpy(raw_data, &raw_size, sizeof(raw_size));
|
|
|
|
memcpy(raw_data + sizeof(u32), off_cpu_raw, i * sizeof(u64));
|
2022-05-18 15:47:21 -07:00
|
|
|
|
2025-04-30 19:28:06 -07:00
|
|
|
n += i + 1;
|
2022-05-18 15:47:21 -07:00
|
|
|
}
|
2022-05-18 15:47:24 -07:00
|
|
|
if (sample_type & PERF_SAMPLE_CGROUP)
|
|
|
|
data.array[n++] = key.cgroup_id;
|
2022-05-18 15:47:21 -07:00
|
|
|
|
|
|
|
size = n * sizeof(u64);
|
|
|
|
data.hdr.size = size;
|
|
|
|
bytes += size;
|
|
|
|
|
|
|
|
if (perf_data_file__write(file, &data, size) < 0) {
|
|
|
|
pr_err("failed to write perf data, error: %m\n");
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = key;
|
|
|
|
/* increase dummy timestamp to sort later samples */
|
|
|
|
tstamp++;
|
|
|
|
}
|
|
|
|
return bytes;
|
|
|
|
}
|