xref: /openbmc/linux/tools/perf/util/evlist.c (revision 07d6f446)
1f8a95309SArnaldo Carvalho de Melo /*
2f8a95309SArnaldo Carvalho de Melo  * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3f8a95309SArnaldo Carvalho de Melo  *
4f8a95309SArnaldo Carvalho de Melo  * Parts came from builtin-{top,stat,record}.c, see those files for further
5f8a95309SArnaldo Carvalho de Melo  * copyright notes.
6f8a95309SArnaldo Carvalho de Melo  *
7f8a95309SArnaldo Carvalho de Melo  * Released under the GPL v2. (and only v2, not any later version)
8f8a95309SArnaldo Carvalho de Melo  */
9a8c9ae18SArnaldo Carvalho de Melo #include "util.h"
10956fa571SArnaldo Carvalho de Melo #include <api/fs/fs.h>
11a43783aeSArnaldo Carvalho de Melo #include <errno.h>
12fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
135c581041SArnaldo Carvalho de Melo #include <poll.h>
14f8a95309SArnaldo Carvalho de Melo #include "cpumap.h"
15f8a95309SArnaldo Carvalho de Melo #include "thread_map.h"
1612864b31SNamhyung Kim #include "target.h"
17361c99a6SArnaldo Carvalho de Melo #include "evlist.h"
18361c99a6SArnaldo Carvalho de Melo #include "evsel.h"
19e3e1a54fSAdrian Hunter #include "debug.h"
2058db1d6eSArnaldo Carvalho de Melo #include "units.h"
2154cc54deSWang Nan #include "asm/bug.h"
229607ad3aSArnaldo Carvalho de Melo #include <signal.h>
2335b9d88eSArnaldo Carvalho de Melo #include <unistd.h>
24361c99a6SArnaldo Carvalho de Melo 
2550d08e47SArnaldo Carvalho de Melo #include "parse-events.h"
264b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h>
2750d08e47SArnaldo Carvalho de Melo 
2886a5e0c2SArnaldo Carvalho de Melo #include <sys/ioctl.h>
29f8a95309SArnaldo Carvalho de Melo #include <sys/mman.h>
30f8a95309SArnaldo Carvalho de Melo 
3170db7533SArnaldo Carvalho de Melo #include <linux/bitops.h>
3270db7533SArnaldo Carvalho de Melo #include <linux/hash.h>
330389cd1fSArnaldo Carvalho de Melo #include <linux/log2.h>
348dd2a131SJiri Olsa #include <linux/err.h>
3570db7533SArnaldo Carvalho de Melo 
36f8a95309SArnaldo Carvalho de Melo #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
37a91e5431SArnaldo Carvalho de Melo #define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
38f8a95309SArnaldo Carvalho de Melo 
397e2ed097SArnaldo Carvalho de Melo void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
407e2ed097SArnaldo Carvalho de Melo 		       struct thread_map *threads)
41361c99a6SArnaldo Carvalho de Melo {
4270db7533SArnaldo Carvalho de Melo 	int i;
4370db7533SArnaldo Carvalho de Melo 
4470db7533SArnaldo Carvalho de Melo 	for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i)
4570db7533SArnaldo Carvalho de Melo 		INIT_HLIST_HEAD(&evlist->heads[i]);
46361c99a6SArnaldo Carvalho de Melo 	INIT_LIST_HEAD(&evlist->entries);
477e2ed097SArnaldo Carvalho de Melo 	perf_evlist__set_maps(evlist, cpus, threads);
481b85337dSArnaldo Carvalho de Melo 	fdarray__init(&evlist->pollfd, 64);
4935b9d88eSArnaldo Carvalho de Melo 	evlist->workload.pid = -1;
5054cc54deSWang Nan 	evlist->bkw_mmap_state = BKW_MMAP_NOTREADY;
51361c99a6SArnaldo Carvalho de Melo }
52361c99a6SArnaldo Carvalho de Melo 
53334fe7a3SNamhyung Kim struct perf_evlist *perf_evlist__new(void)
54ef1d1af2SArnaldo Carvalho de Melo {
55ef1d1af2SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = zalloc(sizeof(*evlist));
56ef1d1af2SArnaldo Carvalho de Melo 
57ef1d1af2SArnaldo Carvalho de Melo 	if (evlist != NULL)
58334fe7a3SNamhyung Kim 		perf_evlist__init(evlist, NULL, NULL);
59ef1d1af2SArnaldo Carvalho de Melo 
60361c99a6SArnaldo Carvalho de Melo 	return evlist;
61361c99a6SArnaldo Carvalho de Melo }
62361c99a6SArnaldo Carvalho de Melo 
63b22d54b0SJiri Olsa struct perf_evlist *perf_evlist__new_default(void)
64b22d54b0SJiri Olsa {
65b22d54b0SJiri Olsa 	struct perf_evlist *evlist = perf_evlist__new();
66b22d54b0SJiri Olsa 
67b22d54b0SJiri Olsa 	if (evlist && perf_evlist__add_default(evlist)) {
68b22d54b0SJiri Olsa 		perf_evlist__delete(evlist);
69b22d54b0SJiri Olsa 		evlist = NULL;
70b22d54b0SJiri Olsa 	}
71b22d54b0SJiri Olsa 
72b22d54b0SJiri Olsa 	return evlist;
73b22d54b0SJiri Olsa }
74b22d54b0SJiri Olsa 
755bae0250SArnaldo Carvalho de Melo struct perf_evlist *perf_evlist__new_dummy(void)
765bae0250SArnaldo Carvalho de Melo {
775bae0250SArnaldo Carvalho de Melo 	struct perf_evlist *evlist = perf_evlist__new();
785bae0250SArnaldo Carvalho de Melo 
795bae0250SArnaldo Carvalho de Melo 	if (evlist && perf_evlist__add_dummy(evlist)) {
805bae0250SArnaldo Carvalho de Melo 		perf_evlist__delete(evlist);
815bae0250SArnaldo Carvalho de Melo 		evlist = NULL;
825bae0250SArnaldo Carvalho de Melo 	}
835bae0250SArnaldo Carvalho de Melo 
845bae0250SArnaldo Carvalho de Melo 	return evlist;
855bae0250SArnaldo Carvalho de Melo }
865bae0250SArnaldo Carvalho de Melo 
8775562573SAdrian Hunter /**
8875562573SAdrian Hunter  * perf_evlist__set_id_pos - set the positions of event ids.
8975562573SAdrian Hunter  * @evlist: selected event list
9075562573SAdrian Hunter  *
9175562573SAdrian Hunter  * Events with compatible sample types all have the same id_pos
9275562573SAdrian Hunter  * and is_pos.  For convenience, put a copy on evlist.
9375562573SAdrian Hunter  */
9475562573SAdrian Hunter void perf_evlist__set_id_pos(struct perf_evlist *evlist)
9575562573SAdrian Hunter {
9675562573SAdrian Hunter 	struct perf_evsel *first = perf_evlist__first(evlist);
9775562573SAdrian Hunter 
9875562573SAdrian Hunter 	evlist->id_pos = first->id_pos;
9975562573SAdrian Hunter 	evlist->is_pos = first->is_pos;
10075562573SAdrian Hunter }
10175562573SAdrian Hunter 
102733cd2feSAdrian Hunter static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
103733cd2feSAdrian Hunter {
104733cd2feSAdrian Hunter 	struct perf_evsel *evsel;
105733cd2feSAdrian Hunter 
106e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel)
107733cd2feSAdrian Hunter 		perf_evsel__calc_id_pos(evsel);
108733cd2feSAdrian Hunter 
109733cd2feSAdrian Hunter 	perf_evlist__set_id_pos(evlist);
110733cd2feSAdrian Hunter }
111733cd2feSAdrian Hunter 
112361c99a6SArnaldo Carvalho de Melo static void perf_evlist__purge(struct perf_evlist *evlist)
113361c99a6SArnaldo Carvalho de Melo {
114361c99a6SArnaldo Carvalho de Melo 	struct perf_evsel *pos, *n;
115361c99a6SArnaldo Carvalho de Melo 
116e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry_safe(evlist, n, pos) {
117361c99a6SArnaldo Carvalho de Melo 		list_del_init(&pos->node);
118d49e4695SArnaldo Carvalho de Melo 		pos->evlist = NULL;
119361c99a6SArnaldo Carvalho de Melo 		perf_evsel__delete(pos);
120361c99a6SArnaldo Carvalho de Melo 	}
121361c99a6SArnaldo Carvalho de Melo 
122361c99a6SArnaldo Carvalho de Melo 	evlist->nr_entries = 0;
123361c99a6SArnaldo Carvalho de Melo }
124361c99a6SArnaldo Carvalho de Melo 
125ef1d1af2SArnaldo Carvalho de Melo void perf_evlist__exit(struct perf_evlist *evlist)
126ef1d1af2SArnaldo Carvalho de Melo {
12704662523SArnaldo Carvalho de Melo 	zfree(&evlist->mmap);
128b2cb615dSWang Nan 	zfree(&evlist->backward_mmap);
1291b85337dSArnaldo Carvalho de Melo 	fdarray__exit(&evlist->pollfd);
130ef1d1af2SArnaldo Carvalho de Melo }
131ef1d1af2SArnaldo Carvalho de Melo 
132361c99a6SArnaldo Carvalho de Melo void perf_evlist__delete(struct perf_evlist *evlist)
133361c99a6SArnaldo Carvalho de Melo {
1340b04b3dcSArnaldo Carvalho de Melo 	if (evlist == NULL)
1350b04b3dcSArnaldo Carvalho de Melo 		return;
1360b04b3dcSArnaldo Carvalho de Melo 
137983874d1SArnaldo Carvalho de Melo 	perf_evlist__munmap(evlist);
138f26e1c7cSArnaldo Carvalho de Melo 	perf_evlist__close(evlist);
139f30a79b0SJiri Olsa 	cpu_map__put(evlist->cpus);
140186fbb74SJiri Olsa 	thread_map__put(evlist->threads);
14103ad9747SArnaldo Carvalho de Melo 	evlist->cpus = NULL;
14203ad9747SArnaldo Carvalho de Melo 	evlist->threads = NULL;
143361c99a6SArnaldo Carvalho de Melo 	perf_evlist__purge(evlist);
144ef1d1af2SArnaldo Carvalho de Melo 	perf_evlist__exit(evlist);
145361c99a6SArnaldo Carvalho de Melo 	free(evlist);
146361c99a6SArnaldo Carvalho de Melo }
147361c99a6SArnaldo Carvalho de Melo 
148adc0c3e8SAdrian Hunter static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
149adc0c3e8SAdrian Hunter 					  struct perf_evsel *evsel)
150adc0c3e8SAdrian Hunter {
151adc0c3e8SAdrian Hunter 	/*
152adc0c3e8SAdrian Hunter 	 * We already have cpus for evsel (via PMU sysfs) so
153adc0c3e8SAdrian Hunter 	 * keep it, if there's no target cpu list defined.
154adc0c3e8SAdrian Hunter 	 */
155adc0c3e8SAdrian Hunter 	if (!evsel->own_cpus || evlist->has_user_cpus) {
156adc0c3e8SAdrian Hunter 		cpu_map__put(evsel->cpus);
157adc0c3e8SAdrian Hunter 		evsel->cpus = cpu_map__get(evlist->cpus);
158adc0c3e8SAdrian Hunter 	} else if (evsel->cpus != evsel->own_cpus) {
159adc0c3e8SAdrian Hunter 		cpu_map__put(evsel->cpus);
160adc0c3e8SAdrian Hunter 		evsel->cpus = cpu_map__get(evsel->own_cpus);
161adc0c3e8SAdrian Hunter 	}
162adc0c3e8SAdrian Hunter 
163adc0c3e8SAdrian Hunter 	thread_map__put(evsel->threads);
164adc0c3e8SAdrian Hunter 	evsel->threads = thread_map__get(evlist->threads);
165adc0c3e8SAdrian Hunter }
166adc0c3e8SAdrian Hunter 
167adc0c3e8SAdrian Hunter static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
168adc0c3e8SAdrian Hunter {
169adc0c3e8SAdrian Hunter 	struct perf_evsel *evsel;
170adc0c3e8SAdrian Hunter 
171e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel)
172adc0c3e8SAdrian Hunter 		__perf_evlist__propagate_maps(evlist, evsel);
173adc0c3e8SAdrian Hunter }
174adc0c3e8SAdrian Hunter 
175361c99a6SArnaldo Carvalho de Melo void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
176361c99a6SArnaldo Carvalho de Melo {
177d49e4695SArnaldo Carvalho de Melo 	entry->evlist = evlist;
178361c99a6SArnaldo Carvalho de Melo 	list_add_tail(&entry->node, &evlist->entries);
179ef503831SArnaldo Carvalho de Melo 	entry->idx = evlist->nr_entries;
18060b0896cSAdrian Hunter 	entry->tracking = !entry->idx;
181ef503831SArnaldo Carvalho de Melo 
18275562573SAdrian Hunter 	if (!evlist->nr_entries++)
18375562573SAdrian Hunter 		perf_evlist__set_id_pos(evlist);
18444c42d71SAdrian Hunter 
18544c42d71SAdrian Hunter 	__perf_evlist__propagate_maps(evlist, entry);
186361c99a6SArnaldo Carvalho de Melo }
187361c99a6SArnaldo Carvalho de Melo 
1884768230aSAdrian Hunter void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel)
1894768230aSAdrian Hunter {
1904768230aSAdrian Hunter 	evsel->evlist = NULL;
1914768230aSAdrian Hunter 	list_del_init(&evsel->node);
1924768230aSAdrian Hunter 	evlist->nr_entries -= 1;
1934768230aSAdrian Hunter }
1944768230aSAdrian Hunter 
1950529bc1fSJiri Olsa void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
196f114d6efSAdrian Hunter 				   struct list_head *list)
19750d08e47SArnaldo Carvalho de Melo {
198f114d6efSAdrian Hunter 	struct perf_evsel *evsel, *temp;
19975562573SAdrian Hunter 
200e5cadb93SArnaldo Carvalho de Melo 	__evlist__for_each_entry_safe(list, temp, evsel) {
201f114d6efSAdrian Hunter 		list_del_init(&evsel->node);
202f114d6efSAdrian Hunter 		perf_evlist__add(evlist, evsel);
203f114d6efSAdrian Hunter 	}
20450d08e47SArnaldo Carvalho de Melo }
20550d08e47SArnaldo Carvalho de Melo 
20663dab225SArnaldo Carvalho de Melo void __perf_evlist__set_leader(struct list_head *list)
20763dab225SArnaldo Carvalho de Melo {
20863dab225SArnaldo Carvalho de Melo 	struct perf_evsel *evsel, *leader;
20963dab225SArnaldo Carvalho de Melo 
21063dab225SArnaldo Carvalho de Melo 	leader = list_entry(list->next, struct perf_evsel, node);
21197f63e4aSNamhyung Kim 	evsel = list_entry(list->prev, struct perf_evsel, node);
21297f63e4aSNamhyung Kim 
21397f63e4aSNamhyung Kim 	leader->nr_members = evsel->idx - leader->idx + 1;
21463dab225SArnaldo Carvalho de Melo 
215e5cadb93SArnaldo Carvalho de Melo 	__evlist__for_each_entry(list, evsel) {
21663dab225SArnaldo Carvalho de Melo 		evsel->leader = leader;
21763dab225SArnaldo Carvalho de Melo 	}
21863dab225SArnaldo Carvalho de Melo }
21963dab225SArnaldo Carvalho de Melo 
22063dab225SArnaldo Carvalho de Melo void perf_evlist__set_leader(struct perf_evlist *evlist)
2216a4bb04cSJiri Olsa {
22297f63e4aSNamhyung Kim 	if (evlist->nr_entries) {
22397f63e4aSNamhyung Kim 		evlist->nr_groups = evlist->nr_entries > 1 ? 1 : 0;
22463dab225SArnaldo Carvalho de Melo 		__perf_evlist__set_leader(&evlist->entries);
2256a4bb04cSJiri Olsa 	}
22697f63e4aSNamhyung Kim }
2276a4bb04cSJiri Olsa 
22845cf6c33SJiri Olsa void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
2297f8d1adeSArnaldo Carvalho de Melo {
2307f8d1adeSArnaldo Carvalho de Melo 	attr->precise_ip = 3;
2317f8d1adeSArnaldo Carvalho de Melo 
2327f8d1adeSArnaldo Carvalho de Melo 	while (attr->precise_ip != 0) {
2337f8d1adeSArnaldo Carvalho de Melo 		int fd = sys_perf_event_open(attr, 0, -1, -1, 0);
2347f8d1adeSArnaldo Carvalho de Melo 		if (fd != -1) {
2357f8d1adeSArnaldo Carvalho de Melo 			close(fd);
2367f8d1adeSArnaldo Carvalho de Melo 			break;
2377f8d1adeSArnaldo Carvalho de Melo 		}
2387f8d1adeSArnaldo Carvalho de Melo 		--attr->precise_ip;
2397f8d1adeSArnaldo Carvalho de Melo 	}
2407f8d1adeSArnaldo Carvalho de Melo }
2417f8d1adeSArnaldo Carvalho de Melo 
242db918acbSArnaldo Carvalho de Melo int __perf_evlist__add_default(struct perf_evlist *evlist, bool precise)
243361c99a6SArnaldo Carvalho de Melo {
244db918acbSArnaldo Carvalho de Melo 	struct perf_evsel *evsel = perf_evsel__new_cycles(precise);
245361c99a6SArnaldo Carvalho de Melo 
246361c99a6SArnaldo Carvalho de Melo 	if (evsel == NULL)
2477c48dcfdSArnaldo Carvalho de Melo 		return -ENOMEM;
248361c99a6SArnaldo Carvalho de Melo 
249361c99a6SArnaldo Carvalho de Melo 	perf_evlist__add(evlist, evsel);
250361c99a6SArnaldo Carvalho de Melo 	return 0;
251361c99a6SArnaldo Carvalho de Melo }
2525c581041SArnaldo Carvalho de Melo 
2535bae0250SArnaldo Carvalho de Melo int perf_evlist__add_dummy(struct perf_evlist *evlist)
2545bae0250SArnaldo Carvalho de Melo {
2555bae0250SArnaldo Carvalho de Melo 	struct perf_event_attr attr = {
2565bae0250SArnaldo Carvalho de Melo 		.type	= PERF_TYPE_SOFTWARE,
2575bae0250SArnaldo Carvalho de Melo 		.config = PERF_COUNT_SW_DUMMY,
2585bae0250SArnaldo Carvalho de Melo 		.size	= sizeof(attr), /* to capture ABI version */
2595bae0250SArnaldo Carvalho de Melo 	};
260640d5175SArnaldo Carvalho de Melo 	struct perf_evsel *evsel = perf_evsel__new_idx(&attr, evlist->nr_entries);
2615bae0250SArnaldo Carvalho de Melo 
2625bae0250SArnaldo Carvalho de Melo 	if (evsel == NULL)
2635bae0250SArnaldo Carvalho de Melo 		return -ENOMEM;
2645bae0250SArnaldo Carvalho de Melo 
2655bae0250SArnaldo Carvalho de Melo 	perf_evlist__add(evlist, evsel);
2665bae0250SArnaldo Carvalho de Melo 	return 0;
2675bae0250SArnaldo Carvalho de Melo }
2685bae0250SArnaldo Carvalho de Melo 
269e60fc847SArnaldo Carvalho de Melo static int perf_evlist__add_attrs(struct perf_evlist *evlist,
27050d08e47SArnaldo Carvalho de Melo 				  struct perf_event_attr *attrs, size_t nr_attrs)
27150d08e47SArnaldo Carvalho de Melo {
27250d08e47SArnaldo Carvalho de Melo 	struct perf_evsel *evsel, *n;
27350d08e47SArnaldo Carvalho de Melo 	LIST_HEAD(head);
27450d08e47SArnaldo Carvalho de Melo 	size_t i;
27550d08e47SArnaldo Carvalho de Melo 
27650d08e47SArnaldo Carvalho de Melo 	for (i = 0; i < nr_attrs; i++) {
277ef503831SArnaldo Carvalho de Melo 		evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i);
27850d08e47SArnaldo Carvalho de Melo 		if (evsel == NULL)
27950d08e47SArnaldo Carvalho de Melo 			goto out_delete_partial_list;
28050d08e47SArnaldo Carvalho de Melo 		list_add_tail(&evsel->node, &head);
28150d08e47SArnaldo Carvalho de Melo 	}
28250d08e47SArnaldo Carvalho de Melo 
283f114d6efSAdrian Hunter 	perf_evlist__splice_list_tail(evlist, &head);
28450d08e47SArnaldo Carvalho de Melo 
28550d08e47SArnaldo Carvalho de Melo 	return 0;
28650d08e47SArnaldo Carvalho de Melo 
28750d08e47SArnaldo Carvalho de Melo out_delete_partial_list:
288e5cadb93SArnaldo Carvalho de Melo 	__evlist__for_each_entry_safe(&head, n, evsel)
28950d08e47SArnaldo Carvalho de Melo 		perf_evsel__delete(evsel);
29050d08e47SArnaldo Carvalho de Melo 	return -1;
29150d08e47SArnaldo Carvalho de Melo }
29250d08e47SArnaldo Carvalho de Melo 
29379695e1bSArnaldo Carvalho de Melo int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
29479695e1bSArnaldo Carvalho de Melo 				     struct perf_event_attr *attrs, size_t nr_attrs)
29579695e1bSArnaldo Carvalho de Melo {
29679695e1bSArnaldo Carvalho de Melo 	size_t i;
29779695e1bSArnaldo Carvalho de Melo 
29879695e1bSArnaldo Carvalho de Melo 	for (i = 0; i < nr_attrs; i++)
29979695e1bSArnaldo Carvalho de Melo 		event_attr_init(attrs + i);
30079695e1bSArnaldo Carvalho de Melo 
30179695e1bSArnaldo Carvalho de Melo 	return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
30279695e1bSArnaldo Carvalho de Melo }
30379695e1bSArnaldo Carvalho de Melo 
304da378962SArnaldo Carvalho de Melo struct perf_evsel *
305ee29be62SArnaldo Carvalho de Melo perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
306ee29be62SArnaldo Carvalho de Melo {
307ee29be62SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
308ee29be62SArnaldo Carvalho de Melo 
309e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
310ee29be62SArnaldo Carvalho de Melo 		if (evsel->attr.type   == PERF_TYPE_TRACEPOINT &&
311ee29be62SArnaldo Carvalho de Melo 		    (int)evsel->attr.config == id)
312ee29be62SArnaldo Carvalho de Melo 			return evsel;
313ee29be62SArnaldo Carvalho de Melo 	}
314ee29be62SArnaldo Carvalho de Melo 
315ee29be62SArnaldo Carvalho de Melo 	return NULL;
316ee29be62SArnaldo Carvalho de Melo }
317ee29be62SArnaldo Carvalho de Melo 
318a2f2804aSDavid Ahern struct perf_evsel *
319a2f2804aSDavid Ahern perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
320a2f2804aSDavid Ahern 				     const char *name)
321a2f2804aSDavid Ahern {
322a2f2804aSDavid Ahern 	struct perf_evsel *evsel;
323a2f2804aSDavid Ahern 
324e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
325a2f2804aSDavid Ahern 		if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
326a2f2804aSDavid Ahern 		    (strcmp(evsel->name, name) == 0))
327a2f2804aSDavid Ahern 			return evsel;
328a2f2804aSDavid Ahern 	}
329a2f2804aSDavid Ahern 
330a2f2804aSDavid Ahern 	return NULL;
331a2f2804aSDavid Ahern }
332a2f2804aSDavid Ahern 
33339876e7dSArnaldo Carvalho de Melo int perf_evlist__add_newtp(struct perf_evlist *evlist,
33439876e7dSArnaldo Carvalho de Melo 			   const char *sys, const char *name, void *handler)
33539876e7dSArnaldo Carvalho de Melo {
336ef503831SArnaldo Carvalho de Melo 	struct perf_evsel *evsel = perf_evsel__newtp(sys, name);
33739876e7dSArnaldo Carvalho de Melo 
3388dd2a131SJiri Olsa 	if (IS_ERR(evsel))
33939876e7dSArnaldo Carvalho de Melo 		return -1;
34039876e7dSArnaldo Carvalho de Melo 
341744a9719SArnaldo Carvalho de Melo 	evsel->handler = handler;
34239876e7dSArnaldo Carvalho de Melo 	perf_evlist__add(evlist, evsel);
34339876e7dSArnaldo Carvalho de Melo 	return 0;
34439876e7dSArnaldo Carvalho de Melo }
34539876e7dSArnaldo Carvalho de Melo 
346bf8e8f4bSAdrian Hunter static int perf_evlist__nr_threads(struct perf_evlist *evlist,
347bf8e8f4bSAdrian Hunter 				   struct perf_evsel *evsel)
348bf8e8f4bSAdrian Hunter {
349bf8e8f4bSAdrian Hunter 	if (evsel->system_wide)
350bf8e8f4bSAdrian Hunter 		return 1;
351bf8e8f4bSAdrian Hunter 	else
352bf8e8f4bSAdrian Hunter 		return thread_map__nr(evlist->threads);
353bf8e8f4bSAdrian Hunter }
354bf8e8f4bSAdrian Hunter 
3554152ab37SArnaldo Carvalho de Melo void perf_evlist__disable(struct perf_evlist *evlist)
3564152ab37SArnaldo Carvalho de Melo {
3574152ab37SArnaldo Carvalho de Melo 	struct perf_evsel *pos;
3584152ab37SArnaldo Carvalho de Melo 
359e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
360395c3070SAdrian Hunter 		if (!perf_evsel__is_group_leader(pos) || !pos->fd)
3613fe4430dSJiri Olsa 			continue;
3623e27c920SJiri Olsa 		perf_evsel__disable(pos);
3634152ab37SArnaldo Carvalho de Melo 	}
3642b56bcfbSArnaldo Carvalho de Melo 
3652b56bcfbSArnaldo Carvalho de Melo 	evlist->enabled = false;
3664152ab37SArnaldo Carvalho de Melo }
3674152ab37SArnaldo Carvalho de Melo 
368764e16a3SDavid Ahern void perf_evlist__enable(struct perf_evlist *evlist)
369764e16a3SDavid Ahern {
370764e16a3SDavid Ahern 	struct perf_evsel *pos;
371764e16a3SDavid Ahern 
372e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
373395c3070SAdrian Hunter 		if (!perf_evsel__is_group_leader(pos) || !pos->fd)
3743fe4430dSJiri Olsa 			continue;
3753e27c920SJiri Olsa 		perf_evsel__enable(pos);
376764e16a3SDavid Ahern 	}
3772b56bcfbSArnaldo Carvalho de Melo 
3782b56bcfbSArnaldo Carvalho de Melo 	evlist->enabled = true;
3792b56bcfbSArnaldo Carvalho de Melo }
3802b56bcfbSArnaldo Carvalho de Melo 
3812b56bcfbSArnaldo Carvalho de Melo void perf_evlist__toggle_enable(struct perf_evlist *evlist)
3822b56bcfbSArnaldo Carvalho de Melo {
3832b56bcfbSArnaldo Carvalho de Melo 	(evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist);
384764e16a3SDavid Ahern }
385764e16a3SDavid Ahern 
3861c65056cSAdrian Hunter static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
3871c65056cSAdrian Hunter 					 struct perf_evsel *evsel, int cpu)
3881c65056cSAdrian Hunter {
38918ef15c6SArnaldo Carvalho de Melo 	int thread;
3901c65056cSAdrian Hunter 	int nr_threads = perf_evlist__nr_threads(evlist, evsel);
3911c65056cSAdrian Hunter 
3921c65056cSAdrian Hunter 	if (!evsel->fd)
3931c65056cSAdrian Hunter 		return -EINVAL;
3941c65056cSAdrian Hunter 
3951c65056cSAdrian Hunter 	for (thread = 0; thread < nr_threads; thread++) {
39618ef15c6SArnaldo Carvalho de Melo 		int err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
3971c65056cSAdrian Hunter 		if (err)
3981c65056cSAdrian Hunter 			return err;
3991c65056cSAdrian Hunter 	}
4001c65056cSAdrian Hunter 	return 0;
4011c65056cSAdrian Hunter }
4021c65056cSAdrian Hunter 
4031c65056cSAdrian Hunter static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
4041c65056cSAdrian Hunter 					    struct perf_evsel *evsel,
4051c65056cSAdrian Hunter 					    int thread)
4061c65056cSAdrian Hunter {
40718ef15c6SArnaldo Carvalho de Melo 	int cpu;
4081c65056cSAdrian Hunter 	int nr_cpus = cpu_map__nr(evlist->cpus);
4091c65056cSAdrian Hunter 
4101c65056cSAdrian Hunter 	if (!evsel->fd)
4111c65056cSAdrian Hunter 		return -EINVAL;
4121c65056cSAdrian Hunter 
4131c65056cSAdrian Hunter 	for (cpu = 0; cpu < nr_cpus; cpu++) {
41418ef15c6SArnaldo Carvalho de Melo 		int err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
4151c65056cSAdrian Hunter 		if (err)
4161c65056cSAdrian Hunter 			return err;
4171c65056cSAdrian Hunter 	}
4181c65056cSAdrian Hunter 	return 0;
4191c65056cSAdrian Hunter }
4201c65056cSAdrian Hunter 
4211c65056cSAdrian Hunter int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
4221c65056cSAdrian Hunter 				  struct perf_evsel *evsel, int idx)
4231c65056cSAdrian Hunter {
4241c65056cSAdrian Hunter 	bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus);
4251c65056cSAdrian Hunter 
4261c65056cSAdrian Hunter 	if (per_cpu_mmaps)
4271c65056cSAdrian Hunter 		return perf_evlist__enable_event_cpu(evlist, evsel, idx);
4281c65056cSAdrian Hunter 	else
4291c65056cSAdrian Hunter 		return perf_evlist__enable_event_thread(evlist, evsel, idx);
4301c65056cSAdrian Hunter }
4311c65056cSAdrian Hunter 
432ad6765ddSArnaldo Carvalho de Melo int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
4335c581041SArnaldo Carvalho de Melo {
434b3a319d5SNamhyung Kim 	int nr_cpus = cpu_map__nr(evlist->cpus);
435b3a319d5SNamhyung Kim 	int nr_threads = thread_map__nr(evlist->threads);
436bf8e8f4bSAdrian Hunter 	int nfds = 0;
437bf8e8f4bSAdrian Hunter 	struct perf_evsel *evsel;
438bf8e8f4bSAdrian Hunter 
439e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
440bf8e8f4bSAdrian Hunter 		if (evsel->system_wide)
441bf8e8f4bSAdrian Hunter 			nfds += nr_cpus;
442bf8e8f4bSAdrian Hunter 		else
443bf8e8f4bSAdrian Hunter 			nfds += nr_cpus * nr_threads;
444bf8e8f4bSAdrian Hunter 	}
445bf8e8f4bSAdrian Hunter 
4461b85337dSArnaldo Carvalho de Melo 	if (fdarray__available_entries(&evlist->pollfd) < nfds &&
4471b85337dSArnaldo Carvalho de Melo 	    fdarray__grow(&evlist->pollfd, nfds) < 0)
448ad6765ddSArnaldo Carvalho de Melo 		return -ENOMEM;
449ad6765ddSArnaldo Carvalho de Melo 
450ad6765ddSArnaldo Carvalho de Melo 	return 0;
4515c581041SArnaldo Carvalho de Melo }
45270082dd9SArnaldo Carvalho de Melo 
4534876075bSWang Nan static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd,
4544876075bSWang Nan 				     struct perf_mmap *map, short revent)
455e4b356b5SArnaldo Carvalho de Melo {
456f3058a1cSWang Nan 	int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP);
457e4b356b5SArnaldo Carvalho de Melo 	/*
458e4b356b5SArnaldo Carvalho de Melo 	 * Save the idx so that when we filter out fds POLLHUP'ed we can
459e4b356b5SArnaldo Carvalho de Melo 	 * close the associated evlist->mmap[] entry.
460e4b356b5SArnaldo Carvalho de Melo 	 */
461e4b356b5SArnaldo Carvalho de Melo 	if (pos >= 0) {
4624876075bSWang Nan 		evlist->pollfd.priv[pos].ptr = map;
463e4b356b5SArnaldo Carvalho de Melo 
464e4b356b5SArnaldo Carvalho de Melo 		fcntl(fd, F_SETFL, O_NONBLOCK);
465e4b356b5SArnaldo Carvalho de Melo 	}
466e4b356b5SArnaldo Carvalho de Melo 
467e4b356b5SArnaldo Carvalho de Melo 	return pos;
468e4b356b5SArnaldo Carvalho de Melo }
469e4b356b5SArnaldo Carvalho de Melo 
470ad6765ddSArnaldo Carvalho de Melo int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
47170082dd9SArnaldo Carvalho de Melo {
4724876075bSWang Nan 	return __perf_evlist__add_pollfd(evlist, fd, NULL, POLLIN);
473e4b356b5SArnaldo Carvalho de Melo }
4741b85337dSArnaldo Carvalho de Melo 
475258e4bfcSWang Nan static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd,
476258e4bfcSWang Nan 					 void *arg __maybe_unused)
477e4b356b5SArnaldo Carvalho de Melo {
4784876075bSWang Nan 	struct perf_mmap *map = fda->priv[fd].ptr;
479e4b356b5SArnaldo Carvalho de Melo 
4804876075bSWang Nan 	if (map)
4814876075bSWang Nan 		perf_mmap__put(map);
48270082dd9SArnaldo Carvalho de Melo }
48370db7533SArnaldo Carvalho de Melo 
4841ddec7f0SArnaldo Carvalho de Melo int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
4851ddec7f0SArnaldo Carvalho de Melo {
486e4b356b5SArnaldo Carvalho de Melo 	return fdarray__filter(&evlist->pollfd, revents_and_mask,
487258e4bfcSWang Nan 			       perf_evlist__munmap_filtered, NULL);
4881ddec7f0SArnaldo Carvalho de Melo }
4891ddec7f0SArnaldo Carvalho de Melo 
490f66a889dSArnaldo Carvalho de Melo int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
491f66a889dSArnaldo Carvalho de Melo {
4921b85337dSArnaldo Carvalho de Melo 	return fdarray__poll(&evlist->pollfd, timeout);
493f66a889dSArnaldo Carvalho de Melo }
494f66a889dSArnaldo Carvalho de Melo 
495a91e5431SArnaldo Carvalho de Melo static void perf_evlist__id_hash(struct perf_evlist *evlist,
496a91e5431SArnaldo Carvalho de Melo 				 struct perf_evsel *evsel,
4973d3b5e95SArnaldo Carvalho de Melo 				 int cpu, int thread, u64 id)
4983d3b5e95SArnaldo Carvalho de Melo {
4993d3b5e95SArnaldo Carvalho de Melo 	int hash;
5003d3b5e95SArnaldo Carvalho de Melo 	struct perf_sample_id *sid = SID(evsel, cpu, thread);
5013d3b5e95SArnaldo Carvalho de Melo 
5023d3b5e95SArnaldo Carvalho de Melo 	sid->id = id;
5033d3b5e95SArnaldo Carvalho de Melo 	sid->evsel = evsel;
5043d3b5e95SArnaldo Carvalho de Melo 	hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS);
5053d3b5e95SArnaldo Carvalho de Melo 	hlist_add_head(&sid->node, &evlist->heads[hash]);
5063d3b5e95SArnaldo Carvalho de Melo }
5073d3b5e95SArnaldo Carvalho de Melo 
508a91e5431SArnaldo Carvalho de Melo void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
509a91e5431SArnaldo Carvalho de Melo 			 int cpu, int thread, u64 id)
510a91e5431SArnaldo Carvalho de Melo {
511a91e5431SArnaldo Carvalho de Melo 	perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
512a91e5431SArnaldo Carvalho de Melo 	evsel->id[evsel->ids++] = id;
513a91e5431SArnaldo Carvalho de Melo }
514a91e5431SArnaldo Carvalho de Melo 
5151c59612dSJiri Olsa int perf_evlist__id_add_fd(struct perf_evlist *evlist,
5163d3b5e95SArnaldo Carvalho de Melo 			   struct perf_evsel *evsel,
517f8a95309SArnaldo Carvalho de Melo 			   int cpu, int thread, int fd)
518f8a95309SArnaldo Carvalho de Melo {
519f8a95309SArnaldo Carvalho de Melo 	u64 read_data[4] = { 0, };
5203d3b5e95SArnaldo Carvalho de Melo 	int id_idx = 1; /* The first entry is the counter value */
521e2b5abe0SJiri Olsa 	u64 id;
522e2b5abe0SJiri Olsa 	int ret;
523e2b5abe0SJiri Olsa 
524e2b5abe0SJiri Olsa 	ret = ioctl(fd, PERF_EVENT_IOC_ID, &id);
525e2b5abe0SJiri Olsa 	if (!ret)
526e2b5abe0SJiri Olsa 		goto add;
527e2b5abe0SJiri Olsa 
528e2b5abe0SJiri Olsa 	if (errno != ENOTTY)
529e2b5abe0SJiri Olsa 		return -1;
530e2b5abe0SJiri Olsa 
531e2b5abe0SJiri Olsa 	/* Legacy way to get event id.. All hail to old kernels! */
532f8a95309SArnaldo Carvalho de Melo 
533c4861afeSJiri Olsa 	/*
534c4861afeSJiri Olsa 	 * This way does not work with group format read, so bail
535c4861afeSJiri Olsa 	 * out in that case.
536c4861afeSJiri Olsa 	 */
537c4861afeSJiri Olsa 	if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP)
538c4861afeSJiri Olsa 		return -1;
539c4861afeSJiri Olsa 
540f8a95309SArnaldo Carvalho de Melo 	if (!(evsel->attr.read_format & PERF_FORMAT_ID) ||
541f8a95309SArnaldo Carvalho de Melo 	    read(fd, &read_data, sizeof(read_data)) == -1)
542f8a95309SArnaldo Carvalho de Melo 		return -1;
543f8a95309SArnaldo Carvalho de Melo 
544f8a95309SArnaldo Carvalho de Melo 	if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
545f8a95309SArnaldo Carvalho de Melo 		++id_idx;
546f8a95309SArnaldo Carvalho de Melo 	if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
547f8a95309SArnaldo Carvalho de Melo 		++id_idx;
548f8a95309SArnaldo Carvalho de Melo 
549e2b5abe0SJiri Olsa 	id = read_data[id_idx];
550e2b5abe0SJiri Olsa 
551e2b5abe0SJiri Olsa  add:
552e2b5abe0SJiri Olsa 	perf_evlist__id_add(evlist, evsel, cpu, thread, id);
553f8a95309SArnaldo Carvalho de Melo 	return 0;
554f8a95309SArnaldo Carvalho de Melo }
555f8a95309SArnaldo Carvalho de Melo 
5563c659eedSAdrian Hunter static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
5573c659eedSAdrian Hunter 				     struct perf_evsel *evsel, int idx, int cpu,
5583c659eedSAdrian Hunter 				     int thread)
5593c659eedSAdrian Hunter {
5603c659eedSAdrian Hunter 	struct perf_sample_id *sid = SID(evsel, cpu, thread);
5613c659eedSAdrian Hunter 	sid->idx = idx;
5623c659eedSAdrian Hunter 	if (evlist->cpus && cpu >= 0)
5633c659eedSAdrian Hunter 		sid->cpu = evlist->cpus->map[cpu];
5643c659eedSAdrian Hunter 	else
5653c659eedSAdrian Hunter 		sid->cpu = -1;
5663c659eedSAdrian Hunter 	if (!evsel->system_wide && evlist->threads && thread >= 0)
567e13798c7SJiri Olsa 		sid->tid = thread_map__pid(evlist->threads, thread);
5683c659eedSAdrian Hunter 	else
5693c659eedSAdrian Hunter 		sid->tid = -1;
5703c659eedSAdrian Hunter }
5713c659eedSAdrian Hunter 
572932a3594SJiri Olsa struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
57370db7533SArnaldo Carvalho de Melo {
57470db7533SArnaldo Carvalho de Melo 	struct hlist_head *head;
57570db7533SArnaldo Carvalho de Melo 	struct perf_sample_id *sid;
57670db7533SArnaldo Carvalho de Melo 	int hash;
57770db7533SArnaldo Carvalho de Melo 
57870db7533SArnaldo Carvalho de Melo 	hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
57970db7533SArnaldo Carvalho de Melo 	head = &evlist->heads[hash];
58070db7533SArnaldo Carvalho de Melo 
581b67bfe0dSSasha Levin 	hlist_for_each_entry(sid, head, node)
58270db7533SArnaldo Carvalho de Melo 		if (sid->id == id)
583932a3594SJiri Olsa 			return sid;
584932a3594SJiri Olsa 
585932a3594SJiri Olsa 	return NULL;
586932a3594SJiri Olsa }
587932a3594SJiri Olsa 
588932a3594SJiri Olsa struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
589932a3594SJiri Olsa {
590932a3594SJiri Olsa 	struct perf_sample_id *sid;
591932a3594SJiri Olsa 
59205169df5SAdrian Hunter 	if (evlist->nr_entries == 1 || !id)
593932a3594SJiri Olsa 		return perf_evlist__first(evlist);
594932a3594SJiri Olsa 
595932a3594SJiri Olsa 	sid = perf_evlist__id2sid(evlist, id);
596932a3594SJiri Olsa 	if (sid)
59770db7533SArnaldo Carvalho de Melo 		return sid->evsel;
59830e68bccSNamhyung Kim 
59930e68bccSNamhyung Kim 	if (!perf_evlist__sample_id_all(evlist))
6000c21f736SArnaldo Carvalho de Melo 		return perf_evlist__first(evlist);
60130e68bccSNamhyung Kim 
60270db7533SArnaldo Carvalho de Melo 	return NULL;
60370db7533SArnaldo Carvalho de Melo }
60404391debSArnaldo Carvalho de Melo 
605dddcf6abSAdrian Hunter struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
606dddcf6abSAdrian Hunter 						u64 id)
607dddcf6abSAdrian Hunter {
608dddcf6abSAdrian Hunter 	struct perf_sample_id *sid;
609dddcf6abSAdrian Hunter 
610dddcf6abSAdrian Hunter 	if (!id)
611dddcf6abSAdrian Hunter 		return NULL;
612dddcf6abSAdrian Hunter 
613dddcf6abSAdrian Hunter 	sid = perf_evlist__id2sid(evlist, id);
614dddcf6abSAdrian Hunter 	if (sid)
615dddcf6abSAdrian Hunter 		return sid->evsel;
616dddcf6abSAdrian Hunter 
617dddcf6abSAdrian Hunter 	return NULL;
618dddcf6abSAdrian Hunter }
619dddcf6abSAdrian Hunter 
62075562573SAdrian Hunter static int perf_evlist__event2id(struct perf_evlist *evlist,
62175562573SAdrian Hunter 				 union perf_event *event, u64 *id)
62275562573SAdrian Hunter {
62375562573SAdrian Hunter 	const u64 *array = event->sample.array;
62475562573SAdrian Hunter 	ssize_t n;
62575562573SAdrian Hunter 
62675562573SAdrian Hunter 	n = (event->header.size - sizeof(event->header)) >> 3;
62775562573SAdrian Hunter 
62875562573SAdrian Hunter 	if (event->header.type == PERF_RECORD_SAMPLE) {
62975562573SAdrian Hunter 		if (evlist->id_pos >= n)
63075562573SAdrian Hunter 			return -1;
63175562573SAdrian Hunter 		*id = array[evlist->id_pos];
63275562573SAdrian Hunter 	} else {
63375562573SAdrian Hunter 		if (evlist->is_pos > n)
63475562573SAdrian Hunter 			return -1;
63575562573SAdrian Hunter 		n -= evlist->is_pos;
63675562573SAdrian Hunter 		*id = array[n];
63775562573SAdrian Hunter 	}
63875562573SAdrian Hunter 	return 0;
63975562573SAdrian Hunter }
64075562573SAdrian Hunter 
6417cb5c5acSJiri Olsa struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
64275562573SAdrian Hunter 					    union perf_event *event)
64375562573SAdrian Hunter {
64498be6966SAdrian Hunter 	struct perf_evsel *first = perf_evlist__first(evlist);
64575562573SAdrian Hunter 	struct hlist_head *head;
64675562573SAdrian Hunter 	struct perf_sample_id *sid;
64775562573SAdrian Hunter 	int hash;
64875562573SAdrian Hunter 	u64 id;
64975562573SAdrian Hunter 
65075562573SAdrian Hunter 	if (evlist->nr_entries == 1)
65198be6966SAdrian Hunter 		return first;
65298be6966SAdrian Hunter 
65398be6966SAdrian Hunter 	if (!first->attr.sample_id_all &&
65498be6966SAdrian Hunter 	    event->header.type != PERF_RECORD_SAMPLE)
65598be6966SAdrian Hunter 		return first;
65675562573SAdrian Hunter 
65775562573SAdrian Hunter 	if (perf_evlist__event2id(evlist, event, &id))
65875562573SAdrian Hunter 		return NULL;
65975562573SAdrian Hunter 
66075562573SAdrian Hunter 	/* Synthesized events have an id of zero */
66175562573SAdrian Hunter 	if (!id)
66298be6966SAdrian Hunter 		return first;
66375562573SAdrian Hunter 
66475562573SAdrian Hunter 	hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
66575562573SAdrian Hunter 	head = &evlist->heads[hash];
66675562573SAdrian Hunter 
66775562573SAdrian Hunter 	hlist_for_each_entry(sid, head, node) {
66875562573SAdrian Hunter 		if (sid->id == id)
66975562573SAdrian Hunter 			return sid->evsel;
67075562573SAdrian Hunter 	}
67175562573SAdrian Hunter 	return NULL;
67275562573SAdrian Hunter }
67375562573SAdrian Hunter 
67465aea233SWang Nan static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
67565aea233SWang Nan {
67665aea233SWang Nan 	int i;
67765aea233SWang Nan 
678078c3386SWang Nan 	if (!evlist->backward_mmap)
679078c3386SWang Nan 		return 0;
680078c3386SWang Nan 
68165aea233SWang Nan 	for (i = 0; i < evlist->nr_mmaps; i++) {
682078c3386SWang Nan 		int fd = evlist->backward_mmap[i].fd;
68365aea233SWang Nan 		int err;
68465aea233SWang Nan 
68565aea233SWang Nan 		if (fd < 0)
68665aea233SWang Nan 			continue;
68765aea233SWang Nan 		err = ioctl(fd, PERF_EVENT_IOC_PAUSE_OUTPUT, value ? 1 : 0);
68865aea233SWang Nan 		if (err)
68965aea233SWang Nan 			return err;
69065aea233SWang Nan 	}
69165aea233SWang Nan 	return 0;
69265aea233SWang Nan }
69365aea233SWang Nan 
694f6cdff83SWang Nan static int perf_evlist__pause(struct perf_evlist *evlist)
69565aea233SWang Nan {
69665aea233SWang Nan 	return perf_evlist__set_paused(evlist, true);
69765aea233SWang Nan }
69865aea233SWang Nan 
699f6cdff83SWang Nan static int perf_evlist__resume(struct perf_evlist *evlist)
70065aea233SWang Nan {
70165aea233SWang Nan 	return perf_evlist__set_paused(evlist, false);
70265aea233SWang Nan }
70365aea233SWang Nan 
7048db6d6b1SWang Nan union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx)
7058db6d6b1SWang Nan {
7068db6d6b1SWang Nan 	struct perf_mmap *md = &evlist->mmap[idx];
7078db6d6b1SWang Nan 
7088db6d6b1SWang Nan 	/*
7098db6d6b1SWang Nan 	 * Check messup is required for forward overwritable ring buffer:
7108db6d6b1SWang Nan 	 * memory pointed by md->prev can be overwritten in this case.
7118db6d6b1SWang Nan 	 * No need for read-write ring buffer: kernel stop outputting when
7128db6d6b1SWang Nan 	 * it hit md->prev (perf_mmap__consume()).
7138db6d6b1SWang Nan 	 */
7148db6d6b1SWang Nan 	return perf_mmap__read_forward(md, evlist->overwrite);
7158db6d6b1SWang Nan }
7168db6d6b1SWang Nan 
7178db6d6b1SWang Nan union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
7188db6d6b1SWang Nan {
7198db6d6b1SWang Nan 	struct perf_mmap *md = &evlist->mmap[idx];
7208db6d6b1SWang Nan 
7218db6d6b1SWang Nan 	/*
7228db6d6b1SWang Nan 	 * No need to check messup for backward ring buffer:
7238db6d6b1SWang Nan 	 * We can always read arbitrary long data from a backward
7248db6d6b1SWang Nan 	 * ring buffer unless we forget to pause it before reading.
7258db6d6b1SWang Nan 	 */
7268db6d6b1SWang Nan 	return perf_mmap__read_backward(md);
7278db6d6b1SWang Nan }
7288db6d6b1SWang Nan 
7295a5ddeb6SWang Nan union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
7305a5ddeb6SWang Nan {
7315a5ddeb6SWang Nan 	return perf_evlist__mmap_read_forward(evlist, idx);
7325a5ddeb6SWang Nan }
7335a5ddeb6SWang Nan 
7348db6d6b1SWang Nan void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
7358db6d6b1SWang Nan {
7368db6d6b1SWang Nan 	perf_mmap__read_catchup(&evlist->mmap[idx]);
7378db6d6b1SWang Nan }
7388db6d6b1SWang Nan 
7398db6d6b1SWang Nan void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
7408db6d6b1SWang Nan {
7418db6d6b1SWang Nan 	perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite);
7428e50d384SZhouyi Zhou }
7438e50d384SZhouyi Zhou 
744a1f72618SWang Nan static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
745f8a95309SArnaldo Carvalho de Melo {
746aece948fSArnaldo Carvalho de Melo 	int i;
747f8a95309SArnaldo Carvalho de Melo 
748b2cb615dSWang Nan 	if (evlist->mmap)
74993edcbd9SAdrian Hunter 		for (i = 0; i < evlist->nr_mmaps; i++)
750a1f72618SWang Nan 			perf_mmap__munmap(&evlist->mmap[i]);
751b2cb615dSWang Nan 
752b2cb615dSWang Nan 	if (evlist->backward_mmap)
753b2cb615dSWang Nan 		for (i = 0; i < evlist->nr_mmaps; i++)
754b2cb615dSWang Nan 			perf_mmap__munmap(&evlist->backward_mmap[i]);
755a1f72618SWang Nan }
756aece948fSArnaldo Carvalho de Melo 
757a1f72618SWang Nan void perf_evlist__munmap(struct perf_evlist *evlist)
758a1f72618SWang Nan {
759a1f72618SWang Nan 	perf_evlist__munmap_nofree(evlist);
76004662523SArnaldo Carvalho de Melo 	zfree(&evlist->mmap);
761b2cb615dSWang Nan 	zfree(&evlist->backward_mmap);
762f8a95309SArnaldo Carvalho de Melo }
763f8a95309SArnaldo Carvalho de Melo 
7648db6d6b1SWang Nan static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
765f8a95309SArnaldo Carvalho de Melo {
766d4c6fb36SWang Nan 	int i;
7678db6d6b1SWang Nan 	struct perf_mmap *map;
768d4c6fb36SWang Nan 
769a14bb7a6SArnaldo Carvalho de Melo 	evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
770ec1e7e43SSukadev Bhattiprolu 	if (cpu_map__empty(evlist->cpus))
771b3a319d5SNamhyung Kim 		evlist->nr_mmaps = thread_map__nr(evlist->threads);
7728db6d6b1SWang Nan 	map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
7738db6d6b1SWang Nan 	if (!map)
7748db6d6b1SWang Nan 		return NULL;
775946ae1d4SWang Nan 
7764738ca30SArnaldo Carvalho de Melo 	for (i = 0; i < evlist->nr_mmaps; i++) {
7778db6d6b1SWang Nan 		map[i].fd = -1;
7784738ca30SArnaldo Carvalho de Melo 		/*
7794738ca30SArnaldo Carvalho de Melo 		 * When the perf_mmap() call is made we grab one refcount, plus
7804738ca30SArnaldo Carvalho de Melo 		 * one extra to let perf_evlist__mmap_consume() get the last
7814738ca30SArnaldo Carvalho de Melo 		 * events after all real references (perf_mmap__get()) are
7824738ca30SArnaldo Carvalho de Melo 		 * dropped.
7834738ca30SArnaldo Carvalho de Melo 		 *
7844738ca30SArnaldo Carvalho de Melo 		 * Each PERF_EVENT_IOC_SET_OUTPUT points to this mmap and
7854738ca30SArnaldo Carvalho de Melo 		 * thus does perf_mmap__get() on it.
7864738ca30SArnaldo Carvalho de Melo 		 */
7874738ca30SArnaldo Carvalho de Melo 		refcount_set(&map[i].refcnt, 0);
7884738ca30SArnaldo Carvalho de Melo 	}
7898db6d6b1SWang Nan 	return map;
790f8a95309SArnaldo Carvalho de Melo }
791f8a95309SArnaldo Carvalho de Melo 
792f3058a1cSWang Nan static bool
793f3058a1cSWang Nan perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
794f3058a1cSWang Nan 			 struct perf_evsel *evsel)
795f3058a1cSWang Nan {
79632a951b4SArnaldo Carvalho de Melo 	if (evsel->attr.write_backward)
797f3058a1cSWang Nan 		return false;
798f3058a1cSWang Nan 	return true;
799f3058a1cSWang Nan }
800f3058a1cSWang Nan 
80104e21314SAdrian Hunter static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
8029f21b815SMark Rutland 				       struct mmap_params *mp, int cpu_idx,
803078c3386SWang Nan 				       int thread, int *_output, int *_output_backward)
804aece948fSArnaldo Carvalho de Melo {
805aece948fSArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
806f3058a1cSWang Nan 	int revent;
8079f21b815SMark Rutland 	int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx);
80804e21314SAdrian Hunter 
809e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
810078c3386SWang Nan 		struct perf_mmap *maps = evlist->mmap;
811078c3386SWang Nan 		int *output = _output;
812bf8e8f4bSAdrian Hunter 		int fd;
8139f21b815SMark Rutland 		int cpu;
814bf8e8f4bSAdrian Hunter 
815078c3386SWang Nan 		if (evsel->attr.write_backward) {
816078c3386SWang Nan 			output = _output_backward;
817078c3386SWang Nan 			maps = evlist->backward_mmap;
818078c3386SWang Nan 
819078c3386SWang Nan 			if (!maps) {
820078c3386SWang Nan 				maps = perf_evlist__alloc_mmap(evlist);
821078c3386SWang Nan 				if (!maps)
822078c3386SWang Nan 					return -1;
823078c3386SWang Nan 				evlist->backward_mmap = maps;
82454cc54deSWang Nan 				if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY)
82554cc54deSWang Nan 					perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
826078c3386SWang Nan 			}
827078c3386SWang Nan 		}
828f3058a1cSWang Nan 
829bf8e8f4bSAdrian Hunter 		if (evsel->system_wide && thread)
830bf8e8f4bSAdrian Hunter 			continue;
831bf8e8f4bSAdrian Hunter 
8329f21b815SMark Rutland 		cpu = cpu_map__idx(evsel->cpus, evlist_cpu);
8339f21b815SMark Rutland 		if (cpu == -1)
8349f21b815SMark Rutland 			continue;
8359f21b815SMark Rutland 
836bf8e8f4bSAdrian Hunter 		fd = FD(evsel, cpu, thread);
83704e21314SAdrian Hunter 
83804e21314SAdrian Hunter 		if (*output == -1) {
83904e21314SAdrian Hunter 			*output = fd;
840078c3386SWang Nan 
841078c3386SWang Nan 			if (perf_mmap__mmap(&maps[idx], mp, *output)  < 0)
84204e21314SAdrian Hunter 				return -1;
84304e21314SAdrian Hunter 		} else {
84404e21314SAdrian Hunter 			if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
84504e21314SAdrian Hunter 				return -1;
84682396986SArnaldo Carvalho de Melo 
847078c3386SWang Nan 			perf_mmap__get(&maps[idx]);
84804e21314SAdrian Hunter 		}
84904e21314SAdrian Hunter 
850f3058a1cSWang Nan 		revent = perf_evlist__should_poll(evlist, evsel) ? POLLIN : 0;
851f3058a1cSWang Nan 
852f90d194aSAdrian Hunter 		/*
853f90d194aSAdrian Hunter 		 * The system_wide flag causes a selected event to be opened
854f90d194aSAdrian Hunter 		 * always without a pid.  Consequently it will never get a
855f90d194aSAdrian Hunter 		 * POLLHUP, but it is used for tracking in combination with
856f90d194aSAdrian Hunter 		 * other events, so it should not need to be polled anyway.
857f90d194aSAdrian Hunter 		 * Therefore don't add it for polling.
858f90d194aSAdrian Hunter 		 */
859f90d194aSAdrian Hunter 		if (!evsel->system_wide &&
860078c3386SWang Nan 		    __perf_evlist__add_pollfd(evlist, fd, &maps[idx], revent) < 0) {
861078c3386SWang Nan 			perf_mmap__put(&maps[idx]);
862ad6765ddSArnaldo Carvalho de Melo 			return -1;
86382396986SArnaldo Carvalho de Melo 		}
864033fa713SArnaldo Carvalho de Melo 
8653c659eedSAdrian Hunter 		if (evsel->attr.read_format & PERF_FORMAT_ID) {
8663c659eedSAdrian Hunter 			if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
8673c659eedSAdrian Hunter 						   fd) < 0)
86804e21314SAdrian Hunter 				return -1;
8693c659eedSAdrian Hunter 			perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
8703c659eedSAdrian Hunter 						 thread);
8713c659eedSAdrian Hunter 		}
87204e21314SAdrian Hunter 	}
87304e21314SAdrian Hunter 
87404e21314SAdrian Hunter 	return 0;
87504e21314SAdrian Hunter }
87604e21314SAdrian Hunter 
877a8a8f3ebSAdrian Hunter static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
878a8a8f3ebSAdrian Hunter 				     struct mmap_params *mp)
87904e21314SAdrian Hunter {
880aece948fSArnaldo Carvalho de Melo 	int cpu, thread;
881b3a319d5SNamhyung Kim 	int nr_cpus = cpu_map__nr(evlist->cpus);
882b3a319d5SNamhyung Kim 	int nr_threads = thread_map__nr(evlist->threads);
883aece948fSArnaldo Carvalho de Melo 
884e3e1a54fSAdrian Hunter 	pr_debug2("perf event ring buffer mmapped per cpu\n");
885b3a319d5SNamhyung Kim 	for (cpu = 0; cpu < nr_cpus; cpu++) {
886aece948fSArnaldo Carvalho de Melo 		int output = -1;
887078c3386SWang Nan 		int output_backward = -1;
888aece948fSArnaldo Carvalho de Melo 
889718c602dSAdrian Hunter 		auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu,
890718c602dSAdrian Hunter 					      true);
891718c602dSAdrian Hunter 
892b3a319d5SNamhyung Kim 		for (thread = 0; thread < nr_threads; thread++) {
893a8a8f3ebSAdrian Hunter 			if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
894078c3386SWang Nan 							thread, &output, &output_backward))
895aece948fSArnaldo Carvalho de Melo 				goto out_unmap;
896aece948fSArnaldo Carvalho de Melo 		}
897aece948fSArnaldo Carvalho de Melo 	}
898aece948fSArnaldo Carvalho de Melo 
899aece948fSArnaldo Carvalho de Melo 	return 0;
900aece948fSArnaldo Carvalho de Melo 
901aece948fSArnaldo Carvalho de Melo out_unmap:
902a1f72618SWang Nan 	perf_evlist__munmap_nofree(evlist);
903aece948fSArnaldo Carvalho de Melo 	return -1;
904aece948fSArnaldo Carvalho de Melo }
905aece948fSArnaldo Carvalho de Melo 
906a8a8f3ebSAdrian Hunter static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
907a8a8f3ebSAdrian Hunter 					struct mmap_params *mp)
908aece948fSArnaldo Carvalho de Melo {
909aece948fSArnaldo Carvalho de Melo 	int thread;
910b3a319d5SNamhyung Kim 	int nr_threads = thread_map__nr(evlist->threads);
911aece948fSArnaldo Carvalho de Melo 
912e3e1a54fSAdrian Hunter 	pr_debug2("perf event ring buffer mmapped per thread\n");
913b3a319d5SNamhyung Kim 	for (thread = 0; thread < nr_threads; thread++) {
914aece948fSArnaldo Carvalho de Melo 		int output = -1;
915078c3386SWang Nan 		int output_backward = -1;
916aece948fSArnaldo Carvalho de Melo 
917718c602dSAdrian Hunter 		auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread,
918718c602dSAdrian Hunter 					      false);
919718c602dSAdrian Hunter 
920a8a8f3ebSAdrian Hunter 		if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
921078c3386SWang Nan 						&output, &output_backward))
922aece948fSArnaldo Carvalho de Melo 			goto out_unmap;
923aece948fSArnaldo Carvalho de Melo 	}
924aece948fSArnaldo Carvalho de Melo 
925aece948fSArnaldo Carvalho de Melo 	return 0;
926aece948fSArnaldo Carvalho de Melo 
927aece948fSArnaldo Carvalho de Melo out_unmap:
928a1f72618SWang Nan 	perf_evlist__munmap_nofree(evlist);
929aece948fSArnaldo Carvalho de Melo 	return -1;
930aece948fSArnaldo Carvalho de Melo }
931aece948fSArnaldo Carvalho de Melo 
932f5e7150cSArnaldo Carvalho de Melo unsigned long perf_event_mlock_kb_in_pages(void)
933994a1f78SJiri Olsa {
934f5e7150cSArnaldo Carvalho de Melo 	unsigned long pages;
9358185e881SArnaldo Carvalho de Melo 	int max;
9368185e881SArnaldo Carvalho de Melo 
9378185e881SArnaldo Carvalho de Melo 	if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
9388185e881SArnaldo Carvalho de Melo 		/*
9398185e881SArnaldo Carvalho de Melo 		 * Pick a once upon a time good value, i.e. things look
9408185e881SArnaldo Carvalho de Melo 		 * strange since we can't read a sysctl value, but lets not
9418185e881SArnaldo Carvalho de Melo 		 * die yet...
9428185e881SArnaldo Carvalho de Melo 		 */
9438185e881SArnaldo Carvalho de Melo 		max = 512;
9448185e881SArnaldo Carvalho de Melo 	} else {
9458185e881SArnaldo Carvalho de Melo 		max -= (page_size / 1024);
9468185e881SArnaldo Carvalho de Melo 	}
9478185e881SArnaldo Carvalho de Melo 
9488185e881SArnaldo Carvalho de Melo 	pages = (max * 1024) / page_size;
9491be300f4SArnaldo Carvalho de Melo 	if (!is_power_of_2(pages))
9501be300f4SArnaldo Carvalho de Melo 		pages = rounddown_pow_of_two(pages);
951f5e7150cSArnaldo Carvalho de Melo 
952f5e7150cSArnaldo Carvalho de Melo 	return pages;
953f5e7150cSArnaldo Carvalho de Melo }
954f5e7150cSArnaldo Carvalho de Melo 
9550c582449SJiri Olsa size_t perf_evlist__mmap_size(unsigned long pages)
956f5e7150cSArnaldo Carvalho de Melo {
957f5e7150cSArnaldo Carvalho de Melo 	if (pages == UINT_MAX)
958f5e7150cSArnaldo Carvalho de Melo 		pages = perf_event_mlock_kb_in_pages();
959f5e7150cSArnaldo Carvalho de Melo 	else if (!is_power_of_2(pages))
960994a1f78SJiri Olsa 		return 0;
961994a1f78SJiri Olsa 
962994a1f78SJiri Olsa 	return (pages + 1) * page_size;
963994a1f78SJiri Olsa }
964994a1f78SJiri Olsa 
96533c2dcfdSDavid Ahern static long parse_pages_arg(const char *str, unsigned long min,
96633c2dcfdSDavid Ahern 			    unsigned long max)
967994a1f78SJiri Olsa {
9682fbe4abeSAdrian Hunter 	unsigned long pages, val;
96927050f53SJiri Olsa 	static struct parse_tag tags[] = {
97027050f53SJiri Olsa 		{ .tag  = 'B', .mult = 1       },
97127050f53SJiri Olsa 		{ .tag  = 'K', .mult = 1 << 10 },
97227050f53SJiri Olsa 		{ .tag  = 'M', .mult = 1 << 20 },
97327050f53SJiri Olsa 		{ .tag  = 'G', .mult = 1 << 30 },
97427050f53SJiri Olsa 		{ .tag  = 0 },
97527050f53SJiri Olsa 	};
976994a1f78SJiri Olsa 
9778973504bSDavid Ahern 	if (str == NULL)
97833c2dcfdSDavid Ahern 		return -EINVAL;
9798973504bSDavid Ahern 
98027050f53SJiri Olsa 	val = parse_tag_value(str, tags);
9812fbe4abeSAdrian Hunter 	if (val != (unsigned long) -1) {
98227050f53SJiri Olsa 		/* we got file size value */
98327050f53SJiri Olsa 		pages = PERF_ALIGN(val, page_size) / page_size;
98427050f53SJiri Olsa 	} else {
98527050f53SJiri Olsa 		/* we got pages count value */
98627050f53SJiri Olsa 		char *eptr;
987994a1f78SJiri Olsa 		pages = strtoul(str, &eptr, 10);
98833c2dcfdSDavid Ahern 		if (*eptr != '\0')
98933c2dcfdSDavid Ahern 			return -EINVAL;
99027050f53SJiri Olsa 	}
991994a1f78SJiri Olsa 
9922bcab6c1SAdrian Hunter 	if (pages == 0 && min == 0) {
99333c2dcfdSDavid Ahern 		/* leave number of pages at 0 */
9941dbfa938SAdrian Hunter 	} else if (!is_power_of_2(pages)) {
9959808143bSJiri Olsa 		char buf[100];
9969808143bSJiri Olsa 
99733c2dcfdSDavid Ahern 		/* round pages up to next power of 2 */
99891529834SArnaldo Carvalho de Melo 		pages = roundup_pow_of_two(pages);
9991dbfa938SAdrian Hunter 		if (!pages)
10001dbfa938SAdrian Hunter 			return -EINVAL;
10019808143bSJiri Olsa 
10029808143bSJiri Olsa 		unit_number__scnprintf(buf, sizeof(buf), pages * page_size);
10039808143bSJiri Olsa 		pr_info("rounding mmap pages size to %s (%lu pages)\n",
10049808143bSJiri Olsa 			buf, pages);
10052fbe4abeSAdrian Hunter 	}
10062fbe4abeSAdrian Hunter 
100733c2dcfdSDavid Ahern 	if (pages > max)
100833c2dcfdSDavid Ahern 		return -EINVAL;
100933c2dcfdSDavid Ahern 
101033c2dcfdSDavid Ahern 	return pages;
101133c2dcfdSDavid Ahern }
101233c2dcfdSDavid Ahern 
1013e9db1310SAdrian Hunter int __perf_evlist__parse_mmap_pages(unsigned int *mmap_pages, const char *str)
101433c2dcfdSDavid Ahern {
101533c2dcfdSDavid Ahern 	unsigned long max = UINT_MAX;
101633c2dcfdSDavid Ahern 	long pages;
101733c2dcfdSDavid Ahern 
1018f5ae9c42SAdrian Hunter 	if (max > SIZE_MAX / page_size)
101933c2dcfdSDavid Ahern 		max = SIZE_MAX / page_size;
102033c2dcfdSDavid Ahern 
102133c2dcfdSDavid Ahern 	pages = parse_pages_arg(str, 1, max);
102233c2dcfdSDavid Ahern 	if (pages < 0) {
102333c2dcfdSDavid Ahern 		pr_err("Invalid argument for --mmap_pages/-m\n");
1024994a1f78SJiri Olsa 		return -1;
1025994a1f78SJiri Olsa 	}
1026994a1f78SJiri Olsa 
1027994a1f78SJiri Olsa 	*mmap_pages = pages;
1028994a1f78SJiri Olsa 	return 0;
1029994a1f78SJiri Olsa }
1030994a1f78SJiri Olsa 
1031e9db1310SAdrian Hunter int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
1032e9db1310SAdrian Hunter 				  int unset __maybe_unused)
1033e9db1310SAdrian Hunter {
1034e9db1310SAdrian Hunter 	return __perf_evlist__parse_mmap_pages(opt->value, str);
1035e9db1310SAdrian Hunter }
1036e9db1310SAdrian Hunter 
1037c83fa7f2SAdrian Hunter /**
1038718c602dSAdrian Hunter  * perf_evlist__mmap_ex - Create mmaps to receive events.
1039c83fa7f2SAdrian Hunter  * @evlist: list of events
1040c83fa7f2SAdrian Hunter  * @pages: map length in pages
1041c83fa7f2SAdrian Hunter  * @overwrite: overwrite older events?
1042718c602dSAdrian Hunter  * @auxtrace_pages - auxtrace map length in pages
1043718c602dSAdrian Hunter  * @auxtrace_overwrite - overwrite older auxtrace data?
1044f8a95309SArnaldo Carvalho de Melo  *
1045c83fa7f2SAdrian Hunter  * If @overwrite is %false the user needs to signal event consumption using
1046c83fa7f2SAdrian Hunter  * perf_mmap__write_tail().  Using perf_evlist__mmap_read() does this
1047c83fa7f2SAdrian Hunter  * automatically.
1048f8a95309SArnaldo Carvalho de Melo  *
1049718c602dSAdrian Hunter  * Similarly, if @auxtrace_overwrite is %false the user needs to signal data
1050718c602dSAdrian Hunter  * consumption using auxtrace_mmap__write_tail().
1051718c602dSAdrian Hunter  *
1052c83fa7f2SAdrian Hunter  * Return: %0 on success, negative error code otherwise.
1053f8a95309SArnaldo Carvalho de Melo  */
1054718c602dSAdrian Hunter int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1055718c602dSAdrian Hunter 			 bool overwrite, unsigned int auxtrace_pages,
1056718c602dSAdrian Hunter 			 bool auxtrace_overwrite)
1057f8a95309SArnaldo Carvalho de Melo {
1058aece948fSArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
10597e2ed097SArnaldo Carvalho de Melo 	const struct cpu_map *cpus = evlist->cpus;
10607e2ed097SArnaldo Carvalho de Melo 	const struct thread_map *threads = evlist->threads;
1061a8a8f3ebSAdrian Hunter 	struct mmap_params mp = {
1062a8a8f3ebSAdrian Hunter 		.prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
1063a8a8f3ebSAdrian Hunter 	};
106450a682ceSArnaldo Carvalho de Melo 
10658db6d6b1SWang Nan 	if (!evlist->mmap)
10668db6d6b1SWang Nan 		evlist->mmap = perf_evlist__alloc_mmap(evlist);
10678db6d6b1SWang Nan 	if (!evlist->mmap)
1068f8a95309SArnaldo Carvalho de Melo 		return -ENOMEM;
1069f8a95309SArnaldo Carvalho de Melo 
10701b85337dSArnaldo Carvalho de Melo 	if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
1071f8a95309SArnaldo Carvalho de Melo 		return -ENOMEM;
1072f8a95309SArnaldo Carvalho de Melo 
1073f8a95309SArnaldo Carvalho de Melo 	evlist->overwrite = overwrite;
1074994a1f78SJiri Olsa 	evlist->mmap_len = perf_evlist__mmap_size(pages);
10752af68ef5SAdrian Hunter 	pr_debug("mmap size %zuB\n", evlist->mmap_len);
1076a8a8f3ebSAdrian Hunter 	mp.mask = evlist->mmap_len - page_size - 1;
1077f8a95309SArnaldo Carvalho de Melo 
1078718c602dSAdrian Hunter 	auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len,
1079718c602dSAdrian Hunter 				   auxtrace_pages, auxtrace_overwrite);
1080718c602dSAdrian Hunter 
1081e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
1082f8a95309SArnaldo Carvalho de Melo 		if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
1083a91e5431SArnaldo Carvalho de Melo 		    evsel->sample_id == NULL &&
1084a14bb7a6SArnaldo Carvalho de Melo 		    perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
1085f8a95309SArnaldo Carvalho de Melo 			return -ENOMEM;
1086f8a95309SArnaldo Carvalho de Melo 	}
1087f8a95309SArnaldo Carvalho de Melo 
1088ec1e7e43SSukadev Bhattiprolu 	if (cpu_map__empty(cpus))
1089a8a8f3ebSAdrian Hunter 		return perf_evlist__mmap_per_thread(evlist, &mp);
1090f8a95309SArnaldo Carvalho de Melo 
1091a8a8f3ebSAdrian Hunter 	return perf_evlist__mmap_per_cpu(evlist, &mp);
1092f8a95309SArnaldo Carvalho de Melo }
10937e2ed097SArnaldo Carvalho de Melo 
1094718c602dSAdrian Hunter int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
1095718c602dSAdrian Hunter 		      bool overwrite)
1096718c602dSAdrian Hunter {
1097718c602dSAdrian Hunter 	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
1098718c602dSAdrian Hunter }
1099718c602dSAdrian Hunter 
1100602ad878SArnaldo Carvalho de Melo int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
11017e2ed097SArnaldo Carvalho de Melo {
110274bfd2b2SAdrian Hunter 	struct cpu_map *cpus;
110374bfd2b2SAdrian Hunter 	struct thread_map *threads;
11047e2ed097SArnaldo Carvalho de Melo 
110574bfd2b2SAdrian Hunter 	threads = thread_map__new_str(target->pid, target->tid, target->uid);
110674bfd2b2SAdrian Hunter 
110774bfd2b2SAdrian Hunter 	if (!threads)
11087e2ed097SArnaldo Carvalho de Melo 		return -1;
11097e2ed097SArnaldo Carvalho de Melo 
11109c105fbcSDongsheng Yang 	if (target__uses_dummy_map(target))
111174bfd2b2SAdrian Hunter 		cpus = cpu_map__dummy_new();
1112879d77d0SNamhyung Kim 	else
111374bfd2b2SAdrian Hunter 		cpus = cpu_map__new(target->cpu_list);
11147e2ed097SArnaldo Carvalho de Melo 
111574bfd2b2SAdrian Hunter 	if (!cpus)
11167e2ed097SArnaldo Carvalho de Melo 		goto out_delete_threads;
11177e2ed097SArnaldo Carvalho de Melo 
1118ec9a77a7SAdrian Hunter 	evlist->has_user_cpus = !!target->cpu_list;
1119ec9a77a7SAdrian Hunter 
112074bfd2b2SAdrian Hunter 	perf_evlist__set_maps(evlist, cpus, threads);
1121d5bc056eSAdrian Hunter 
1122d5bc056eSAdrian Hunter 	return 0;
11237e2ed097SArnaldo Carvalho de Melo 
11247e2ed097SArnaldo Carvalho de Melo out_delete_threads:
112574bfd2b2SAdrian Hunter 	thread_map__put(threads);
11267e2ed097SArnaldo Carvalho de Melo 	return -1;
11277e2ed097SArnaldo Carvalho de Melo }
11287e2ed097SArnaldo Carvalho de Melo 
1129d5bc056eSAdrian Hunter void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
11303de5cfb0SJiri Olsa 			   struct thread_map *threads)
11313de5cfb0SJiri Olsa {
1132934e0f20SAdrian Hunter 	/*
1133934e0f20SAdrian Hunter 	 * Allow for the possibility that one or another of the maps isn't being
1134934e0f20SAdrian Hunter 	 * changed i.e. don't put it.  Note we are assuming the maps that are
1135934e0f20SAdrian Hunter 	 * being applied are brand new and evlist is taking ownership of the
1136934e0f20SAdrian Hunter 	 * original reference count of 1.  If that is not the case it is up to
1137934e0f20SAdrian Hunter 	 * the caller to increase the reference count.
1138934e0f20SAdrian Hunter 	 */
1139934e0f20SAdrian Hunter 	if (cpus != evlist->cpus) {
11403de5cfb0SJiri Olsa 		cpu_map__put(evlist->cpus);
1141a55e5663SArnaldo Carvalho de Melo 		evlist->cpus = cpu_map__get(cpus);
1142934e0f20SAdrian Hunter 	}
11433de5cfb0SJiri Olsa 
1144934e0f20SAdrian Hunter 	if (threads != evlist->threads) {
11453de5cfb0SJiri Olsa 		thread_map__put(evlist->threads);
1146a55e5663SArnaldo Carvalho de Melo 		evlist->threads = thread_map__get(threads);
1147934e0f20SAdrian Hunter 	}
11483de5cfb0SJiri Olsa 
1149ec9a77a7SAdrian Hunter 	perf_evlist__propagate_maps(evlist);
11503de5cfb0SJiri Olsa }
11513de5cfb0SJiri Olsa 
115222c8a376SArnaldo Carvalho de Melo void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
115322c8a376SArnaldo Carvalho de Melo 				   enum perf_event_sample_format bit)
115422c8a376SArnaldo Carvalho de Melo {
115522c8a376SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
115622c8a376SArnaldo Carvalho de Melo 
1157e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel)
115822c8a376SArnaldo Carvalho de Melo 		__perf_evsel__set_sample_bit(evsel, bit);
115922c8a376SArnaldo Carvalho de Melo }
116022c8a376SArnaldo Carvalho de Melo 
116122c8a376SArnaldo Carvalho de Melo void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
116222c8a376SArnaldo Carvalho de Melo 				     enum perf_event_sample_format bit)
116322c8a376SArnaldo Carvalho de Melo {
116422c8a376SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
116522c8a376SArnaldo Carvalho de Melo 
1166e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel)
116722c8a376SArnaldo Carvalho de Melo 		__perf_evsel__reset_sample_bit(evsel, bit);
116822c8a376SArnaldo Carvalho de Melo }
116922c8a376SArnaldo Carvalho de Melo 
117023d4aad4SArnaldo Carvalho de Melo int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
11710a102479SFrederic Weisbecker {
11720a102479SFrederic Weisbecker 	struct perf_evsel *evsel;
1173745cefc5SArnaldo Carvalho de Melo 	int err = 0;
11740a102479SFrederic Weisbecker 
1175e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
1176745cefc5SArnaldo Carvalho de Melo 		if (evsel->filter == NULL)
11770a102479SFrederic Weisbecker 			continue;
1178745cefc5SArnaldo Carvalho de Melo 
1179d988d5eeSKan Liang 		/*
1180d988d5eeSKan Liang 		 * filters only work for tracepoint event, which doesn't have cpu limit.
1181d988d5eeSKan Liang 		 * So evlist and evsel should always be same.
1182d988d5eeSKan Liang 		 */
1183475fb533SAndi Kleen 		err = perf_evsel__apply_filter(evsel, evsel->filter);
118423d4aad4SArnaldo Carvalho de Melo 		if (err) {
118523d4aad4SArnaldo Carvalho de Melo 			*err_evsel = evsel;
1186745cefc5SArnaldo Carvalho de Melo 			break;
11870a102479SFrederic Weisbecker 		}
118823d4aad4SArnaldo Carvalho de Melo 	}
11890a102479SFrederic Weisbecker 
1190745cefc5SArnaldo Carvalho de Melo 	return err;
1191745cefc5SArnaldo Carvalho de Melo }
1192745cefc5SArnaldo Carvalho de Melo 
1193745cefc5SArnaldo Carvalho de Melo int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
1194745cefc5SArnaldo Carvalho de Melo {
1195745cefc5SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
1196745cefc5SArnaldo Carvalho de Melo 	int err = 0;
1197745cefc5SArnaldo Carvalho de Melo 
1198e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
1199fdf14720SWang Nan 		if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1200fdf14720SWang Nan 			continue;
1201fdf14720SWang Nan 
120294ad89bcSArnaldo Carvalho de Melo 		err = perf_evsel__set_filter(evsel, filter);
1203745cefc5SArnaldo Carvalho de Melo 		if (err)
1204745cefc5SArnaldo Carvalho de Melo 			break;
1205745cefc5SArnaldo Carvalho de Melo 	}
1206745cefc5SArnaldo Carvalho de Melo 
1207745cefc5SArnaldo Carvalho de Melo 	return err;
12080a102479SFrederic Weisbecker }
120974429964SFrederic Weisbecker 
1210be199adaSArnaldo Carvalho de Melo int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids)
1211cfd70a26SArnaldo Carvalho de Melo {
1212cfd70a26SArnaldo Carvalho de Melo 	char *filter;
1213be199adaSArnaldo Carvalho de Melo 	int ret = -1;
1214be199adaSArnaldo Carvalho de Melo 	size_t i;
1215cfd70a26SArnaldo Carvalho de Melo 
1216be199adaSArnaldo Carvalho de Melo 	for (i = 0; i < npids; ++i) {
1217be199adaSArnaldo Carvalho de Melo 		if (i == 0) {
1218be199adaSArnaldo Carvalho de Melo 			if (asprintf(&filter, "common_pid != %d", pids[i]) < 0)
1219cfd70a26SArnaldo Carvalho de Melo 				return -1;
1220be199adaSArnaldo Carvalho de Melo 		} else {
1221be199adaSArnaldo Carvalho de Melo 			char *tmp;
1222be199adaSArnaldo Carvalho de Melo 
1223be199adaSArnaldo Carvalho de Melo 			if (asprintf(&tmp, "%s && common_pid != %d", filter, pids[i]) < 0)
1224be199adaSArnaldo Carvalho de Melo 				goto out_free;
1225be199adaSArnaldo Carvalho de Melo 
1226be199adaSArnaldo Carvalho de Melo 			free(filter);
1227be199adaSArnaldo Carvalho de Melo 			filter = tmp;
1228be199adaSArnaldo Carvalho de Melo 		}
1229be199adaSArnaldo Carvalho de Melo 	}
1230cfd70a26SArnaldo Carvalho de Melo 
1231cfd70a26SArnaldo Carvalho de Melo 	ret = perf_evlist__set_filter(evlist, filter);
1232be199adaSArnaldo Carvalho de Melo out_free:
1233cfd70a26SArnaldo Carvalho de Melo 	free(filter);
1234cfd70a26SArnaldo Carvalho de Melo 	return ret;
1235cfd70a26SArnaldo Carvalho de Melo }
1236cfd70a26SArnaldo Carvalho de Melo 
1237be199adaSArnaldo Carvalho de Melo int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid)
1238be199adaSArnaldo Carvalho de Melo {
1239be199adaSArnaldo Carvalho de Melo 	return perf_evlist__set_filter_pids(evlist, 1, &pid);
1240be199adaSArnaldo Carvalho de Melo }
1241be199adaSArnaldo Carvalho de Melo 
12420c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
124374429964SFrederic Weisbecker {
124475562573SAdrian Hunter 	struct perf_evsel *pos;
1245c2a70653SArnaldo Carvalho de Melo 
124675562573SAdrian Hunter 	if (evlist->nr_entries == 1)
124775562573SAdrian Hunter 		return true;
124875562573SAdrian Hunter 
124975562573SAdrian Hunter 	if (evlist->id_pos < 0 || evlist->is_pos < 0)
125075562573SAdrian Hunter 		return false;
125175562573SAdrian Hunter 
1252e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
125375562573SAdrian Hunter 		if (pos->id_pos != evlist->id_pos ||
125475562573SAdrian Hunter 		    pos->is_pos != evlist->is_pos)
1255c2a70653SArnaldo Carvalho de Melo 			return false;
125674429964SFrederic Weisbecker 	}
125774429964SFrederic Weisbecker 
1258c2a70653SArnaldo Carvalho de Melo 	return true;
1259c2a70653SArnaldo Carvalho de Melo }
1260c2a70653SArnaldo Carvalho de Melo 
126175562573SAdrian Hunter u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
1262c2a70653SArnaldo Carvalho de Melo {
126375562573SAdrian Hunter 	struct perf_evsel *evsel;
126475562573SAdrian Hunter 
126575562573SAdrian Hunter 	if (evlist->combined_sample_type)
126675562573SAdrian Hunter 		return evlist->combined_sample_type;
126775562573SAdrian Hunter 
1268e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel)
126975562573SAdrian Hunter 		evlist->combined_sample_type |= evsel->attr.sample_type;
127075562573SAdrian Hunter 
127175562573SAdrian Hunter 	return evlist->combined_sample_type;
127275562573SAdrian Hunter }
127375562573SAdrian Hunter 
127475562573SAdrian Hunter u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist)
127575562573SAdrian Hunter {
127675562573SAdrian Hunter 	evlist->combined_sample_type = 0;
127775562573SAdrian Hunter 	return __perf_evlist__combined_sample_type(evlist);
1278c2a70653SArnaldo Carvalho de Melo }
1279c2a70653SArnaldo Carvalho de Melo 
128098df858eSAndi Kleen u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist)
128198df858eSAndi Kleen {
128298df858eSAndi Kleen 	struct perf_evsel *evsel;
128398df858eSAndi Kleen 	u64 branch_type = 0;
128498df858eSAndi Kleen 
1285e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel)
128698df858eSAndi Kleen 		branch_type |= evsel->attr.branch_sample_type;
128798df858eSAndi Kleen 	return branch_type;
128898df858eSAndi Kleen }
128998df858eSAndi Kleen 
12909ede473cSJiri Olsa bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
12919ede473cSJiri Olsa {
12929ede473cSJiri Olsa 	struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
12939ede473cSJiri Olsa 	u64 read_format = first->attr.read_format;
12949ede473cSJiri Olsa 	u64 sample_type = first->attr.sample_type;
12959ede473cSJiri Olsa 
1296e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, pos) {
12979ede473cSJiri Olsa 		if (read_format != pos->attr.read_format)
12989ede473cSJiri Olsa 			return false;
12999ede473cSJiri Olsa 	}
13009ede473cSJiri Olsa 
13019ede473cSJiri Olsa 	/* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */
13029ede473cSJiri Olsa 	if ((sample_type & PERF_SAMPLE_READ) &&
13039ede473cSJiri Olsa 	    !(read_format & PERF_FORMAT_ID)) {
13049ede473cSJiri Olsa 		return false;
13059ede473cSJiri Olsa 	}
13069ede473cSJiri Olsa 
13079ede473cSJiri Olsa 	return true;
13089ede473cSJiri Olsa }
13099ede473cSJiri Olsa 
13109ede473cSJiri Olsa u64 perf_evlist__read_format(struct perf_evlist *evlist)
13119ede473cSJiri Olsa {
13129ede473cSJiri Olsa 	struct perf_evsel *first = perf_evlist__first(evlist);
13139ede473cSJiri Olsa 	return first->attr.read_format;
13149ede473cSJiri Olsa }
13159ede473cSJiri Olsa 
13160c21f736SArnaldo Carvalho de Melo u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
131781e36bffSArnaldo Carvalho de Melo {
13180c21f736SArnaldo Carvalho de Melo 	struct perf_evsel *first = perf_evlist__first(evlist);
131981e36bffSArnaldo Carvalho de Melo 	struct perf_sample *data;
132081e36bffSArnaldo Carvalho de Melo 	u64 sample_type;
132181e36bffSArnaldo Carvalho de Melo 	u16 size = 0;
132281e36bffSArnaldo Carvalho de Melo 
132381e36bffSArnaldo Carvalho de Melo 	if (!first->attr.sample_id_all)
132481e36bffSArnaldo Carvalho de Melo 		goto out;
132581e36bffSArnaldo Carvalho de Melo 
132681e36bffSArnaldo Carvalho de Melo 	sample_type = first->attr.sample_type;
132781e36bffSArnaldo Carvalho de Melo 
132881e36bffSArnaldo Carvalho de Melo 	if (sample_type & PERF_SAMPLE_TID)
132981e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->tid) * 2;
133081e36bffSArnaldo Carvalho de Melo 
133181e36bffSArnaldo Carvalho de Melo        if (sample_type & PERF_SAMPLE_TIME)
133281e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->time);
133381e36bffSArnaldo Carvalho de Melo 
133481e36bffSArnaldo Carvalho de Melo 	if (sample_type & PERF_SAMPLE_ID)
133581e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->id);
133681e36bffSArnaldo Carvalho de Melo 
133781e36bffSArnaldo Carvalho de Melo 	if (sample_type & PERF_SAMPLE_STREAM_ID)
133881e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->stream_id);
133981e36bffSArnaldo Carvalho de Melo 
134081e36bffSArnaldo Carvalho de Melo 	if (sample_type & PERF_SAMPLE_CPU)
134181e36bffSArnaldo Carvalho de Melo 		size += sizeof(data->cpu) * 2;
134275562573SAdrian Hunter 
134375562573SAdrian Hunter 	if (sample_type & PERF_SAMPLE_IDENTIFIER)
134475562573SAdrian Hunter 		size += sizeof(data->id);
134581e36bffSArnaldo Carvalho de Melo out:
134681e36bffSArnaldo Carvalho de Melo 	return size;
134781e36bffSArnaldo Carvalho de Melo }
134881e36bffSArnaldo Carvalho de Melo 
13490c21f736SArnaldo Carvalho de Melo bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
1350c2a70653SArnaldo Carvalho de Melo {
13510c21f736SArnaldo Carvalho de Melo 	struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
1352c2a70653SArnaldo Carvalho de Melo 
1353e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry_continue(evlist, pos) {
1354c2a70653SArnaldo Carvalho de Melo 		if (first->attr.sample_id_all != pos->attr.sample_id_all)
1355c2a70653SArnaldo Carvalho de Melo 			return false;
1356c2a70653SArnaldo Carvalho de Melo 	}
1357c2a70653SArnaldo Carvalho de Melo 
1358c2a70653SArnaldo Carvalho de Melo 	return true;
135974429964SFrederic Weisbecker }
136074429964SFrederic Weisbecker 
13610c21f736SArnaldo Carvalho de Melo bool perf_evlist__sample_id_all(struct perf_evlist *evlist)
136274429964SFrederic Weisbecker {
13630c21f736SArnaldo Carvalho de Melo 	struct perf_evsel *first = perf_evlist__first(evlist);
1364c2a70653SArnaldo Carvalho de Melo 	return first->attr.sample_id_all;
136574429964SFrederic Weisbecker }
136681cce8deSArnaldo Carvalho de Melo 
136781cce8deSArnaldo Carvalho de Melo void perf_evlist__set_selected(struct perf_evlist *evlist,
136881cce8deSArnaldo Carvalho de Melo 			       struct perf_evsel *evsel)
136981cce8deSArnaldo Carvalho de Melo {
137081cce8deSArnaldo Carvalho de Melo 	evlist->selected = evsel;
137181cce8deSArnaldo Carvalho de Melo }
1372727ab04eSArnaldo Carvalho de Melo 
1373a74b4b66SNamhyung Kim void perf_evlist__close(struct perf_evlist *evlist)
1374a74b4b66SNamhyung Kim {
1375a74b4b66SNamhyung Kim 	struct perf_evsel *evsel;
1376a74b4b66SNamhyung Kim 
1377475fb533SAndi Kleen 	evlist__for_each_entry_reverse(evlist, evsel)
1378475fb533SAndi Kleen 		perf_evsel__close(evsel);
1379a74b4b66SNamhyung Kim }
1380a74b4b66SNamhyung Kim 
13814112eb18SArnaldo Carvalho de Melo static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
13824112eb18SArnaldo Carvalho de Melo {
13838c0498b6SAdrian Hunter 	struct cpu_map	  *cpus;
13848c0498b6SAdrian Hunter 	struct thread_map *threads;
13854112eb18SArnaldo Carvalho de Melo 	int err = -ENOMEM;
13864112eb18SArnaldo Carvalho de Melo 
13874112eb18SArnaldo Carvalho de Melo 	/*
13884112eb18SArnaldo Carvalho de Melo 	 * Try reading /sys/devices/system/cpu/online to get
13894112eb18SArnaldo Carvalho de Melo 	 * an all cpus map.
13904112eb18SArnaldo Carvalho de Melo 	 *
13914112eb18SArnaldo Carvalho de Melo 	 * FIXME: -ENOMEM is the best we can do here, the cpu_map
13924112eb18SArnaldo Carvalho de Melo 	 * code needs an overhaul to properly forward the
13934112eb18SArnaldo Carvalho de Melo 	 * error, and we may not want to do that fallback to a
13944112eb18SArnaldo Carvalho de Melo 	 * default cpu identity map :-\
13954112eb18SArnaldo Carvalho de Melo 	 */
13968c0498b6SAdrian Hunter 	cpus = cpu_map__new(NULL);
13978c0498b6SAdrian Hunter 	if (!cpus)
13984112eb18SArnaldo Carvalho de Melo 		goto out;
13994112eb18SArnaldo Carvalho de Melo 
14008c0498b6SAdrian Hunter 	threads = thread_map__new_dummy();
14018c0498b6SAdrian Hunter 	if (!threads)
14028c0498b6SAdrian Hunter 		goto out_put;
14034112eb18SArnaldo Carvalho de Melo 
14048c0498b6SAdrian Hunter 	perf_evlist__set_maps(evlist, cpus, threads);
14054112eb18SArnaldo Carvalho de Melo out:
14064112eb18SArnaldo Carvalho de Melo 	return err;
14078c0498b6SAdrian Hunter out_put:
14088c0498b6SAdrian Hunter 	cpu_map__put(cpus);
14094112eb18SArnaldo Carvalho de Melo 	goto out;
14104112eb18SArnaldo Carvalho de Melo }
14114112eb18SArnaldo Carvalho de Melo 
14126a4bb04cSJiri Olsa int perf_evlist__open(struct perf_evlist *evlist)
1413727ab04eSArnaldo Carvalho de Melo {
14146a4bb04cSJiri Olsa 	struct perf_evsel *evsel;
1415a74b4b66SNamhyung Kim 	int err;
1416727ab04eSArnaldo Carvalho de Melo 
14174112eb18SArnaldo Carvalho de Melo 	/*
14184112eb18SArnaldo Carvalho de Melo 	 * Default: one fd per CPU, all threads, aka systemwide
14194112eb18SArnaldo Carvalho de Melo 	 * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL
14204112eb18SArnaldo Carvalho de Melo 	 */
14214112eb18SArnaldo Carvalho de Melo 	if (evlist->threads == NULL && evlist->cpus == NULL) {
14224112eb18SArnaldo Carvalho de Melo 		err = perf_evlist__create_syswide_maps(evlist);
14234112eb18SArnaldo Carvalho de Melo 		if (err < 0)
14244112eb18SArnaldo Carvalho de Melo 			goto out_err;
14254112eb18SArnaldo Carvalho de Melo 	}
14264112eb18SArnaldo Carvalho de Melo 
1427733cd2feSAdrian Hunter 	perf_evlist__update_id_pos(evlist);
1428733cd2feSAdrian Hunter 
1429e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
143023df7f79SAdrian Hunter 		err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
1431727ab04eSArnaldo Carvalho de Melo 		if (err < 0)
1432727ab04eSArnaldo Carvalho de Melo 			goto out_err;
1433727ab04eSArnaldo Carvalho de Melo 	}
1434727ab04eSArnaldo Carvalho de Melo 
1435727ab04eSArnaldo Carvalho de Melo 	return 0;
1436727ab04eSArnaldo Carvalho de Melo out_err:
1437a74b4b66SNamhyung Kim 	perf_evlist__close(evlist);
143841c21a68SNamhyung Kim 	errno = -err;
1439727ab04eSArnaldo Carvalho de Melo 	return err;
1440727ab04eSArnaldo Carvalho de Melo }
144135b9d88eSArnaldo Carvalho de Melo 
1442602ad878SArnaldo Carvalho de Melo int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
144355e162eaSNamhyung Kim 				  const char *argv[], bool pipe_output,
1444735f7e0bSArnaldo Carvalho de Melo 				  void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
144535b9d88eSArnaldo Carvalho de Melo {
144635b9d88eSArnaldo Carvalho de Melo 	int child_ready_pipe[2], go_pipe[2];
144735b9d88eSArnaldo Carvalho de Melo 	char bf;
144835b9d88eSArnaldo Carvalho de Melo 
144935b9d88eSArnaldo Carvalho de Melo 	if (pipe(child_ready_pipe) < 0) {
145035b9d88eSArnaldo Carvalho de Melo 		perror("failed to create 'ready' pipe");
145135b9d88eSArnaldo Carvalho de Melo 		return -1;
145235b9d88eSArnaldo Carvalho de Melo 	}
145335b9d88eSArnaldo Carvalho de Melo 
145435b9d88eSArnaldo Carvalho de Melo 	if (pipe(go_pipe) < 0) {
145535b9d88eSArnaldo Carvalho de Melo 		perror("failed to create 'go' pipe");
145635b9d88eSArnaldo Carvalho de Melo 		goto out_close_ready_pipe;
145735b9d88eSArnaldo Carvalho de Melo 	}
145835b9d88eSArnaldo Carvalho de Melo 
145935b9d88eSArnaldo Carvalho de Melo 	evlist->workload.pid = fork();
146035b9d88eSArnaldo Carvalho de Melo 	if (evlist->workload.pid < 0) {
146135b9d88eSArnaldo Carvalho de Melo 		perror("failed to fork");
146235b9d88eSArnaldo Carvalho de Melo 		goto out_close_pipes;
146335b9d88eSArnaldo Carvalho de Melo 	}
146435b9d88eSArnaldo Carvalho de Melo 
146535b9d88eSArnaldo Carvalho de Melo 	if (!evlist->workload.pid) {
14665f1c4225SArnaldo Carvalho de Melo 		int ret;
14675f1c4225SArnaldo Carvalho de Melo 
1468119fa3c9SNamhyung Kim 		if (pipe_output)
146935b9d88eSArnaldo Carvalho de Melo 			dup2(2, 1);
147035b9d88eSArnaldo Carvalho de Melo 
14710817df08SDavid Ahern 		signal(SIGTERM, SIG_DFL);
14720817df08SDavid Ahern 
147335b9d88eSArnaldo Carvalho de Melo 		close(child_ready_pipe[0]);
147435b9d88eSArnaldo Carvalho de Melo 		close(go_pipe[1]);
147535b9d88eSArnaldo Carvalho de Melo 		fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
147635b9d88eSArnaldo Carvalho de Melo 
147735b9d88eSArnaldo Carvalho de Melo 		/*
147835b9d88eSArnaldo Carvalho de Melo 		 * Tell the parent we're ready to go
147935b9d88eSArnaldo Carvalho de Melo 		 */
148035b9d88eSArnaldo Carvalho de Melo 		close(child_ready_pipe[1]);
148135b9d88eSArnaldo Carvalho de Melo 
148235b9d88eSArnaldo Carvalho de Melo 		/*
148335b9d88eSArnaldo Carvalho de Melo 		 * Wait until the parent tells us to go.
148435b9d88eSArnaldo Carvalho de Melo 		 */
14855f1c4225SArnaldo Carvalho de Melo 		ret = read(go_pipe[0], &bf, 1);
14865f1c4225SArnaldo Carvalho de Melo 		/*
14875f1c4225SArnaldo Carvalho de Melo 		 * The parent will ask for the execvp() to be performed by
14885f1c4225SArnaldo Carvalho de Melo 		 * writing exactly one byte, in workload.cork_fd, usually via
14895f1c4225SArnaldo Carvalho de Melo 		 * perf_evlist__start_workload().
14905f1c4225SArnaldo Carvalho de Melo 		 *
149120f86fc1SArnaldo Carvalho de Melo 		 * For cancelling the workload without actually running it,
14925f1c4225SArnaldo Carvalho de Melo 		 * the parent will just close workload.cork_fd, without writing
14935f1c4225SArnaldo Carvalho de Melo 		 * anything, i.e. read will return zero and we just exit()
14945f1c4225SArnaldo Carvalho de Melo 		 * here.
14955f1c4225SArnaldo Carvalho de Melo 		 */
14965f1c4225SArnaldo Carvalho de Melo 		if (ret != 1) {
14975f1c4225SArnaldo Carvalho de Melo 			if (ret == -1)
149835b9d88eSArnaldo Carvalho de Melo 				perror("unable to read pipe");
14995f1c4225SArnaldo Carvalho de Melo 			exit(ret);
15005f1c4225SArnaldo Carvalho de Melo 		}
150135b9d88eSArnaldo Carvalho de Melo 
150235b9d88eSArnaldo Carvalho de Melo 		execvp(argv[0], (char **)argv);
150335b9d88eSArnaldo Carvalho de Melo 
1504735f7e0bSArnaldo Carvalho de Melo 		if (exec_error) {
1505f33cbe72SArnaldo Carvalho de Melo 			union sigval val;
1506f33cbe72SArnaldo Carvalho de Melo 
1507f33cbe72SArnaldo Carvalho de Melo 			val.sival_int = errno;
1508f33cbe72SArnaldo Carvalho de Melo 			if (sigqueue(getppid(), SIGUSR1, val))
150935b9d88eSArnaldo Carvalho de Melo 				perror(argv[0]);
1510f33cbe72SArnaldo Carvalho de Melo 		} else
1511f33cbe72SArnaldo Carvalho de Melo 			perror(argv[0]);
151235b9d88eSArnaldo Carvalho de Melo 		exit(-1);
151335b9d88eSArnaldo Carvalho de Melo 	}
151435b9d88eSArnaldo Carvalho de Melo 
1515735f7e0bSArnaldo Carvalho de Melo 	if (exec_error) {
1516735f7e0bSArnaldo Carvalho de Melo 		struct sigaction act = {
1517735f7e0bSArnaldo Carvalho de Melo 			.sa_flags     = SA_SIGINFO,
1518735f7e0bSArnaldo Carvalho de Melo 			.sa_sigaction = exec_error,
1519735f7e0bSArnaldo Carvalho de Melo 		};
1520735f7e0bSArnaldo Carvalho de Melo 		sigaction(SIGUSR1, &act, NULL);
1521735f7e0bSArnaldo Carvalho de Melo 	}
1522735f7e0bSArnaldo Carvalho de Melo 
15231aaf63b1SArnaldo Carvalho de Melo 	if (target__none(target)) {
15241aaf63b1SArnaldo Carvalho de Melo 		if (evlist->threads == NULL) {
15251aaf63b1SArnaldo Carvalho de Melo 			fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n",
15261aaf63b1SArnaldo Carvalho de Melo 				__func__, __LINE__);
15271aaf63b1SArnaldo Carvalho de Melo 			goto out_close_pipes;
15281aaf63b1SArnaldo Carvalho de Melo 		}
1529e13798c7SJiri Olsa 		thread_map__set_pid(evlist->threads, 0, evlist->workload.pid);
15301aaf63b1SArnaldo Carvalho de Melo 	}
153135b9d88eSArnaldo Carvalho de Melo 
153235b9d88eSArnaldo Carvalho de Melo 	close(child_ready_pipe[1]);
153335b9d88eSArnaldo Carvalho de Melo 	close(go_pipe[0]);
153435b9d88eSArnaldo Carvalho de Melo 	/*
153535b9d88eSArnaldo Carvalho de Melo 	 * wait for child to settle
153635b9d88eSArnaldo Carvalho de Melo 	 */
153735b9d88eSArnaldo Carvalho de Melo 	if (read(child_ready_pipe[0], &bf, 1) == -1) {
153835b9d88eSArnaldo Carvalho de Melo 		perror("unable to read pipe");
153935b9d88eSArnaldo Carvalho de Melo 		goto out_close_pipes;
154035b9d88eSArnaldo Carvalho de Melo 	}
154135b9d88eSArnaldo Carvalho de Melo 
1542bcf3145fSNamhyung Kim 	fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC);
154335b9d88eSArnaldo Carvalho de Melo 	evlist->workload.cork_fd = go_pipe[1];
154435b9d88eSArnaldo Carvalho de Melo 	close(child_ready_pipe[0]);
154535b9d88eSArnaldo Carvalho de Melo 	return 0;
154635b9d88eSArnaldo Carvalho de Melo 
154735b9d88eSArnaldo Carvalho de Melo out_close_pipes:
154835b9d88eSArnaldo Carvalho de Melo 	close(go_pipe[0]);
154935b9d88eSArnaldo Carvalho de Melo 	close(go_pipe[1]);
155035b9d88eSArnaldo Carvalho de Melo out_close_ready_pipe:
155135b9d88eSArnaldo Carvalho de Melo 	close(child_ready_pipe[0]);
155235b9d88eSArnaldo Carvalho de Melo 	close(child_ready_pipe[1]);
155335b9d88eSArnaldo Carvalho de Melo 	return -1;
155435b9d88eSArnaldo Carvalho de Melo }
155535b9d88eSArnaldo Carvalho de Melo 
155635b9d88eSArnaldo Carvalho de Melo int perf_evlist__start_workload(struct perf_evlist *evlist)
155735b9d88eSArnaldo Carvalho de Melo {
155835b9d88eSArnaldo Carvalho de Melo 	if (evlist->workload.cork_fd > 0) {
1559b3824404SDavid Ahern 		char bf = 0;
1560bcf3145fSNamhyung Kim 		int ret;
156135b9d88eSArnaldo Carvalho de Melo 		/*
156235b9d88eSArnaldo Carvalho de Melo 		 * Remove the cork, let it rip!
156335b9d88eSArnaldo Carvalho de Melo 		 */
1564bcf3145fSNamhyung Kim 		ret = write(evlist->workload.cork_fd, &bf, 1);
1565bcf3145fSNamhyung Kim 		if (ret < 0)
1566e978be9eSSoramichi Akiyama 			perror("unable to write to pipe");
1567bcf3145fSNamhyung Kim 
1568bcf3145fSNamhyung Kim 		close(evlist->workload.cork_fd);
1569bcf3145fSNamhyung Kim 		return ret;
157035b9d88eSArnaldo Carvalho de Melo 	}
157135b9d88eSArnaldo Carvalho de Melo 
157235b9d88eSArnaldo Carvalho de Melo 	return 0;
157335b9d88eSArnaldo Carvalho de Melo }
1574cb0b29e0SArnaldo Carvalho de Melo 
1575a3f698feSArnaldo Carvalho de Melo int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
15760807d2d8SArnaldo Carvalho de Melo 			      struct perf_sample *sample)
1577cb0b29e0SArnaldo Carvalho de Melo {
157875562573SAdrian Hunter 	struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
157975562573SAdrian Hunter 
158075562573SAdrian Hunter 	if (!evsel)
158175562573SAdrian Hunter 		return -EFAULT;
15820807d2d8SArnaldo Carvalho de Melo 	return perf_evsel__parse_sample(evsel, event, sample);
1583cb0b29e0SArnaldo Carvalho de Melo }
158478f067b3SArnaldo Carvalho de Melo 
158578f067b3SArnaldo Carvalho de Melo size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
158678f067b3SArnaldo Carvalho de Melo {
158778f067b3SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
158878f067b3SArnaldo Carvalho de Melo 	size_t printed = 0;
158978f067b3SArnaldo Carvalho de Melo 
1590e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
159178f067b3SArnaldo Carvalho de Melo 		printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
159278f067b3SArnaldo Carvalho de Melo 				   perf_evsel__name(evsel));
159378f067b3SArnaldo Carvalho de Melo 	}
159478f067b3SArnaldo Carvalho de Melo 
1595b2222139SDavidlohr Bueso 	return printed + fprintf(fp, "\n");
159678f067b3SArnaldo Carvalho de Melo }
15976ef068cbSArnaldo Carvalho de Melo 
1598d9aade7fSArnaldo Carvalho de Melo int perf_evlist__strerror_open(struct perf_evlist *evlist,
1599a8f23d8fSArnaldo Carvalho de Melo 			       int err, char *buf, size_t size)
1600a8f23d8fSArnaldo Carvalho de Melo {
1601a8f23d8fSArnaldo Carvalho de Melo 	int printed, value;
1602c8b5f2c9SArnaldo Carvalho de Melo 	char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
1603a8f23d8fSArnaldo Carvalho de Melo 
1604a8f23d8fSArnaldo Carvalho de Melo 	switch (err) {
1605a8f23d8fSArnaldo Carvalho de Melo 	case EACCES:
1606a8f23d8fSArnaldo Carvalho de Melo 	case EPERM:
1607a8f23d8fSArnaldo Carvalho de Melo 		printed = scnprintf(buf, size,
1608a8f23d8fSArnaldo Carvalho de Melo 				    "Error:\t%s.\n"
1609a8f23d8fSArnaldo Carvalho de Melo 				    "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
1610a8f23d8fSArnaldo Carvalho de Melo 
16111a47245dSAdrian Hunter 		value = perf_event_paranoid();
1612a8f23d8fSArnaldo Carvalho de Melo 
1613a8f23d8fSArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
1614a8f23d8fSArnaldo Carvalho de Melo 
1615a8f23d8fSArnaldo Carvalho de Melo 		if (value >= 2) {
1616a8f23d8fSArnaldo Carvalho de Melo 			printed += scnprintf(buf + printed, size - printed,
1617a8f23d8fSArnaldo Carvalho de Melo 					     "For your workloads it needs to be <= 1\nHint:\t");
1618a8f23d8fSArnaldo Carvalho de Melo 		}
1619a8f23d8fSArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed,
16205229e366SArnaldo Carvalho de Melo 				     "For system wide tracing it needs to be set to -1.\n");
1621a8f23d8fSArnaldo Carvalho de Melo 
1622a8f23d8fSArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed,
16235229e366SArnaldo Carvalho de Melo 				    "Hint:\tTry: 'sudo sh -c \"echo -1 > /proc/sys/kernel/perf_event_paranoid\"'\n"
16245229e366SArnaldo Carvalho de Melo 				    "Hint:\tThe current value is %d.", value);
1625a8f23d8fSArnaldo Carvalho de Melo 		break;
1626d9aade7fSArnaldo Carvalho de Melo 	case EINVAL: {
1627d9aade7fSArnaldo Carvalho de Melo 		struct perf_evsel *first = perf_evlist__first(evlist);
1628d9aade7fSArnaldo Carvalho de Melo 		int max_freq;
1629d9aade7fSArnaldo Carvalho de Melo 
1630d9aade7fSArnaldo Carvalho de Melo 		if (sysctl__read_int("kernel/perf_event_max_sample_rate", &max_freq) < 0)
1631d9aade7fSArnaldo Carvalho de Melo 			goto out_default;
1632d9aade7fSArnaldo Carvalho de Melo 
1633d9aade7fSArnaldo Carvalho de Melo 		if (first->attr.sample_freq < (u64)max_freq)
1634d9aade7fSArnaldo Carvalho de Melo 			goto out_default;
1635d9aade7fSArnaldo Carvalho de Melo 
1636d9aade7fSArnaldo Carvalho de Melo 		printed = scnprintf(buf, size,
1637d9aade7fSArnaldo Carvalho de Melo 				    "Error:\t%s.\n"
1638d9aade7fSArnaldo Carvalho de Melo 				    "Hint:\tCheck /proc/sys/kernel/perf_event_max_sample_rate.\n"
1639d9aade7fSArnaldo Carvalho de Melo 				    "Hint:\tThe current value is %d and %" PRIu64 " is being requested.",
1640d9aade7fSArnaldo Carvalho de Melo 				    emsg, max_freq, first->attr.sample_freq);
1641d9aade7fSArnaldo Carvalho de Melo 		break;
1642d9aade7fSArnaldo Carvalho de Melo 	}
1643a8f23d8fSArnaldo Carvalho de Melo 	default:
1644d9aade7fSArnaldo Carvalho de Melo out_default:
1645a8f23d8fSArnaldo Carvalho de Melo 		scnprintf(buf, size, "%s", emsg);
1646a8f23d8fSArnaldo Carvalho de Melo 		break;
1647a8f23d8fSArnaldo Carvalho de Melo 	}
1648a8f23d8fSArnaldo Carvalho de Melo 
1649a8f23d8fSArnaldo Carvalho de Melo 	return 0;
1650a8f23d8fSArnaldo Carvalho de Melo }
1651a025e4f0SAdrian Hunter 
1652956fa571SArnaldo Carvalho de Melo int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
1653956fa571SArnaldo Carvalho de Melo {
1654c8b5f2c9SArnaldo Carvalho de Melo 	char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
1655e965bea1SArnaldo Carvalho de Melo 	int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
1656956fa571SArnaldo Carvalho de Melo 
1657956fa571SArnaldo Carvalho de Melo 	switch (err) {
1658956fa571SArnaldo Carvalho de Melo 	case EPERM:
1659e5d4a290SArnaldo Carvalho de Melo 		sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
1660e965bea1SArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed,
1661e965bea1SArnaldo Carvalho de Melo 				     "Error:\t%s.\n"
1662956fa571SArnaldo Carvalho de Melo 				     "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
1663e965bea1SArnaldo Carvalho de Melo 				     "Hint:\tTried using %zd kB.\n",
1664e5d4a290SArnaldo Carvalho de Melo 				     emsg, pages_max_per_user, pages_attempted);
1665e965bea1SArnaldo Carvalho de Melo 
1666e965bea1SArnaldo Carvalho de Melo 		if (pages_attempted >= pages_max_per_user) {
1667e965bea1SArnaldo Carvalho de Melo 			printed += scnprintf(buf + printed, size - printed,
1668e965bea1SArnaldo Carvalho de Melo 					     "Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n",
1669e965bea1SArnaldo Carvalho de Melo 					     pages_max_per_user + pages_attempted);
1670e965bea1SArnaldo Carvalho de Melo 		}
1671e965bea1SArnaldo Carvalho de Melo 
1672e965bea1SArnaldo Carvalho de Melo 		printed += scnprintf(buf + printed, size - printed,
1673e965bea1SArnaldo Carvalho de Melo 				     "Hint:\tTry using a smaller -m/--mmap-pages value.");
1674956fa571SArnaldo Carvalho de Melo 		break;
1675956fa571SArnaldo Carvalho de Melo 	default:
1676956fa571SArnaldo Carvalho de Melo 		scnprintf(buf, size, "%s", emsg);
1677956fa571SArnaldo Carvalho de Melo 		break;
1678956fa571SArnaldo Carvalho de Melo 	}
1679956fa571SArnaldo Carvalho de Melo 
1680956fa571SArnaldo Carvalho de Melo 	return 0;
1681956fa571SArnaldo Carvalho de Melo }
1682956fa571SArnaldo Carvalho de Melo 
1683a025e4f0SAdrian Hunter void perf_evlist__to_front(struct perf_evlist *evlist,
1684a025e4f0SAdrian Hunter 			   struct perf_evsel *move_evsel)
1685a025e4f0SAdrian Hunter {
1686a025e4f0SAdrian Hunter 	struct perf_evsel *evsel, *n;
1687a025e4f0SAdrian Hunter 	LIST_HEAD(move);
1688a025e4f0SAdrian Hunter 
1689a025e4f0SAdrian Hunter 	if (move_evsel == perf_evlist__first(evlist))
1690a025e4f0SAdrian Hunter 		return;
1691a025e4f0SAdrian Hunter 
1692e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry_safe(evlist, n, evsel) {
1693a025e4f0SAdrian Hunter 		if (evsel->leader == move_evsel->leader)
1694a025e4f0SAdrian Hunter 			list_move_tail(&evsel->node, &move);
1695a025e4f0SAdrian Hunter 	}
1696a025e4f0SAdrian Hunter 
1697a025e4f0SAdrian Hunter 	list_splice(&move, &evlist->entries);
1698a025e4f0SAdrian Hunter }
169960b0896cSAdrian Hunter 
170060b0896cSAdrian Hunter void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
170160b0896cSAdrian Hunter 				     struct perf_evsel *tracking_evsel)
170260b0896cSAdrian Hunter {
170360b0896cSAdrian Hunter 	struct perf_evsel *evsel;
170460b0896cSAdrian Hunter 
170560b0896cSAdrian Hunter 	if (tracking_evsel->tracking)
170660b0896cSAdrian Hunter 		return;
170760b0896cSAdrian Hunter 
1708e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
170960b0896cSAdrian Hunter 		if (evsel != tracking_evsel)
171060b0896cSAdrian Hunter 			evsel->tracking = false;
171160b0896cSAdrian Hunter 	}
171260b0896cSAdrian Hunter 
171360b0896cSAdrian Hunter 	tracking_evsel->tracking = true;
171460b0896cSAdrian Hunter }
17157630b3e2SWang Nan 
17167630b3e2SWang Nan struct perf_evsel *
17177630b3e2SWang Nan perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
17187630b3e2SWang Nan 			       const char *str)
17197630b3e2SWang Nan {
17207630b3e2SWang Nan 	struct perf_evsel *evsel;
17217630b3e2SWang Nan 
1722e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
17237630b3e2SWang Nan 		if (!evsel->name)
17247630b3e2SWang Nan 			continue;
17257630b3e2SWang Nan 		if (strcmp(str, evsel->name) == 0)
17267630b3e2SWang Nan 			return evsel;
17277630b3e2SWang Nan 	}
17287630b3e2SWang Nan 
17297630b3e2SWang Nan 	return NULL;
17307630b3e2SWang Nan }
173154cc54deSWang Nan 
173254cc54deSWang Nan void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist,
173354cc54deSWang Nan 				  enum bkw_mmap_state state)
173454cc54deSWang Nan {
173554cc54deSWang Nan 	enum bkw_mmap_state old_state = evlist->bkw_mmap_state;
173654cc54deSWang Nan 	enum action {
173754cc54deSWang Nan 		NONE,
173854cc54deSWang Nan 		PAUSE,
173954cc54deSWang Nan 		RESUME,
174054cc54deSWang Nan 	} action = NONE;
174154cc54deSWang Nan 
174254cc54deSWang Nan 	if (!evlist->backward_mmap)
174354cc54deSWang Nan 		return;
174454cc54deSWang Nan 
174554cc54deSWang Nan 	switch (old_state) {
174654cc54deSWang Nan 	case BKW_MMAP_NOTREADY: {
174754cc54deSWang Nan 		if (state != BKW_MMAP_RUNNING)
174854cc54deSWang Nan 			goto state_err;;
174954cc54deSWang Nan 		break;
175054cc54deSWang Nan 	}
175154cc54deSWang Nan 	case BKW_MMAP_RUNNING: {
175254cc54deSWang Nan 		if (state != BKW_MMAP_DATA_PENDING)
175354cc54deSWang Nan 			goto state_err;
175454cc54deSWang Nan 		action = PAUSE;
175554cc54deSWang Nan 		break;
175654cc54deSWang Nan 	}
175754cc54deSWang Nan 	case BKW_MMAP_DATA_PENDING: {
175854cc54deSWang Nan 		if (state != BKW_MMAP_EMPTY)
175954cc54deSWang Nan 			goto state_err;
176054cc54deSWang Nan 		break;
176154cc54deSWang Nan 	}
176254cc54deSWang Nan 	case BKW_MMAP_EMPTY: {
176354cc54deSWang Nan 		if (state != BKW_MMAP_RUNNING)
176454cc54deSWang Nan 			goto state_err;
176554cc54deSWang Nan 		action = RESUME;
176654cc54deSWang Nan 		break;
176754cc54deSWang Nan 	}
176854cc54deSWang Nan 	default:
176954cc54deSWang Nan 		WARN_ONCE(1, "Shouldn't get there\n");
177054cc54deSWang Nan 	}
177154cc54deSWang Nan 
177254cc54deSWang Nan 	evlist->bkw_mmap_state = state;
177354cc54deSWang Nan 
177454cc54deSWang Nan 	switch (action) {
177554cc54deSWang Nan 	case PAUSE:
177654cc54deSWang Nan 		perf_evlist__pause(evlist);
177754cc54deSWang Nan 		break;
177854cc54deSWang Nan 	case RESUME:
177954cc54deSWang Nan 		perf_evlist__resume(evlist);
178054cc54deSWang Nan 		break;
178154cc54deSWang Nan 	case NONE:
178254cc54deSWang Nan 	default:
178354cc54deSWang Nan 		break;
178454cc54deSWang Nan 	}
178554cc54deSWang Nan 
178654cc54deSWang Nan state_err:
178754cc54deSWang Nan 	return;
178854cc54deSWang Nan }
178907d6f446SArnaldo Carvalho de Melo 
179007d6f446SArnaldo Carvalho de Melo bool perf_evlist__exclude_kernel(struct perf_evlist *evlist)
179107d6f446SArnaldo Carvalho de Melo {
179207d6f446SArnaldo Carvalho de Melo 	struct perf_evsel *evsel;
179307d6f446SArnaldo Carvalho de Melo 
179407d6f446SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
179507d6f446SArnaldo Carvalho de Melo 		if (!evsel->attr.exclude_kernel)
179607d6f446SArnaldo Carvalho de Melo 			return false;
179707d6f446SArnaldo Carvalho de Melo 	}
179807d6f446SArnaldo Carvalho de Melo 
179907d6f446SArnaldo Carvalho de Melo 	return true;
180007d6f446SArnaldo Carvalho de Melo }
1801