xref: /linux/tools/perf/util/evsel.c (revision d97b46a64674a267bc41c9e16132ee2a98c3347d)
1 /*
2  * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3  *
4  * Parts came from builtin-{top,stat,record}.c, see those files for further
5  * copyright notes.
6  *
7  * Released under the GPL v2. (and only v2, not any later version)
8  */
9 
10 #include <byteswap.h>
11 #include "asm/bug.h"
12 #include "evsel.h"
13 #include "evlist.h"
14 #include "util.h"
15 #include "cpumap.h"
16 #include "thread_map.h"
17 #include "target.h"
18 
19 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
20 #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
21 
22 int __perf_evsel__sample_size(u64 sample_type)
23 {
24 	u64 mask = sample_type & PERF_SAMPLE_MASK;
25 	int size = 0;
26 	int i;
27 
28 	for (i = 0; i < 64; i++) {
29 		if (mask & (1ULL << i))
30 			size++;
31 	}
32 
33 	size *= sizeof(u64);
34 
35 	return size;
36 }
37 
38 void hists__init(struct hists *hists)
39 {
40 	memset(hists, 0, sizeof(*hists));
41 	hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
42 	hists->entries_in = &hists->entries_in_array[0];
43 	hists->entries_collapsed = RB_ROOT;
44 	hists->entries = RB_ROOT;
45 	pthread_mutex_init(&hists->lock, NULL);
46 }
47 
48 void perf_evsel__init(struct perf_evsel *evsel,
49 		      struct perf_event_attr *attr, int idx)
50 {
51 	evsel->idx	   = idx;
52 	evsel->attr	   = *attr;
53 	INIT_LIST_HEAD(&evsel->node);
54 	hists__init(&evsel->hists);
55 }
56 
57 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
58 {
59 	struct perf_evsel *evsel = zalloc(sizeof(*evsel));
60 
61 	if (evsel != NULL)
62 		perf_evsel__init(evsel, attr, idx);
63 
64 	return evsel;
65 }
66 
67 void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
68 			struct perf_evsel *first)
69 {
70 	struct perf_event_attr *attr = &evsel->attr;
71 	int track = !evsel->idx; /* only the first counter needs these */
72 
73 	attr->disabled = 1;
74 	attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
75 	attr->inherit	    = !opts->no_inherit;
76 	attr->read_format   = PERF_FORMAT_TOTAL_TIME_ENABLED |
77 			      PERF_FORMAT_TOTAL_TIME_RUNNING |
78 			      PERF_FORMAT_ID;
79 
80 	attr->sample_type  |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
81 
82 	/*
83 	 * We default some events to a 1 default interval. But keep
84 	 * it a weak assumption overridable by the user.
85 	 */
86 	if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
87 				     opts->user_interval != ULLONG_MAX)) {
88 		if (opts->freq) {
89 			attr->sample_type	|= PERF_SAMPLE_PERIOD;
90 			attr->freq		= 1;
91 			attr->sample_freq	= opts->freq;
92 		} else {
93 			attr->sample_period = opts->default_interval;
94 		}
95 	}
96 
97 	if (opts->no_samples)
98 		attr->sample_freq = 0;
99 
100 	if (opts->inherit_stat)
101 		attr->inherit_stat = 1;
102 
103 	if (opts->sample_address) {
104 		attr->sample_type	|= PERF_SAMPLE_ADDR;
105 		attr->mmap_data = track;
106 	}
107 
108 	if (opts->call_graph)
109 		attr->sample_type	|= PERF_SAMPLE_CALLCHAIN;
110 
111 	if (perf_target__has_cpu(&opts->target))
112 		attr->sample_type	|= PERF_SAMPLE_CPU;
113 
114 	if (opts->period)
115 		attr->sample_type	|= PERF_SAMPLE_PERIOD;
116 
117 	if (!opts->sample_id_all_missing &&
118 	    (opts->sample_time || !opts->no_inherit ||
119 	     perf_target__has_cpu(&opts->target)))
120 		attr->sample_type	|= PERF_SAMPLE_TIME;
121 
122 	if (opts->raw_samples) {
123 		attr->sample_type	|= PERF_SAMPLE_TIME;
124 		attr->sample_type	|= PERF_SAMPLE_RAW;
125 		attr->sample_type	|= PERF_SAMPLE_CPU;
126 	}
127 
128 	if (opts->no_delay) {
129 		attr->watermark = 0;
130 		attr->wakeup_events = 1;
131 	}
132 	if (opts->branch_stack) {
133 		attr->sample_type	|= PERF_SAMPLE_BRANCH_STACK;
134 		attr->branch_sample_type = opts->branch_stack;
135 	}
136 
137 	attr->mmap = track;
138 	attr->comm = track;
139 
140 	if (perf_target__none(&opts->target) &&
141 	    (!opts->group || evsel == first)) {
142 		attr->enable_on_exec = 1;
143 	}
144 }
145 
146 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
147 {
148 	int cpu, thread;
149 	evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
150 
151 	if (evsel->fd) {
152 		for (cpu = 0; cpu < ncpus; cpu++) {
153 			for (thread = 0; thread < nthreads; thread++) {
154 				FD(evsel, cpu, thread) = -1;
155 			}
156 		}
157 	}
158 
159 	return evsel->fd != NULL ? 0 : -ENOMEM;
160 }
161 
162 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
163 {
164 	evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
165 	if (evsel->sample_id == NULL)
166 		return -ENOMEM;
167 
168 	evsel->id = zalloc(ncpus * nthreads * sizeof(u64));
169 	if (evsel->id == NULL) {
170 		xyarray__delete(evsel->sample_id);
171 		evsel->sample_id = NULL;
172 		return -ENOMEM;
173 	}
174 
175 	return 0;
176 }
177 
178 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
179 {
180 	evsel->counts = zalloc((sizeof(*evsel->counts) +
181 				(ncpus * sizeof(struct perf_counts_values))));
182 	return evsel->counts != NULL ? 0 : -ENOMEM;
183 }
184 
185 void perf_evsel__free_fd(struct perf_evsel *evsel)
186 {
187 	xyarray__delete(evsel->fd);
188 	evsel->fd = NULL;
189 }
190 
191 void perf_evsel__free_id(struct perf_evsel *evsel)
192 {
193 	xyarray__delete(evsel->sample_id);
194 	evsel->sample_id = NULL;
195 	free(evsel->id);
196 	evsel->id = NULL;
197 }
198 
199 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
200 {
201 	int cpu, thread;
202 
203 	for (cpu = 0; cpu < ncpus; cpu++)
204 		for (thread = 0; thread < nthreads; ++thread) {
205 			close(FD(evsel, cpu, thread));
206 			FD(evsel, cpu, thread) = -1;
207 		}
208 }
209 
210 void perf_evsel__exit(struct perf_evsel *evsel)
211 {
212 	assert(list_empty(&evsel->node));
213 	xyarray__delete(evsel->fd);
214 	xyarray__delete(evsel->sample_id);
215 	free(evsel->id);
216 }
217 
218 void perf_evsel__delete(struct perf_evsel *evsel)
219 {
220 	perf_evsel__exit(evsel);
221 	close_cgroup(evsel->cgrp);
222 	free(evsel->name);
223 	free(evsel);
224 }
225 
226 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
227 			      int cpu, int thread, bool scale)
228 {
229 	struct perf_counts_values count;
230 	size_t nv = scale ? 3 : 1;
231 
232 	if (FD(evsel, cpu, thread) < 0)
233 		return -EINVAL;
234 
235 	if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
236 		return -ENOMEM;
237 
238 	if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
239 		return -errno;
240 
241 	if (scale) {
242 		if (count.run == 0)
243 			count.val = 0;
244 		else if (count.run < count.ena)
245 			count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
246 	} else
247 		count.ena = count.run = 0;
248 
249 	evsel->counts->cpu[cpu] = count;
250 	return 0;
251 }
252 
253 int __perf_evsel__read(struct perf_evsel *evsel,
254 		       int ncpus, int nthreads, bool scale)
255 {
256 	size_t nv = scale ? 3 : 1;
257 	int cpu, thread;
258 	struct perf_counts_values *aggr = &evsel->counts->aggr, count;
259 
260 	aggr->val = aggr->ena = aggr->run = 0;
261 
262 	for (cpu = 0; cpu < ncpus; cpu++) {
263 		for (thread = 0; thread < nthreads; thread++) {
264 			if (FD(evsel, cpu, thread) < 0)
265 				continue;
266 
267 			if (readn(FD(evsel, cpu, thread),
268 				  &count, nv * sizeof(u64)) < 0)
269 				return -errno;
270 
271 			aggr->val += count.val;
272 			if (scale) {
273 				aggr->ena += count.ena;
274 				aggr->run += count.run;
275 			}
276 		}
277 	}
278 
279 	evsel->counts->scaled = 0;
280 	if (scale) {
281 		if (aggr->run == 0) {
282 			evsel->counts->scaled = -1;
283 			aggr->val = 0;
284 			return 0;
285 		}
286 
287 		if (aggr->run < aggr->ena) {
288 			evsel->counts->scaled = 1;
289 			aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
290 		}
291 	} else
292 		aggr->ena = aggr->run = 0;
293 
294 	return 0;
295 }
296 
297 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
298 			      struct thread_map *threads, bool group,
299 			      struct xyarray *group_fds)
300 {
301 	int cpu, thread;
302 	unsigned long flags = 0;
303 	int pid = -1, err;
304 
305 	if (evsel->fd == NULL &&
306 	    perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
307 		return -ENOMEM;
308 
309 	if (evsel->cgrp) {
310 		flags = PERF_FLAG_PID_CGROUP;
311 		pid = evsel->cgrp->fd;
312 	}
313 
314 	for (cpu = 0; cpu < cpus->nr; cpu++) {
315 		int group_fd = group_fds ? GROUP_FD(group_fds, cpu) : -1;
316 
317 		for (thread = 0; thread < threads->nr; thread++) {
318 
319 			if (!evsel->cgrp)
320 				pid = threads->map[thread];
321 
322 			FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
323 								     pid,
324 								     cpus->map[cpu],
325 								     group_fd, flags);
326 			if (FD(evsel, cpu, thread) < 0) {
327 				err = -errno;
328 				goto out_close;
329 			}
330 
331 			if (group && group_fd == -1)
332 				group_fd = FD(evsel, cpu, thread);
333 		}
334 	}
335 
336 	return 0;
337 
338 out_close:
339 	do {
340 		while (--thread >= 0) {
341 			close(FD(evsel, cpu, thread));
342 			FD(evsel, cpu, thread) = -1;
343 		}
344 		thread = threads->nr;
345 	} while (--cpu >= 0);
346 	return err;
347 }
348 
349 void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
350 {
351 	if (evsel->fd == NULL)
352 		return;
353 
354 	perf_evsel__close_fd(evsel, ncpus, nthreads);
355 	perf_evsel__free_fd(evsel);
356 	evsel->fd = NULL;
357 }
358 
359 static struct {
360 	struct cpu_map map;
361 	int cpus[1];
362 } empty_cpu_map = {
363 	.map.nr	= 1,
364 	.cpus	= { -1, },
365 };
366 
367 static struct {
368 	struct thread_map map;
369 	int threads[1];
370 } empty_thread_map = {
371 	.map.nr	 = 1,
372 	.threads = { -1, },
373 };
374 
375 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
376 		     struct thread_map *threads, bool group,
377 		     struct xyarray *group_fd)
378 {
379 	if (cpus == NULL) {
380 		/* Work around old compiler warnings about strict aliasing */
381 		cpus = &empty_cpu_map.map;
382 	}
383 
384 	if (threads == NULL)
385 		threads = &empty_thread_map.map;
386 
387 	return __perf_evsel__open(evsel, cpus, threads, group, group_fd);
388 }
389 
390 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
391 			     struct cpu_map *cpus, bool group,
392 			     struct xyarray *group_fd)
393 {
394 	return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group,
395 				  group_fd);
396 }
397 
398 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
399 				struct thread_map *threads, bool group,
400 				struct xyarray *group_fd)
401 {
402 	return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group,
403 				  group_fd);
404 }
405 
406 static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
407 				       struct perf_sample *sample)
408 {
409 	const u64 *array = event->sample.array;
410 
411 	array += ((event->header.size -
412 		   sizeof(event->header)) / sizeof(u64)) - 1;
413 
414 	if (type & PERF_SAMPLE_CPU) {
415 		u32 *p = (u32 *)array;
416 		sample->cpu = *p;
417 		array--;
418 	}
419 
420 	if (type & PERF_SAMPLE_STREAM_ID) {
421 		sample->stream_id = *array;
422 		array--;
423 	}
424 
425 	if (type & PERF_SAMPLE_ID) {
426 		sample->id = *array;
427 		array--;
428 	}
429 
430 	if (type & PERF_SAMPLE_TIME) {
431 		sample->time = *array;
432 		array--;
433 	}
434 
435 	if (type & PERF_SAMPLE_TID) {
436 		u32 *p = (u32 *)array;
437 		sample->pid = p[0];
438 		sample->tid = p[1];
439 	}
440 
441 	return 0;
442 }
443 
444 static bool sample_overlap(const union perf_event *event,
445 			   const void *offset, u64 size)
446 {
447 	const void *base = event;
448 
449 	if (offset + size > base + event->header.size)
450 		return true;
451 
452 	return false;
453 }
454 
455 int perf_event__parse_sample(const union perf_event *event, u64 type,
456 			     int sample_size, bool sample_id_all,
457 			     struct perf_sample *data, bool swapped)
458 {
459 	const u64 *array;
460 
461 	/*
462 	 * used for cross-endian analysis. See git commit 65014ab3
463 	 * for why this goofiness is needed.
464 	 */
465 	union u64_swap u;
466 
467 	memset(data, 0, sizeof(*data));
468 	data->cpu = data->pid = data->tid = -1;
469 	data->stream_id = data->id = data->time = -1ULL;
470 	data->period = 1;
471 
472 	if (event->header.type != PERF_RECORD_SAMPLE) {
473 		if (!sample_id_all)
474 			return 0;
475 		return perf_event__parse_id_sample(event, type, data);
476 	}
477 
478 	array = event->sample.array;
479 
480 	if (sample_size + sizeof(event->header) > event->header.size)
481 		return -EFAULT;
482 
483 	if (type & PERF_SAMPLE_IP) {
484 		data->ip = event->ip.ip;
485 		array++;
486 	}
487 
488 	if (type & PERF_SAMPLE_TID) {
489 		u.val64 = *array;
490 		if (swapped) {
491 			/* undo swap of u64, then swap on individual u32s */
492 			u.val64 = bswap_64(u.val64);
493 			u.val32[0] = bswap_32(u.val32[0]);
494 			u.val32[1] = bswap_32(u.val32[1]);
495 		}
496 
497 		data->pid = u.val32[0];
498 		data->tid = u.val32[1];
499 		array++;
500 	}
501 
502 	if (type & PERF_SAMPLE_TIME) {
503 		data->time = *array;
504 		array++;
505 	}
506 
507 	data->addr = 0;
508 	if (type & PERF_SAMPLE_ADDR) {
509 		data->addr = *array;
510 		array++;
511 	}
512 
513 	data->id = -1ULL;
514 	if (type & PERF_SAMPLE_ID) {
515 		data->id = *array;
516 		array++;
517 	}
518 
519 	if (type & PERF_SAMPLE_STREAM_ID) {
520 		data->stream_id = *array;
521 		array++;
522 	}
523 
524 	if (type & PERF_SAMPLE_CPU) {
525 
526 		u.val64 = *array;
527 		if (swapped) {
528 			/* undo swap of u64, then swap on individual u32s */
529 			u.val64 = bswap_64(u.val64);
530 			u.val32[0] = bswap_32(u.val32[0]);
531 		}
532 
533 		data->cpu = u.val32[0];
534 		array++;
535 	}
536 
537 	if (type & PERF_SAMPLE_PERIOD) {
538 		data->period = *array;
539 		array++;
540 	}
541 
542 	if (type & PERF_SAMPLE_READ) {
543 		fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n");
544 		return -1;
545 	}
546 
547 	if (type & PERF_SAMPLE_CALLCHAIN) {
548 		if (sample_overlap(event, array, sizeof(data->callchain->nr)))
549 			return -EFAULT;
550 
551 		data->callchain = (struct ip_callchain *)array;
552 
553 		if (sample_overlap(event, array, data->callchain->nr))
554 			return -EFAULT;
555 
556 		array += 1 + data->callchain->nr;
557 	}
558 
559 	if (type & PERF_SAMPLE_RAW) {
560 		const u64 *pdata;
561 
562 		u.val64 = *array;
563 		if (WARN_ONCE(swapped,
564 			      "Endianness of raw data not corrected!\n")) {
565 			/* undo swap of u64, then swap on individual u32s */
566 			u.val64 = bswap_64(u.val64);
567 			u.val32[0] = bswap_32(u.val32[0]);
568 			u.val32[1] = bswap_32(u.val32[1]);
569 		}
570 
571 		if (sample_overlap(event, array, sizeof(u32)))
572 			return -EFAULT;
573 
574 		data->raw_size = u.val32[0];
575 		pdata = (void *) array + sizeof(u32);
576 
577 		if (sample_overlap(event, pdata, data->raw_size))
578 			return -EFAULT;
579 
580 		data->raw_data = (void *) pdata;
581 
582 		array = (void *)array + data->raw_size + sizeof(u32);
583 	}
584 
585 	if (type & PERF_SAMPLE_BRANCH_STACK) {
586 		u64 sz;
587 
588 		data->branch_stack = (struct branch_stack *)array;
589 		array++; /* nr */
590 
591 		sz = data->branch_stack->nr * sizeof(struct branch_entry);
592 		sz /= sizeof(u64);
593 		array += sz;
594 	}
595 	return 0;
596 }
597 
598 int perf_event__synthesize_sample(union perf_event *event, u64 type,
599 				  const struct perf_sample *sample,
600 				  bool swapped)
601 {
602 	u64 *array;
603 
604 	/*
605 	 * used for cross-endian analysis. See git commit 65014ab3
606 	 * for why this goofiness is needed.
607 	 */
608 	union u64_swap u;
609 
610 	array = event->sample.array;
611 
612 	if (type & PERF_SAMPLE_IP) {
613 		event->ip.ip = sample->ip;
614 		array++;
615 	}
616 
617 	if (type & PERF_SAMPLE_TID) {
618 		u.val32[0] = sample->pid;
619 		u.val32[1] = sample->tid;
620 		if (swapped) {
621 			/*
622 			 * Inverse of what is done in perf_event__parse_sample
623 			 */
624 			u.val32[0] = bswap_32(u.val32[0]);
625 			u.val32[1] = bswap_32(u.val32[1]);
626 			u.val64 = bswap_64(u.val64);
627 		}
628 
629 		*array = u.val64;
630 		array++;
631 	}
632 
633 	if (type & PERF_SAMPLE_TIME) {
634 		*array = sample->time;
635 		array++;
636 	}
637 
638 	if (type & PERF_SAMPLE_ADDR) {
639 		*array = sample->addr;
640 		array++;
641 	}
642 
643 	if (type & PERF_SAMPLE_ID) {
644 		*array = sample->id;
645 		array++;
646 	}
647 
648 	if (type & PERF_SAMPLE_STREAM_ID) {
649 		*array = sample->stream_id;
650 		array++;
651 	}
652 
653 	if (type & PERF_SAMPLE_CPU) {
654 		u.val32[0] = sample->cpu;
655 		if (swapped) {
656 			/*
657 			 * Inverse of what is done in perf_event__parse_sample
658 			 */
659 			u.val32[0] = bswap_32(u.val32[0]);
660 			u.val64 = bswap_64(u.val64);
661 		}
662 		*array = u.val64;
663 		array++;
664 	}
665 
666 	if (type & PERF_SAMPLE_PERIOD) {
667 		*array = sample->period;
668 		array++;
669 	}
670 
671 	return 0;
672 }
673