xref: /linux/tools/perf/util/evsel.c (revision 5148fa52a12fa1b97c730b2fe321f2aad7ea041c)
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 (opts->target.system_wide)
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 {
466 		u64 val64;
467 		u32 val32[2];
468 	} u;
469 
470 	memset(data, 0, sizeof(*data));
471 	data->cpu = data->pid = data->tid = -1;
472 	data->stream_id = data->id = data->time = -1ULL;
473 	data->period = 1;
474 
475 	if (event->header.type != PERF_RECORD_SAMPLE) {
476 		if (!sample_id_all)
477 			return 0;
478 		return perf_event__parse_id_sample(event, type, data);
479 	}
480 
481 	array = event->sample.array;
482 
483 	if (sample_size + sizeof(event->header) > event->header.size)
484 		return -EFAULT;
485 
486 	if (type & PERF_SAMPLE_IP) {
487 		data->ip = event->ip.ip;
488 		array++;
489 	}
490 
491 	if (type & PERF_SAMPLE_TID) {
492 		u.val64 = *array;
493 		if (swapped) {
494 			/* undo swap of u64, then swap on individual u32s */
495 			u.val64 = bswap_64(u.val64);
496 			u.val32[0] = bswap_32(u.val32[0]);
497 			u.val32[1] = bswap_32(u.val32[1]);
498 		}
499 
500 		data->pid = u.val32[0];
501 		data->tid = u.val32[1];
502 		array++;
503 	}
504 
505 	if (type & PERF_SAMPLE_TIME) {
506 		data->time = *array;
507 		array++;
508 	}
509 
510 	data->addr = 0;
511 	if (type & PERF_SAMPLE_ADDR) {
512 		data->addr = *array;
513 		array++;
514 	}
515 
516 	data->id = -1ULL;
517 	if (type & PERF_SAMPLE_ID) {
518 		data->id = *array;
519 		array++;
520 	}
521 
522 	if (type & PERF_SAMPLE_STREAM_ID) {
523 		data->stream_id = *array;
524 		array++;
525 	}
526 
527 	if (type & PERF_SAMPLE_CPU) {
528 
529 		u.val64 = *array;
530 		if (swapped) {
531 			/* undo swap of u64, then swap on individual u32s */
532 			u.val64 = bswap_64(u.val64);
533 			u.val32[0] = bswap_32(u.val32[0]);
534 		}
535 
536 		data->cpu = u.val32[0];
537 		array++;
538 	}
539 
540 	if (type & PERF_SAMPLE_PERIOD) {
541 		data->period = *array;
542 		array++;
543 	}
544 
545 	if (type & PERF_SAMPLE_READ) {
546 		fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n");
547 		return -1;
548 	}
549 
550 	if (type & PERF_SAMPLE_CALLCHAIN) {
551 		if (sample_overlap(event, array, sizeof(data->callchain->nr)))
552 			return -EFAULT;
553 
554 		data->callchain = (struct ip_callchain *)array;
555 
556 		if (sample_overlap(event, array, data->callchain->nr))
557 			return -EFAULT;
558 
559 		array += 1 + data->callchain->nr;
560 	}
561 
562 	if (type & PERF_SAMPLE_RAW) {
563 		const u64 *pdata;
564 
565 		u.val64 = *array;
566 		if (WARN_ONCE(swapped,
567 			      "Endianness of raw data not corrected!\n")) {
568 			/* undo swap of u64, then swap on individual u32s */
569 			u.val64 = bswap_64(u.val64);
570 			u.val32[0] = bswap_32(u.val32[0]);
571 			u.val32[1] = bswap_32(u.val32[1]);
572 		}
573 
574 		if (sample_overlap(event, array, sizeof(u32)))
575 			return -EFAULT;
576 
577 		data->raw_size = u.val32[0];
578 		pdata = (void *) array + sizeof(u32);
579 
580 		if (sample_overlap(event, pdata, data->raw_size))
581 			return -EFAULT;
582 
583 		data->raw_data = (void *) pdata;
584 
585 		array = (void *)array + data->raw_size + sizeof(u32);
586 	}
587 
588 	if (type & PERF_SAMPLE_BRANCH_STACK) {
589 		u64 sz;
590 
591 		data->branch_stack = (struct branch_stack *)array;
592 		array++; /* nr */
593 
594 		sz = data->branch_stack->nr * sizeof(struct branch_entry);
595 		sz /= sizeof(u64);
596 		array += sz;
597 	}
598 	return 0;
599 }
600 
601 int perf_event__synthesize_sample(union perf_event *event, u64 type,
602 				  const struct perf_sample *sample,
603 				  bool swapped)
604 {
605 	u64 *array;
606 
607 	/*
608 	 * used for cross-endian analysis. See git commit 65014ab3
609 	 * for why this goofiness is needed.
610 	 */
611 	union {
612 		u64 val64;
613 		u32 val32[2];
614 	} u;
615 
616 	array = event->sample.array;
617 
618 	if (type & PERF_SAMPLE_IP) {
619 		event->ip.ip = sample->ip;
620 		array++;
621 	}
622 
623 	if (type & PERF_SAMPLE_TID) {
624 		u.val32[0] = sample->pid;
625 		u.val32[1] = sample->tid;
626 		if (swapped) {
627 			/*
628 			 * Inverse of what is done in perf_event__parse_sample
629 			 */
630 			u.val32[0] = bswap_32(u.val32[0]);
631 			u.val32[1] = bswap_32(u.val32[1]);
632 			u.val64 = bswap_64(u.val64);
633 		}
634 
635 		*array = u.val64;
636 		array++;
637 	}
638 
639 	if (type & PERF_SAMPLE_TIME) {
640 		*array = sample->time;
641 		array++;
642 	}
643 
644 	if (type & PERF_SAMPLE_ADDR) {
645 		*array = sample->addr;
646 		array++;
647 	}
648 
649 	if (type & PERF_SAMPLE_ID) {
650 		*array = sample->id;
651 		array++;
652 	}
653 
654 	if (type & PERF_SAMPLE_STREAM_ID) {
655 		*array = sample->stream_id;
656 		array++;
657 	}
658 
659 	if (type & PERF_SAMPLE_CPU) {
660 		u.val32[0] = sample->cpu;
661 		if (swapped) {
662 			/*
663 			 * Inverse of what is done in perf_event__parse_sample
664 			 */
665 			u.val32[0] = bswap_32(u.val32[0]);
666 			u.val64 = bswap_64(u.val64);
667 		}
668 		*array = u.val64;
669 		array++;
670 	}
671 
672 	if (type & PERF_SAMPLE_PERIOD) {
673 		*array = sample->period;
674 		array++;
675 	}
676 
677 	return 0;
678 }
679