diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 6f645fd72fed..4e2d953d4bc5 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1238,6 +1238,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_child; } + if (!opts->no_bpf_event) + bpf_event__add_sb_event(&sb_evlist, &session->header.env); + if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) { pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); opts->no_bpf_event = true; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 3ce8a8db6c1d..1999d6533d12 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1637,6 +1637,9 @@ int cmd_top(int argc, const char **argv) goto out_delete_evlist; } + if (!top.record_opts.no_bpf_event) + bpf_event__add_sb_event(&sb_evlist, &perf_env); + if (perf_evlist__start_sb_thread(sb_evlist, target)) { pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n"); opts->no_bpf_event = true; diff --git a/tools/perf/tests/attr/test-record-C0 b/tools/perf/tests/attr/test-record-C0 index cb0a3138fa54..93818054ae20 100644 --- a/tools/perf/tests/attr/test-record-C0 +++ b/tools/perf/tests/attr/test-record-C0 @@ -1,6 +1,6 @@ [config] command = record -args = -C 0 kill >/dev/null 2>&1 +args = --no-bpf-event -C 0 kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-basic b/tools/perf/tests/attr/test-record-basic index 85a23cf35ba1..b0ca42a5ecc9 100644 --- a/tools/perf/tests/attr/test-record-basic +++ b/tools/perf/tests/attr/test-record-basic @@ -1,6 +1,6 @@ [config] command = record -args = kill >/dev/null 2>&1 +args = --no-bpf-event kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-branch-any b/tools/perf/tests/attr/test-record-branch-any index 81f839e2fad0..1a99b3ce6b89 100644 --- a/tools/perf/tests/attr/test-record-branch-any +++ b/tools/perf/tests/attr/test-record-branch-any @@ -1,6 +1,6 @@ [config] command = record -args = -b kill >/dev/null 2>&1 +args = --no-bpf-event -b kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-branch-filter-any b/tools/perf/tests/attr/test-record-branch-filter-any index 357421f4dfce..709768b508c6 100644 --- a/tools/perf/tests/attr/test-record-branch-filter-any +++ b/tools/perf/tests/attr/test-record-branch-filter-any @@ -1,6 +1,6 @@ [config] command = record -args = -j any kill >/dev/null 2>&1 +args = --no-bpf-event -j any kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_call b/tools/perf/tests/attr/test-record-branch-filter-any_call index dbc55f2ab845..f943221f7825 100644 --- a/tools/perf/tests/attr/test-record-branch-filter-any_call +++ b/tools/perf/tests/attr/test-record-branch-filter-any_call @@ -1,6 +1,6 @@ [config] command = record -args = -j any_call kill >/dev/null 2>&1 +args = --no-bpf-event -j any_call kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_ret b/tools/perf/tests/attr/test-record-branch-filter-any_ret index a0824ff8e131..fd4f5b4154a9 100644 --- a/tools/perf/tests/attr/test-record-branch-filter-any_ret +++ b/tools/perf/tests/attr/test-record-branch-filter-any_ret @@ -1,6 +1,6 @@ [config] command = record -args = -j any_ret kill >/dev/null 2>&1 +args = --no-bpf-event -j any_ret kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-branch-filter-hv b/tools/perf/tests/attr/test-record-branch-filter-hv index f34d6f120181..4e52d685ebe1 100644 --- a/tools/perf/tests/attr/test-record-branch-filter-hv +++ b/tools/perf/tests/attr/test-record-branch-filter-hv @@ -1,6 +1,6 @@ [config] command = record -args = -j hv kill >/dev/null 2>&1 +args = --no-bpf-event -j hv kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-branch-filter-ind_call b/tools/perf/tests/attr/test-record-branch-filter-ind_call index b86a35232248..e08c6ab3796e 100644 --- a/tools/perf/tests/attr/test-record-branch-filter-ind_call +++ b/tools/perf/tests/attr/test-record-branch-filter-ind_call @@ -1,6 +1,6 @@ [config] command = record -args = -j ind_call kill >/dev/null 2>&1 +args = --no-bpf-event -j ind_call kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-branch-filter-k b/tools/perf/tests/attr/test-record-branch-filter-k index d3fbc5e1858a..b4b98f84fc2f 100644 --- a/tools/perf/tests/attr/test-record-branch-filter-k +++ b/tools/perf/tests/attr/test-record-branch-filter-k @@ -1,6 +1,6 @@ [config] command = record -args = -j k kill >/dev/null 2>&1 +args = --no-bpf-event -j k kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-branch-filter-u b/tools/perf/tests/attr/test-record-branch-filter-u index a318f0dda173..fb9610edbb0d 100644 --- a/tools/perf/tests/attr/test-record-branch-filter-u +++ b/tools/perf/tests/attr/test-record-branch-filter-u @@ -1,6 +1,6 @@ [config] command = record -args = -j u kill >/dev/null 2>&1 +args = --no-bpf-event -j u kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-count b/tools/perf/tests/attr/test-record-count index 34f6cc577263..5e9b9019d786 100644 --- a/tools/perf/tests/attr/test-record-count +++ b/tools/perf/tests/attr/test-record-count @@ -1,6 +1,6 @@ [config] command = record -args = -c 123 kill >/dev/null 2>&1 +args = --no-bpf-event -c 123 kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-data b/tools/perf/tests/attr/test-record-data index a9cf2233b0ce..a99bb13149c2 100644 --- a/tools/perf/tests/attr/test-record-data +++ b/tools/perf/tests/attr/test-record-data @@ -1,6 +1,6 @@ [config] command = record -args = -d kill >/dev/null 2>&1 +args = --no-bpf-event -d kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-freq b/tools/perf/tests/attr/test-record-freq index bf4cb459f0d5..89e29f6b2ae0 100644 --- a/tools/perf/tests/attr/test-record-freq +++ b/tools/perf/tests/attr/test-record-freq @@ -1,6 +1,6 @@ [config] command = record -args = -F 100 kill >/dev/null 2>&1 +args = --no-bpf-event -F 100 kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default index 0b216e69760c..5d8234d50845 100644 --- a/tools/perf/tests/attr/test-record-graph-default +++ b/tools/perf/tests/attr/test-record-graph-default @@ -1,6 +1,6 @@ [config] command = record -args = -g kill >/dev/null 2>&1 +args = --no-bpf-event -g kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf index da2fa73bd0a2..ae92061d611d 100644 --- a/tools/perf/tests/attr/test-record-graph-dwarf +++ b/tools/perf/tests/attr/test-record-graph-dwarf @@ -1,6 +1,6 @@ [config] command = record -args = --call-graph dwarf -- kill >/dev/null 2>&1 +args = --no-bpf-event --call-graph dwarf -- kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp index 625d190bb798..5630521c0b0f 100644 --- a/tools/perf/tests/attr/test-record-graph-fp +++ b/tools/perf/tests/attr/test-record-graph-fp @@ -1,6 +1,6 @@ [config] command = record -args = --call-graph fp kill >/dev/null 2>&1 +args = --no-bpf-event --call-graph fp kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group index 618ba1c17474..14ee60fd3f41 100644 --- a/tools/perf/tests/attr/test-record-group +++ b/tools/perf/tests/attr/test-record-group @@ -1,6 +1,6 @@ [config] command = record -args = --group -e cycles,instructions kill >/dev/null 2>&1 +args = --no-bpf-event --group -e cycles,instructions kill >/dev/null 2>&1 ret = 1 [event-1:base-record] diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling index f0729c454f16..300b9f7e6d69 100644 --- a/tools/perf/tests/attr/test-record-group-sampling +++ b/tools/perf/tests/attr/test-record-group-sampling @@ -1,6 +1,6 @@ [config] command = record -args = -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 +args = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 ret = 1 [event-1:base-record] diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1 index 48e8bd12fe46..3ffe246e0228 100644 --- a/tools/perf/tests/attr/test-record-group1 +++ b/tools/perf/tests/attr/test-record-group1 @@ -1,6 +1,6 @@ [config] command = record -args = -e '{cycles,instructions}' kill >/dev/null 2>&1 +args = --no-bpf-event -e '{cycles,instructions}' kill >/dev/null 2>&1 ret = 1 [event-1:base-record] diff --git a/tools/perf/tests/attr/test-record-no-buffering b/tools/perf/tests/attr/test-record-no-buffering index aa3956d8fe20..583dcbb078ba 100644 --- a/tools/perf/tests/attr/test-record-no-buffering +++ b/tools/perf/tests/attr/test-record-no-buffering @@ -1,6 +1,6 @@ [config] command = record -args = --no-buffering kill >/dev/null 2>&1 +args = --no-bpf-event --no-buffering kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-no-inherit b/tools/perf/tests/attr/test-record-no-inherit index 560943decb87..15d1dc162e1c 100644 --- a/tools/perf/tests/attr/test-record-no-inherit +++ b/tools/perf/tests/attr/test-record-no-inherit @@ -1,6 +1,6 @@ [config] command = record -args = -i kill >/dev/null 2>&1 +args = --no-bpf-event -i kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-no-samples b/tools/perf/tests/attr/test-record-no-samples index 8eb73ab639e0..596fbd6d5a2c 100644 --- a/tools/perf/tests/attr/test-record-no-samples +++ b/tools/perf/tests/attr/test-record-no-samples @@ -1,6 +1,6 @@ [config] command = record -args = -n kill >/dev/null 2>&1 +args = --no-bpf-event -n kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-period b/tools/perf/tests/attr/test-record-period index 69bc748f0f27..119101154c5e 100644 --- a/tools/perf/tests/attr/test-record-period +++ b/tools/perf/tests/attr/test-record-period @@ -1,6 +1,6 @@ [config] command = record -args = -c 100 -P kill >/dev/null 2>&1 +args = --no-bpf-event -c 100 -P kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/tests/attr/test-record-raw b/tools/perf/tests/attr/test-record-raw index a188a614a44c..13a5f7860c78 100644 --- a/tools/perf/tests/attr/test-record-raw +++ b/tools/perf/tests/attr/test-record-raw @@ -1,6 +1,6 @@ [config] command = record -args = -R kill >/dev/null 2>&1 +args = --no-bpf-event -R kill >/dev/null 2>&1 ret = 1 [event:base-record] diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 7ffe7db59828..2a8c245ca942 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -13,6 +13,7 @@ #include "env.h" #include "session.h" #include "map.h" +#include "evlist.h" #define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr)) @@ -330,3 +331,102 @@ int perf_event__synthesize_bpf_events(struct perf_session *session, free(event); return err; } + +static void perf_env__add_bpf_info(struct perf_env *env, u32 id) +{ + struct bpf_prog_info_linear *info_linear; + struct bpf_prog_info_node *info_node; + struct btf *btf = NULL; + u64 arrays; + u32 btf_id; + int fd; + + fd = bpf_prog_get_fd_by_id(id); + if (fd < 0) + return; + + arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS; + arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; + arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS; + arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS; + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; + arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO; + + info_linear = bpf_program__get_prog_info_linear(fd, arrays); + if (IS_ERR_OR_NULL(info_linear)) { + pr_debug("%s: failed to get BPF program info. aborting\n", __func__); + goto out; + } + + btf_id = info_linear->info.btf_id; + + info_node = malloc(sizeof(struct bpf_prog_info_node)); + if (info_node) { + info_node->info_linear = info_linear; + perf_env__insert_bpf_prog_info(env, info_node); + } else + free(info_linear); + + if (btf_id == 0) + goto out; + + if (btf__get_from_id(btf_id, &btf)) { + pr_debug("%s: failed to get BTF of id %u, aborting\n", + __func__, btf_id); + goto out; + } + perf_env__fetch_btf(env, btf_id, btf); + +out: + free(btf); + close(fd); +} + +static int bpf_event__sb_cb(union perf_event *event, void *data) +{ + struct perf_env *env = data; + + if (event->header.type != PERF_RECORD_BPF_EVENT) + return -1; + + switch (event->bpf_event.type) { + case PERF_BPF_EVENT_PROG_LOAD: + perf_env__add_bpf_info(env, event->bpf_event.id); + + case PERF_BPF_EVENT_PROG_UNLOAD: + /* + * Do not free bpf_prog_info and btf of the program here, + * as annotation still need them. They will be freed at + * the end of the session. + */ + break; + default: + pr_debug("unexpected bpf_event type of %d\n", + event->bpf_event.type); + break; + } + + return 0; +} + +int bpf_event__add_sb_event(struct perf_evlist **evlist, + struct perf_env *env) +{ + struct perf_event_attr attr = { + .type = PERF_TYPE_SOFTWARE, + .config = PERF_COUNT_SW_DUMMY, + .sample_id_all = 1, + .watermark = 1, + .bpf_event = 1, + .size = sizeof(attr), /* to capture ABI version */ + }; + + /* + * Older gcc versions don't support designated initializers, like above, + * for unnamed union members, such as the following: + */ + attr.wakeup_watermark = 1; + + return perf_evlist__add_sb_event(evlist, &attr, bpf_event__sb_cb, env); +} diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index b9ec394dc7c7..8cb1189149ec 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -4,12 +4,17 @@ #include #include +#include +#include #include "event.h" struct machine; union perf_event; +struct perf_env; struct perf_sample; struct record_opts; +struct evlist; +struct target; struct bpf_prog_info_node { struct bpf_prog_info_linear *info_linear; @@ -31,6 +36,9 @@ int perf_event__synthesize_bpf_events(struct perf_session *session, perf_event__handler_t process, struct machine *machine, struct record_opts *opts); +int bpf_event__add_sb_event(struct perf_evlist **evlist, + struct perf_env *env); + #else static inline int machine__process_bpf_event(struct machine *machine __maybe_unused, union perf_event *event __maybe_unused, @@ -46,5 +54,12 @@ static inline int perf_event__synthesize_bpf_events(struct perf_session *session { return 0; } + +static inline int bpf_event__add_sb_event(struct perf_evlist **evlist __maybe_unused, + struct perf_env *env __maybe_unused) +{ + return 0; +} + #endif // HAVE_LIBBPF_SUPPORT #endif