aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/perf.c1
-rw-r--r--tools/perf/util/bpf-event.c30
-rw-r--r--tools/perf/util/bpf-event.h7
-rw-r--r--tools/perf/util/env.c88
-rw-r--r--tools/perf/util/env.h19
-rw-r--r--tools/perf/util/session.c1
6 files changed, 144 insertions, 2 deletions
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index a11cb006f968..72df4b6fa36f 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -298,6 +298,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
298 use_pager = 1; 298 use_pager = 1;
299 commit_pager_choice(); 299 commit_pager_choice();
300 300
301 perf_env__init(&perf_env);
301 perf_env__set_cmdline(&perf_env, argc, argv); 302 perf_env__set_cmdline(&perf_env, argc, argv);
302 status = p->fn(argc, argv); 303 status = p->fn(argc, argv);
303 perf_config__exit(); 304 perf_config__exit();
diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
index 5237e8f11997..37ee4e2a728a 100644
--- a/tools/perf/util/bpf-event.c
+++ b/tools/perf/util/bpf-event.c
@@ -10,6 +10,7 @@
10#include "debug.h" 10#include "debug.h"
11#include "symbol.h" 11#include "symbol.h"
12#include "machine.h" 12#include "machine.h"
13#include "env.h"
13#include "session.h" 14#include "session.h"
14 15
15#define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr)) 16#define ptr_to_u64(ptr) ((__u64)(unsigned long)(ptr))
@@ -54,17 +55,28 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
54 struct bpf_event *bpf_event = &event->bpf_event; 55 struct bpf_event *bpf_event = &event->bpf_event;
55 struct bpf_prog_info_linear *info_linear; 56 struct bpf_prog_info_linear *info_linear;
56 struct perf_tool *tool = session->tool; 57 struct perf_tool *tool = session->tool;
58 struct bpf_prog_info_node *info_node;
57 struct bpf_prog_info *info; 59 struct bpf_prog_info *info;
58 struct btf *btf = NULL; 60 struct btf *btf = NULL;
59 bool has_btf = false; 61 bool has_btf = false;
62 struct perf_env *env;
60 u32 sub_prog_cnt, i; 63 u32 sub_prog_cnt, i;
61 int err = 0; 64 int err = 0;
62 u64 arrays; 65 u64 arrays;
63 66
67 /*
68 * for perf-record and perf-report use header.env;
69 * otherwise, use global perf_env.
70 */
71 env = session->data ? &session->header.env : &perf_env;
72
64 arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS; 73 arrays = 1UL << BPF_PROG_INFO_JITED_KSYMS;
65 arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS; 74 arrays |= 1UL << BPF_PROG_INFO_JITED_FUNC_LENS;
66 arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; 75 arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO;
67 arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS; 76 arrays |= 1UL << BPF_PROG_INFO_PROG_TAGS;
77 arrays |= 1UL << BPF_PROG_INFO_JITED_INSNS;
78 arrays |= 1UL << BPF_PROG_INFO_LINE_INFO;
79 arrays |= 1UL << BPF_PROG_INFO_JITED_LINE_INFO;
68 80
69 info_linear = bpf_program__get_prog_info_linear(fd, arrays); 81 info_linear = bpf_program__get_prog_info_linear(fd, arrays);
70 if (IS_ERR_OR_NULL(info_linear)) { 82 if (IS_ERR_OR_NULL(info_linear)) {
@@ -153,8 +165,8 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
153 machine, process); 165 machine, process);
154 } 166 }
155 167
156 /* Synthesize PERF_RECORD_BPF_EVENT */
157 if (!opts->no_bpf_event) { 168 if (!opts->no_bpf_event) {
169 /* Synthesize PERF_RECORD_BPF_EVENT */
158 *bpf_event = (struct bpf_event){ 170 *bpf_event = (struct bpf_event){
159 .header = { 171 .header = {
160 .type = PERF_RECORD_BPF_EVENT, 172 .type = PERF_RECORD_BPF_EVENT,
@@ -167,6 +179,22 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session,
167 memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE); 179 memcpy(bpf_event->tag, info->tag, BPF_TAG_SIZE);
168 memset((void *)event + event->header.size, 0, machine->id_hdr_size); 180 memset((void *)event + event->header.size, 0, machine->id_hdr_size);
169 event->header.size += machine->id_hdr_size; 181 event->header.size += machine->id_hdr_size;
182
183 /* save bpf_prog_info to env */
184 info_node = malloc(sizeof(struct bpf_prog_info_node));
185 if (!info_node) {
186 err = -1;
187 goto out;
188 }
189
190 info_node->info_linear = info_linear;
191 perf_env__insert_bpf_prog_info(env, info_node);
192 info_linear = NULL;
193
194 /*
195 * process after saving bpf_prog_info to env, so that
196 * required information is ready for look up
197 */
170 err = perf_tool__process_synth_event(tool, event, 198 err = perf_tool__process_synth_event(tool, event,
171 machine, process); 199 machine, process);
172 } 200 }
diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h
index 6698683612a7..fad932f7404f 100644
--- a/tools/perf/util/bpf-event.h
+++ b/tools/perf/util/bpf-event.h
@@ -3,14 +3,19 @@
3#define __PERF_BPF_EVENT_H 3#define __PERF_BPF_EVENT_H
4 4
5#include <linux/compiler.h> 5#include <linux/compiler.h>
6#include <linux/rbtree.h>
6#include "event.h" 7#include "event.h"
7 8
8struct machine; 9struct machine;
9union perf_event; 10union perf_event;
10struct perf_sample; 11struct perf_sample;
11struct perf_tool;
12struct record_opts; 12struct record_opts;
13 13
14struct bpf_prog_info_node {
15 struct bpf_prog_info_linear *info_linear;
16 struct rb_node rb_node;
17};
18
14#ifdef HAVE_LIBBPF_SUPPORT 19#ifdef HAVE_LIBBPF_SUPPORT
15int machine__process_bpf_event(struct machine *machine, union perf_event *event, 20int machine__process_bpf_event(struct machine *machine, union perf_event *event,
16 struct perf_sample *sample); 21 struct perf_sample *sample);
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 4c23779e271a..98cd36f0e317 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -3,15 +3,97 @@
3#include "env.h" 3#include "env.h"
4#include "sane_ctype.h" 4#include "sane_ctype.h"
5#include "util.h" 5#include "util.h"
6#include "bpf-event.h"
6#include <errno.h> 7#include <errno.h>
7#include <sys/utsname.h> 8#include <sys/utsname.h>
9#include <bpf/libbpf.h>
8 10
9struct perf_env perf_env; 11struct perf_env perf_env;
10 12
13void perf_env__insert_bpf_prog_info(struct perf_env *env,
14 struct bpf_prog_info_node *info_node)
15{
16 __u32 prog_id = info_node->info_linear->info.id;
17 struct bpf_prog_info_node *node;
18 struct rb_node *parent = NULL;
19 struct rb_node **p;
20
21 down_write(&env->bpf_progs.lock);
22 p = &env->bpf_progs.infos.rb_node;
23
24 while (*p != NULL) {
25 parent = *p;
26 node = rb_entry(parent, struct bpf_prog_info_node, rb_node);
27 if (prog_id < node->info_linear->info.id) {
28 p = &(*p)->rb_left;
29 } else if (prog_id > node->info_linear->info.id) {
30 p = &(*p)->rb_right;
31 } else {
32 pr_debug("duplicated bpf prog info %u\n", prog_id);
33 goto out;
34 }
35 }
36
37 rb_link_node(&info_node->rb_node, parent, p);
38 rb_insert_color(&info_node->rb_node, &env->bpf_progs.infos);
39 env->bpf_progs.infos_cnt++;
40out:
41 up_write(&env->bpf_progs.lock);
42}
43
44struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
45 __u32 prog_id)
46{
47 struct bpf_prog_info_node *node = NULL;
48 struct rb_node *n;
49
50 down_read(&env->bpf_progs.lock);
51 n = env->bpf_progs.infos.rb_node;
52
53 while (n) {
54 node = rb_entry(n, struct bpf_prog_info_node, rb_node);
55 if (prog_id < node->info_linear->info.id)
56 n = n->rb_left;
57 else if (prog_id > node->info_linear->info.id)
58 n = n->rb_right;
59 else
60 break;
61 }
62
63 up_read(&env->bpf_progs.lock);
64 return node;
65}
66
67/* purge data in bpf_progs.infos tree */
68static void perf_env__purge_bpf(struct perf_env *env)
69{
70 struct rb_root *root;
71 struct rb_node *next;
72
73 down_write(&env->bpf_progs.lock);
74
75 root = &env->bpf_progs.infos;
76 next = rb_first(root);
77
78 while (next) {
79 struct bpf_prog_info_node *node;
80
81 node = rb_entry(next, struct bpf_prog_info_node, rb_node);
82 next = rb_next(&node->rb_node);
83 rb_erase(&node->rb_node, root);
84 free(node);
85 }
86
87 env->bpf_progs.infos_cnt = 0;
88
89 up_write(&env->bpf_progs.lock);
90}
91
11void perf_env__exit(struct perf_env *env) 92void perf_env__exit(struct perf_env *env)
12{ 93{
13 int i; 94 int i;
14 95
96 perf_env__purge_bpf(env);
15 zfree(&env->hostname); 97 zfree(&env->hostname);
16 zfree(&env->os_release); 98 zfree(&env->os_release);
17 zfree(&env->version); 99 zfree(&env->version);
@@ -38,6 +120,12 @@ void perf_env__exit(struct perf_env *env)
38 zfree(&env->memory_nodes); 120 zfree(&env->memory_nodes);
39} 121}
40 122
123void perf_env__init(struct perf_env *env)
124{
125 env->bpf_progs.infos = RB_ROOT;
126 init_rwsem(&env->bpf_progs.lock);
127}
128
41int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) 129int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
42{ 130{
43 int i; 131 int i;
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index d01b8355f4ca..24b11c564ba4 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -3,7 +3,9 @@
3#define __PERF_ENV_H 3#define __PERF_ENV_H
4 4
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/rbtree.h>
6#include "cpumap.h" 7#include "cpumap.h"
8#include "rwsem.h"
7 9
8struct cpu_topology_map { 10struct cpu_topology_map {
9 int socket_id; 11 int socket_id;
@@ -64,8 +66,20 @@ struct perf_env {
64 struct memory_node *memory_nodes; 66 struct memory_node *memory_nodes;
65 unsigned long long memory_bsize; 67 unsigned long long memory_bsize;
66 u64 clockid_res_ns; 68 u64 clockid_res_ns;
69
70 /*
71 * bpf_info_lock protects bpf rbtrees. This is needed because the
72 * trees are accessed by different threads in perf-top
73 */
74 struct {
75 struct rw_semaphore lock;
76 struct rb_root infos;
77 u32 infos_cnt;
78 } bpf_progs;
67}; 79};
68 80
81struct bpf_prog_info_node;
82
69extern struct perf_env perf_env; 83extern struct perf_env perf_env;
70 84
71void perf_env__exit(struct perf_env *env); 85void perf_env__exit(struct perf_env *env);
@@ -80,4 +94,9 @@ const char *perf_env__arch(struct perf_env *env);
80const char *perf_env__raw_arch(struct perf_env *env); 94const char *perf_env__raw_arch(struct perf_env *env);
81int perf_env__nr_cpus_avail(struct perf_env *env); 95int perf_env__nr_cpus_avail(struct perf_env *env);
82 96
97void perf_env__init(struct perf_env *env);
98void perf_env__insert_bpf_prog_info(struct perf_env *env,
99 struct bpf_prog_info_node *info_node);
100struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
101 __u32 prog_id);
83#endif /* __PERF_ENV_H */ 102#endif /* __PERF_ENV_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0ec34227bd60..b17f1c9bc965 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -132,6 +132,7 @@ struct perf_session *perf_session__new(struct perf_data *data,
132 ordered_events__init(&session->ordered_events, 132 ordered_events__init(&session->ordered_events,
133 ordered_events__deliver_event, NULL); 133 ordered_events__deliver_event, NULL);
134 134
135 perf_env__init(&session->header.env);
135 if (data) { 136 if (data) {
136 if (perf_data__open(data)) 137 if (perf_data__open(data))
137 goto out_delete; 138 goto out_delete;