Blame view

samples/bpf/trace_event_user.c 7.92 KB
25763b3c8   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
2
  /* Copyright (c) 2016 Facebook
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
3
4
5
6
7
8
   */
  #include <stdio.h>
  #include <unistd.h>
  #include <stdlib.h>
  #include <stdbool.h>
  #include <string.h>
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
9
10
11
  #include <linux/perf_event.h>
  #include <linux/bpf.h>
  #include <signal.h>
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
12
13
  #include <errno.h>
  #include <sys/resource.h>
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
14
  #include <bpf/bpf.h>
7cf245a37   Toke Høiland-Jørgensen   samples/bpf: Use ...
15
  #include <bpf/libbpf.h>
205c8ada3   Joe Stringer   samples/bpf: Remo...
16
  #include "perf-sys.h"
28dbf861d   Yonghong Song   samples/bpf: move...
17
  #include "trace_helpers.h"
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
18
19
  
  #define SAMPLE_FREQ 50
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
20
21
22
23
  static int pid;
  /* counts, stackmap */
  static int map_fd[2];
  struct bpf_program *prog;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
24
25
26
27
28
29
30
31
32
  static bool sys_read_seen, sys_write_seen;
  
  static void print_ksym(__u64 addr)
  {
  	struct ksym *sym;
  
  	if (!addr)
  		return;
  	sym = ksym_search(addr);
e67b2c715   Daniel T. Lee   samples, selftest...
33
34
35
36
37
  	if (!sym) {
  		printf("ksym not found. Is kallsyms loaded?
  ");
  		return;
  	}
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
38
  	printf("%s;", sym->name);
bba1b2a89   Daniel T. Lee   samples: bpf: Rep...
39
  	if (!strstr(sym->name, "sys_read"))
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
40
  		sys_read_seen = true;
bba1b2a89   Daniel T. Lee   samples: bpf: Rep...
41
  	else if (!strstr(sym->name, "sys_write"))
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  		sys_write_seen = true;
  }
  
  static void print_addr(__u64 addr)
  {
  	if (!addr)
  		return;
  	printf("%llx;", addr);
  }
  
  #define TASK_COMM_LEN 16
  
  struct key_t {
  	char comm[TASK_COMM_LEN];
  	__u32 kernstack;
  	__u32 userstack;
  };
  
  static void print_stack(struct key_t *key, __u64 count)
  {
  	__u64 ip[PERF_MAX_STACK_DEPTH] = {};
  	static bool warned;
  	int i;
  
  	printf("%3lld %s;", count, key->comm);
d40fc181e   Joe Stringer   samples/bpf: Make...
67
  	if (bpf_map_lookup_elem(map_fd[1], &key->kernstack, ip) != 0) {
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
68
69
70
71
72
73
  		printf("---;");
  	} else {
  		for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--)
  			print_ksym(ip[i]);
  	}
  	printf("-;");
d40fc181e   Joe Stringer   samples/bpf: Make...
74
  	if (bpf_map_lookup_elem(map_fd[1], &key->userstack, ip) != 0) {
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
75
76
77
78
79
  		printf("---;");
  	} else {
  		for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--)
  			print_addr(ip[i]);
  	}
41e9a8046   Teng Qin   samples/bpf: add ...
80
81
82
83
84
  	if (count < 6)
  		printf("\r");
  	else
  		printf("
  ");
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
85
86
87
88
89
90
91
92
93
94
  
  	if (key->kernstack == -EEXIST && !warned) {
  		printf("stackmap collisions seen. Consider increasing size
  ");
  		warned = true;
  	} else if ((int)key->kernstack < 0 && (int)key->userstack < 0) {
  		printf("err stackid %d %d
  ", key->kernstack, key->userstack);
  	}
  }
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
95
  static void err_exit(int err)
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
96
  {
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
97
98
  	kill(pid, SIGKILL);
  	exit(err);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
99
100
101
102
103
104
105
  }
  
  static void print_stacks(void)
  {
  	struct key_t key = {}, next_key;
  	__u64 value;
  	__u32 stackid = 0, next_id;
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
106
  	int error = 1, fd = map_fd[0], stack_map = map_fd[1];
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
107
108
  
  	sys_read_seen = sys_write_seen = false;
d40fc181e   Joe Stringer   samples/bpf: Make...
109
110
  	while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
  		bpf_map_lookup_elem(fd, &next_key, &value);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
111
  		print_stack(&next_key, value);
d40fc181e   Joe Stringer   samples/bpf: Make...
112
  		bpf_map_delete_elem(fd, &next_key);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
113
114
  		key = next_key;
  	}
41e9a8046   Teng Qin   samples/bpf: add ...
115
116
  	printf("
  ");
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
117
118
119
  	if (!sys_read_seen || !sys_write_seen) {
  		printf("BUG kernel stack doesn't contain sys_read() and sys_write()
  ");
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
120
  		err_exit(error);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
121
122
123
  	}
  
  	/* clear stack map */
d40fc181e   Joe Stringer   samples/bpf: Make...
124
125
  	while (bpf_map_get_next_key(stack_map, &stackid, &next_id) == 0) {
  		bpf_map_delete_elem(stack_map, &next_id);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
126
127
128
  		stackid = next_id;
  	}
  }
492b7e894   Taeung Song   samples/bpf: Chec...
129
130
131
132
133
134
135
136
137
138
  static inline int generate_load(void)
  {
  	if (system("dd if=/dev/zero of=/dev/null count=5000k status=none") < 0) {
  		printf("failed to generate some load with dd: %s
  ", strerror(errno));
  		return -1;
  	}
  
  	return 0;
  }
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
139
140
  static void test_perf_event_all_cpu(struct perf_event_attr *attr)
  {
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
141
142
143
144
145
146
147
148
149
  	int nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
  	struct bpf_link **links = calloc(nr_cpus, sizeof(struct bpf_link *));
  	int i, pmu_fd, error = 1;
  
  	if (!links) {
  		printf("malloc of links failed
  ");
  		goto err;
  	}
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
150

81b9cf802   Yonghong Song   bpf: add a test c...
151
152
  	/* system wide perf event, no need to inherit */
  	attr->inherit = 0;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
153
154
  	/* open perf_event on all cpus */
  	for (i = 0; i < nr_cpus; i++) {
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
155
156
  		pmu_fd = sys_perf_event_open(attr, -1, i, -1, 0);
  		if (pmu_fd < 0) {
205c8ada3   Joe Stringer   samples/bpf: Remo...
157
158
  			printf("sys_perf_event_open failed
  ");
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
159
160
  			goto all_cpu_err;
  		}
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
161
  		links[i] = bpf_program__attach_perf_event(prog, pmu_fd);
0efdcefb0   Daniel T. Lee   samples, bpf: Ref...
162
  		if (libbpf_get_error(links[i])) {
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
163
164
165
166
167
168
  			printf("bpf_program__attach_perf_event failed
  ");
  			links[i] = NULL;
  			close(pmu_fd);
  			goto all_cpu_err;
  		}
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
169
  	}
492b7e894   Taeung Song   samples/bpf: Chec...
170

aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
171
  	if (generate_load() < 0)
492b7e894   Taeung Song   samples/bpf: Chec...
172
  		goto all_cpu_err;
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
173

1c47910ef   Alexei Starovoitov   samples/bpf: add ...
174
  	print_stacks();
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
175
  	error = 0;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
176
  all_cpu_err:
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
177
178
179
180
  	for (i--; i >= 0; i--)
  		bpf_link__destroy(links[i]);
  err:
  	free(links);
41e9a8046   Teng Qin   samples/bpf: add ...
181
  	if (error)
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
182
  		err_exit(error);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
183
184
185
186
  }
  
  static void test_perf_event_task(struct perf_event_attr *attr)
  {
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
187
188
  	struct bpf_link *link = NULL;
  	int pmu_fd, error = 1;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
189

81b9cf802   Yonghong Song   bpf: add a test c...
190
191
192
193
  	/* per task perf event, enable inherit so the "dd ..." command can be traced properly.
  	 * Enabling inherit will cause bpf_perf_prog_read_time helper failure.
  	 */
  	attr->inherit = 1;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
194
  	/* open task bound event */
205c8ada3   Joe Stringer   samples/bpf: Remo...
195
  	pmu_fd = sys_perf_event_open(attr, 0, -1, -1, 0);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
196
  	if (pmu_fd < 0) {
205c8ada3   Joe Stringer   samples/bpf: Remo...
197
198
  		printf("sys_perf_event_open failed
  ");
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
199
  		goto err;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
200
  	}
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
201
  	link = bpf_program__attach_perf_event(prog, pmu_fd);
0efdcefb0   Daniel T. Lee   samples, bpf: Ref...
202
  	if (libbpf_get_error(link)) {
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
203
204
205
206
  		printf("bpf_program__attach_perf_event failed
  ");
  		link = NULL;
  		close(pmu_fd);
492b7e894   Taeung Song   samples/bpf: Chec...
207
208
  		goto err;
  	}
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
209
210
211
  
  	if (generate_load() < 0)
  		goto err;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
212
  	print_stacks();
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
213
  	error = 0;
492b7e894   Taeung Song   samples/bpf: Chec...
214
  err:
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
215
  	bpf_link__destroy(link);
492b7e894   Taeung Song   samples/bpf: Chec...
216
  	if (error)
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
217
  		err_exit(error);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
218
219
220
221
222
223
224
225
226
  }
  
  static void test_bpf_perf_event(void)
  {
  	struct perf_event_attr attr_type_hw = {
  		.sample_freq = SAMPLE_FREQ,
  		.freq = 1,
  		.type = PERF_TYPE_HARDWARE,
  		.config = PERF_COUNT_HW_CPU_CYCLES,
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
227
228
229
230
231
232
  	};
  	struct perf_event_attr attr_type_sw = {
  		.sample_freq = SAMPLE_FREQ,
  		.freq = 1,
  		.type = PERF_TYPE_SOFTWARE,
  		.config = PERF_COUNT_SW_CPU_CLOCK,
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
233
  	};
41e9a8046   Teng Qin   samples/bpf: add ...
234
235
236
237
238
239
240
241
  	struct perf_event_attr attr_hw_cache_l1d = {
  		.sample_freq = SAMPLE_FREQ,
  		.freq = 1,
  		.type = PERF_TYPE_HW_CACHE,
  		.config =
  			PERF_COUNT_HW_CACHE_L1D |
  			(PERF_COUNT_HW_CACHE_OP_READ << 8) |
  			(PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
41e9a8046   Teng Qin   samples/bpf: add ...
242
243
244
245
246
247
248
249
250
  	};
  	struct perf_event_attr attr_hw_cache_branch_miss = {
  		.sample_freq = SAMPLE_FREQ,
  		.freq = 1,
  		.type = PERF_TYPE_HW_CACHE,
  		.config =
  			PERF_COUNT_HW_CACHE_BPU |
  			(PERF_COUNT_HW_CACHE_OP_READ << 8) |
  			(PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
41e9a8046   Teng Qin   samples/bpf: add ...
251
252
253
254
255
256
257
  	};
  	struct perf_event_attr attr_type_raw = {
  		.sample_freq = SAMPLE_FREQ,
  		.freq = 1,
  		.type = PERF_TYPE_RAW,
  		/* Intel Instruction Retired */
  		.config = 0xc0,
41e9a8046   Teng Qin   samples/bpf: add ...
258
  	};
12fe12253   Teng Qin   samples/bpf: add ...
259
260
261
262
263
264
265
266
267
268
269
  	struct perf_event_attr attr_type_raw_lock_load = {
  		.sample_freq = SAMPLE_FREQ,
  		.freq = 1,
  		.type = PERF_TYPE_RAW,
  		/* Intel MEM_UOPS_RETIRED.LOCK_LOADS */
  		.config = 0x21d0,
  		/* Request to record lock address from PEBS */
  		.sample_type = PERF_SAMPLE_ADDR,
  		/* Record address value requires precise event */
  		.precise_ip = 2,
  	};
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
270

41e9a8046   Teng Qin   samples/bpf: add ...
271
272
  	printf("Test HW_CPU_CYCLES
  ");
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
273
274
  	test_perf_event_all_cpu(&attr_type_hw);
  	test_perf_event_task(&attr_type_hw);
41e9a8046   Teng Qin   samples/bpf: add ...
275
276
277
  
  	printf("Test SW_CPU_CLOCK
  ");
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
278
279
  	test_perf_event_all_cpu(&attr_type_sw);
  	test_perf_event_task(&attr_type_sw);
41e9a8046   Teng Qin   samples/bpf: add ...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  
  	printf("Test HW_CACHE_L1D
  ");
  	test_perf_event_all_cpu(&attr_hw_cache_l1d);
  	test_perf_event_task(&attr_hw_cache_l1d);
  
  	printf("Test HW_CACHE_BPU
  ");
  	test_perf_event_all_cpu(&attr_hw_cache_branch_miss);
  	test_perf_event_task(&attr_hw_cache_branch_miss);
  
  	printf("Test Instruction Retired
  ");
  	test_perf_event_all_cpu(&attr_type_raw);
  	test_perf_event_task(&attr_type_raw);
12fe12253   Teng Qin   samples/bpf: add ...
295
296
297
298
  	printf("Test Lock Load
  ");
  	test_perf_event_all_cpu(&attr_type_raw_lock_load);
  	test_perf_event_task(&attr_type_raw_lock_load);
41e9a8046   Teng Qin   samples/bpf: add ...
299
300
  	printf("*** PASS ***
  ");
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
301
302
303
304
305
306
  }
  
  
  int main(int argc, char **argv)
  {
  	struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
307
  	struct bpf_object *obj = NULL;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
308
  	char filename[256];
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
309
  	int error = 1;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
310
311
312
  
  	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
  	setrlimit(RLIMIT_MEMLOCK, &r);
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
313
314
  	signal(SIGINT, err_exit);
  	signal(SIGTERM, err_exit);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
315
316
317
318
  
  	if (load_kallsyms()) {
  		printf("failed to process /proc/kallsyms
  ");
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
319
320
321
322
  		goto cleanup;
  	}
  
  	obj = bpf_object__open_file(filename, NULL);
0efdcefb0   Daniel T. Lee   samples, bpf: Ref...
323
  	if (libbpf_get_error(obj)) {
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  		printf("opening BPF object file failed
  ");
  		obj = NULL;
  		goto cleanup;
  	}
  
  	prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
  	if (!prog) {
  		printf("finding a prog in obj file failed
  ");
  		goto cleanup;
  	}
  
  	/* load BPF program */
  	if (bpf_object__load(obj)) {
  		printf("loading BPF object file failed
  ");
  		goto cleanup;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
342
  	}
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
343
344
345
346
347
348
  	map_fd[0] = bpf_object__find_map_fd_by_name(obj, "counts");
  	map_fd[1] = bpf_object__find_map_fd_by_name(obj, "stackmap");
  	if (map_fd[0] < 0 || map_fd[1] < 0) {
  		printf("finding a counts/stackmap map in obj file failed
  ");
  		goto cleanup;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
349
  	}
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
350
351
  	pid = fork();
  	if (pid == 0) {
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
352
353
  		read_trace_pipe();
  		return 0;
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
354
355
356
357
  	} else if (pid == -1) {
  		printf("couldn't spawn process
  ");
  		goto cleanup;
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
358
  	}
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
359

1c47910ef   Alexei Starovoitov   samples/bpf: add ...
360
  	test_bpf_perf_event();
aa5e2af66   Daniel T. Lee   samples, bpf: Ref...
361
362
363
364
365
  	error = 0;
  
  cleanup:
  	bpf_object__close(obj);
  	err_exit(error);
1c47910ef   Alexei Starovoitov   samples/bpf: add ...
366
  }