xref: /openbmc/linux/tools/perf/util/metricgroup.c (revision a6efaa2c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2017, Intel Corporation.
4  */
5 
6 /* Manage metrics and groups of metrics from JSON files */
7 
8 #include "metricgroup.h"
9 #include "debug.h"
10 #include "evlist.h"
11 #include "evsel.h"
12 #include "strbuf.h"
13 #include "pmu.h"
14 #include "pmu-hybrid.h"
15 #include "expr.h"
16 #include "rblist.h"
17 #include <string.h>
18 #include <errno.h>
19 #include "strlist.h"
20 #include <assert.h>
21 #include <linux/ctype.h>
22 #include <linux/list_sort.h>
23 #include <linux/string.h>
24 #include <linux/zalloc.h>
25 #include <perf/cpumap.h>
26 #include <subcmd/parse-options.h>
27 #include <api/fs/fs.h>
28 #include "util.h"
29 #include <asm/bug.h>
30 #include "cgroup.h"
31 
32 struct metric_event *metricgroup__lookup(struct rblist *metric_events,
33 					 struct evsel *evsel,
34 					 bool create)
35 {
36 	struct rb_node *nd;
37 	struct metric_event me = {
38 		.evsel = evsel
39 	};
40 
41 	if (!metric_events)
42 		return NULL;
43 
44 	nd = rblist__find(metric_events, &me);
45 	if (nd)
46 		return container_of(nd, struct metric_event, nd);
47 	if (create) {
48 		rblist__add_node(metric_events, &me);
49 		nd = rblist__find(metric_events, &me);
50 		if (nd)
51 			return container_of(nd, struct metric_event, nd);
52 	}
53 	return NULL;
54 }
55 
56 static int metric_event_cmp(struct rb_node *rb_node, const void *entry)
57 {
58 	struct metric_event *a = container_of(rb_node,
59 					      struct metric_event,
60 					      nd);
61 	const struct metric_event *b = entry;
62 
63 	if (a->evsel == b->evsel)
64 		return 0;
65 	if ((char *)a->evsel < (char *)b->evsel)
66 		return -1;
67 	return +1;
68 }
69 
70 static struct rb_node *metric_event_new(struct rblist *rblist __maybe_unused,
71 					const void *entry)
72 {
73 	struct metric_event *me = malloc(sizeof(struct metric_event));
74 
75 	if (!me)
76 		return NULL;
77 	memcpy(me, entry, sizeof(struct metric_event));
78 	me->evsel = ((struct metric_event *)entry)->evsel;
79 	INIT_LIST_HEAD(&me->head);
80 	return &me->nd;
81 }
82 
83 static void metric_event_delete(struct rblist *rblist __maybe_unused,
84 				struct rb_node *rb_node)
85 {
86 	struct metric_event *me = container_of(rb_node, struct metric_event, nd);
87 	struct metric_expr *expr, *tmp;
88 
89 	list_for_each_entry_safe(expr, tmp, &me->head, nd) {
90 		free((char *)expr->metric_name);
91 		free(expr->metric_refs);
92 		free(expr->metric_events);
93 		free(expr);
94 	}
95 
96 	free(me);
97 }
98 
99 static void metricgroup__rblist_init(struct rblist *metric_events)
100 {
101 	rblist__init(metric_events);
102 	metric_events->node_cmp = metric_event_cmp;
103 	metric_events->node_new = metric_event_new;
104 	metric_events->node_delete = metric_event_delete;
105 }
106 
107 void metricgroup__rblist_exit(struct rblist *metric_events)
108 {
109 	rblist__exit(metric_events);
110 }
111 
112 /**
113  * The metric under construction. The data held here will be placed in a
114  * metric_expr.
115  */
116 struct metric {
117 	struct list_head nd;
118 	/**
119 	 * The expression parse context importantly holding the IDs contained
120 	 * within the expression.
121 	 */
122 	struct expr_parse_ctx *pctx;
123 	/** The name of the metric such as "IPC". */
124 	const char *metric_name;
125 	/** Modifier on the metric such as "u" or NULL for none. */
126 	const char *modifier;
127 	/** The expression to parse, for example, "instructions/cycles". */
128 	const char *metric_expr;
129 	/**
130 	 * The "ScaleUnit" that scales and adds a unit to the metric during
131 	 * output.
132 	 */
133 	const char *metric_unit;
134 	/** Optional null terminated array of referenced metrics. */
135 	struct metric_ref *metric_refs;
136 	/**
137 	 * Is there a constraint on the group of events? In which case the
138 	 * events won't be grouped.
139 	 */
140 	bool has_constraint;
141 	/**
142 	 * Parsed events for the metric. Optional as events may be taken from a
143 	 * different metric whose group contains all the IDs necessary for this
144 	 * one.
145 	 */
146 	struct evlist *evlist;
147 };
148 
149 static void metricgroup___watchdog_constraint_hint(const char *name, bool foot)
150 {
151 	static bool violate_nmi_constraint;
152 
153 	if (!foot) {
154 		pr_warning("Splitting metric group %s into standalone metrics.\n", name);
155 		violate_nmi_constraint = true;
156 		return;
157 	}
158 
159 	if (!violate_nmi_constraint)
160 		return;
161 
162 	pr_warning("Try disabling the NMI watchdog to comply NO_NMI_WATCHDOG metric constraint:\n"
163 		   "    echo 0 > /proc/sys/kernel/nmi_watchdog\n"
164 		   "    perf stat ...\n"
165 		   "    echo 1 > /proc/sys/kernel/nmi_watchdog\n");
166 }
167 
168 static bool metricgroup__has_constraint(const struct pmu_event *pe)
169 {
170 	if (!pe->metric_constraint)
171 		return false;
172 
173 	if (!strcmp(pe->metric_constraint, "NO_NMI_WATCHDOG") &&
174 	    sysctl__nmi_watchdog_enabled()) {
175 		metricgroup___watchdog_constraint_hint(pe->metric_name, false);
176 		return true;
177 	}
178 
179 	return false;
180 }
181 
182 static void metric__free(struct metric *m)
183 {
184 	if (!m)
185 		return;
186 
187 	free(m->metric_refs);
188 	expr__ctx_free(m->pctx);
189 	free((char *)m->modifier);
190 	evlist__delete(m->evlist);
191 	free(m);
192 }
193 
194 static struct metric *metric__new(const struct pmu_event *pe,
195 				  const char *modifier,
196 				  bool metric_no_group,
197 				  int runtime,
198 				  const char *user_requested_cpu_list,
199 				  bool system_wide)
200 {
201 	struct metric *m;
202 
203 	m = zalloc(sizeof(*m));
204 	if (!m)
205 		return NULL;
206 
207 	m->pctx = expr__ctx_new();
208 	if (!m->pctx)
209 		goto out_err;
210 
211 	m->metric_name = pe->metric_name;
212 	m->modifier = NULL;
213 	if (modifier) {
214 		m->modifier = strdup(modifier);
215 		if (!m->modifier)
216 			goto out_err;
217 	}
218 	m->metric_expr = pe->metric_expr;
219 	m->metric_unit = pe->unit;
220 	m->pctx->sctx.user_requested_cpu_list = NULL;
221 	if (user_requested_cpu_list) {
222 		m->pctx->sctx.user_requested_cpu_list = strdup(user_requested_cpu_list);
223 		if (!m->pctx->sctx.user_requested_cpu_list)
224 			goto out_err;
225 	}
226 	m->pctx->sctx.runtime = runtime;
227 	m->pctx->sctx.system_wide = system_wide;
228 	m->has_constraint = metric_no_group || metricgroup__has_constraint(pe);
229 	m->metric_refs = NULL;
230 	m->evlist = NULL;
231 
232 	return m;
233 out_err:
234 	metric__free(m);
235 	return NULL;
236 }
237 
238 static bool contains_metric_id(struct evsel **metric_events, int num_events,
239 			       const char *metric_id)
240 {
241 	int i;
242 
243 	for (i = 0; i < num_events; i++) {
244 		if (!strcmp(evsel__metric_id(metric_events[i]), metric_id))
245 			return true;
246 	}
247 	return false;
248 }
249 
250 /**
251  * setup_metric_events - Find a group of events in metric_evlist that correspond
252  *                       to the IDs from a parsed metric expression.
253  * @ids: the metric IDs to match.
254  * @metric_evlist: the list of perf events.
255  * @out_metric_events: holds the created metric events array.
256  */
257 static int setup_metric_events(struct hashmap *ids,
258 			       struct evlist *metric_evlist,
259 			       struct evsel ***out_metric_events)
260 {
261 	struct evsel **metric_events;
262 	const char *metric_id;
263 	struct evsel *ev;
264 	size_t ids_size, matched_events, i;
265 
266 	*out_metric_events = NULL;
267 	ids_size = hashmap__size(ids);
268 
269 	metric_events = calloc(sizeof(void *), ids_size + 1);
270 	if (!metric_events)
271 		return -ENOMEM;
272 
273 	matched_events = 0;
274 	evlist__for_each_entry(metric_evlist, ev) {
275 		struct expr_id_data *val_ptr;
276 
277 		/*
278 		 * Check for duplicate events with the same name. For
279 		 * example, uncore_imc/cas_count_read/ will turn into 6
280 		 * events per socket on skylakex. Only the first such
281 		 * event is placed in metric_events.
282 		 */
283 		metric_id = evsel__metric_id(ev);
284 		if (contains_metric_id(metric_events, matched_events, metric_id))
285 			continue;
286 		/*
287 		 * Does this event belong to the parse context? For
288 		 * combined or shared groups, this metric may not care
289 		 * about this event.
290 		 */
291 		if (hashmap__find(ids, metric_id, (void **)&val_ptr)) {
292 			metric_events[matched_events++] = ev;
293 
294 			if (matched_events >= ids_size)
295 				break;
296 		}
297 	}
298 	if (matched_events < ids_size) {
299 		free(metric_events);
300 		return -EINVAL;
301 	}
302 	for (i = 0; i < ids_size; i++) {
303 		ev = metric_events[i];
304 		ev->collect_stat = true;
305 
306 		/*
307 		 * The metric leader points to the identically named
308 		 * event in metric_events.
309 		 */
310 		ev->metric_leader = ev;
311 		/*
312 		 * Mark two events with identical names in the same
313 		 * group (or globally) as being in use as uncore events
314 		 * may be duplicated for each pmu. Set the metric leader
315 		 * of such events to be the event that appears in
316 		 * metric_events.
317 		 */
318 		metric_id = evsel__metric_id(ev);
319 		evlist__for_each_entry_continue(metric_evlist, ev) {
320 			if (!strcmp(evsel__metric_id(ev), metric_id))
321 				ev->metric_leader = metric_events[i];
322 		}
323 	}
324 	*out_metric_events = metric_events;
325 	return 0;
326 }
327 
328 static bool match_metric(const char *n, const char *list)
329 {
330 	int len;
331 	char *m;
332 
333 	if (!list)
334 		return false;
335 	if (!strcmp(list, "all"))
336 		return true;
337 	if (!n)
338 		return !strcasecmp(list, "No_group");
339 	len = strlen(list);
340 	m = strcasestr(n, list);
341 	if (!m)
342 		return false;
343 	if ((m == n || m[-1] == ';' || m[-1] == ' ') &&
344 	    (m[len] == 0 || m[len] == ';'))
345 		return true;
346 	return false;
347 }
348 
349 static bool match_pe_metric(const struct pmu_event *pe, const char *metric)
350 {
351 	return match_metric(pe->metric_group, metric) ||
352 	       match_metric(pe->metric_name, metric);
353 }
354 
355 struct mep {
356 	struct rb_node nd;
357 	const char *name;
358 	struct strlist *metrics;
359 };
360 
361 static int mep_cmp(struct rb_node *rb_node, const void *entry)
362 {
363 	struct mep *a = container_of(rb_node, struct mep, nd);
364 	struct mep *b = (struct mep *)entry;
365 
366 	return strcmp(a->name, b->name);
367 }
368 
369 static struct rb_node *mep_new(struct rblist *rl __maybe_unused,
370 					const void *entry)
371 {
372 	struct mep *me = malloc(sizeof(struct mep));
373 
374 	if (!me)
375 		return NULL;
376 	memcpy(me, entry, sizeof(struct mep));
377 	me->name = strdup(me->name);
378 	if (!me->name)
379 		goto out_me;
380 	me->metrics = strlist__new(NULL, NULL);
381 	if (!me->metrics)
382 		goto out_name;
383 	return &me->nd;
384 out_name:
385 	zfree(&me->name);
386 out_me:
387 	free(me);
388 	return NULL;
389 }
390 
391 static struct mep *mep_lookup(struct rblist *groups, const char *name)
392 {
393 	struct rb_node *nd;
394 	struct mep me = {
395 		.name = name
396 	};
397 	nd = rblist__find(groups, &me);
398 	if (nd)
399 		return container_of(nd, struct mep, nd);
400 	rblist__add_node(groups, &me);
401 	nd = rblist__find(groups, &me);
402 	if (nd)
403 		return container_of(nd, struct mep, nd);
404 	return NULL;
405 }
406 
407 static void mep_delete(struct rblist *rl __maybe_unused,
408 		       struct rb_node *nd)
409 {
410 	struct mep *me = container_of(nd, struct mep, nd);
411 
412 	strlist__delete(me->metrics);
413 	zfree(&me->name);
414 	free(me);
415 }
416 
417 static void metricgroup__print_strlist(struct strlist *metrics, bool raw)
418 {
419 	struct str_node *sn;
420 	int n = 0;
421 
422 	strlist__for_each_entry (sn, metrics) {
423 		if (raw)
424 			printf("%s%s", n > 0 ? " " : "", sn->s);
425 		else
426 			printf("  %s\n", sn->s);
427 		n++;
428 	}
429 	if (raw)
430 		putchar('\n');
431 }
432 
433 static int metricgroup__print_pmu_event(const struct pmu_event *pe,
434 					bool metricgroups, char *filter,
435 					bool raw, bool details,
436 					struct rblist *groups,
437 					struct strlist *metriclist)
438 {
439 	const char *g;
440 	char *omg, *mg;
441 
442 	g = pe->metric_group;
443 	if (!g && pe->metric_name) {
444 		if (pe->name)
445 			return 0;
446 		g = "No_group";
447 	}
448 
449 	if (!g)
450 		return 0;
451 
452 	mg = strdup(g);
453 
454 	if (!mg)
455 		return -ENOMEM;
456 	omg = mg;
457 	while ((g = strsep(&mg, ";")) != NULL) {
458 		struct mep *me;
459 		char *s;
460 
461 		g = skip_spaces(g);
462 		if (*g == 0)
463 			g = "No_group";
464 		if (filter && !strstr(g, filter))
465 			continue;
466 		if (raw)
467 			s = (char *)pe->metric_name;
468 		else {
469 			if (asprintf(&s, "%s\n%*s%s]",
470 				     pe->metric_name, 8, "[", pe->desc) < 0)
471 				return -1;
472 			if (details) {
473 				if (asprintf(&s, "%s\n%*s%s]",
474 					     s, 8, "[", pe->metric_expr) < 0)
475 					return -1;
476 			}
477 		}
478 
479 		if (!s)
480 			continue;
481 
482 		if (!metricgroups) {
483 			strlist__add(metriclist, s);
484 		} else {
485 			me = mep_lookup(groups, g);
486 			if (!me)
487 				continue;
488 			strlist__add(me->metrics, s);
489 		}
490 
491 		if (!raw)
492 			free(s);
493 	}
494 	free(omg);
495 
496 	return 0;
497 }
498 
499 struct metricgroup_print_sys_idata {
500 	struct strlist *metriclist;
501 	char *filter;
502 	struct rblist *groups;
503 	bool metricgroups;
504 	bool raw;
505 	bool details;
506 };
507 
508 struct metricgroup_iter_data {
509 	pmu_event_iter_fn fn;
510 	void *data;
511 };
512 
513 static int metricgroup__sys_event_iter(const struct pmu_event *pe,
514 				       const struct pmu_events_table *table,
515 				       void *data)
516 {
517 	struct metricgroup_iter_data *d = data;
518 	struct perf_pmu *pmu = NULL;
519 
520 	if (!pe->metric_expr || !pe->compat)
521 		return 0;
522 
523 	while ((pmu = perf_pmu__scan(pmu))) {
524 
525 		if (!pmu->id || strcmp(pmu->id, pe->compat))
526 			continue;
527 
528 		return d->fn(pe, table, d->data);
529 	}
530 
531 	return 0;
532 }
533 
534 static int metricgroup__print_sys_event_iter(const struct pmu_event *pe,
535 					     const struct pmu_events_table *table __maybe_unused,
536 					     void *data)
537 {
538 	struct metricgroup_print_sys_idata *d = data;
539 
540 	return metricgroup__print_pmu_event(pe, d->metricgroups, d->filter, d->raw,
541 				     d->details, d->groups, d->metriclist);
542 }
543 
544 struct metricgroup_print_data {
545 	const char *pmu_name;
546 	struct strlist *metriclist;
547 	char *filter;
548 	struct rblist *groups;
549 	bool metricgroups;
550 	bool raw;
551 	bool details;
552 };
553 
554 static int metricgroup__print_callback(const struct pmu_event *pe,
555 				       const struct pmu_events_table *table __maybe_unused,
556 				       void *vdata)
557 {
558 	struct metricgroup_print_data *data = vdata;
559 	const char *pmu = pe->pmu ?: "cpu";
560 
561 	if (!pe->metric_expr)
562 		return 0;
563 
564 	if (data->pmu_name && strcmp(data->pmu_name, pmu))
565 		return 0;
566 
567 	return metricgroup__print_pmu_event(pe, data->metricgroups, data->filter,
568 					    data->raw, data->details, data->groups,
569 					    data->metriclist);
570 }
571 
572 void metricgroup__print(bool metrics, bool metricgroups, char *filter,
573 			bool raw, bool details, const char *pmu_name)
574 {
575 	struct rblist groups;
576 	struct rb_node *node, *next;
577 	struct strlist *metriclist = NULL;
578 	const struct pmu_events_table *table;
579 
580 	if (!metricgroups) {
581 		metriclist = strlist__new(NULL, NULL);
582 		if (!metriclist)
583 			return;
584 	}
585 
586 	rblist__init(&groups);
587 	groups.node_new = mep_new;
588 	groups.node_cmp = mep_cmp;
589 	groups.node_delete = mep_delete;
590 	table = pmu_events_table__find();
591 	if (table) {
592 		struct metricgroup_print_data data = {
593 			.pmu_name = pmu_name,
594 			.metriclist = metriclist,
595 			.metricgroups = metricgroups,
596 			.filter = filter,
597 			.raw = raw,
598 			.details = details,
599 			.groups = &groups,
600 		};
601 
602 		pmu_events_table_for_each_event(table,
603 						metricgroup__print_callback,
604 						&data);
605 	}
606 	{
607 		struct metricgroup_iter_data data = {
608 			.fn = metricgroup__print_sys_event_iter,
609 			.data = (void *) &(struct metricgroup_print_sys_idata){
610 				.metriclist = metriclist,
611 				.metricgroups = metricgroups,
612 				.filter = filter,
613 				.raw = raw,
614 				.details = details,
615 				.groups = &groups,
616 			},
617 		};
618 
619 		pmu_for_each_sys_event(metricgroup__sys_event_iter, &data);
620 	}
621 
622 	if (!filter || !rblist__empty(&groups)) {
623 		if (metricgroups && !raw)
624 			printf("\nMetric Groups:\n\n");
625 		else if (metrics && !raw)
626 			printf("\nMetrics:\n\n");
627 	}
628 
629 	for (node = rb_first_cached(&groups.entries); node; node = next) {
630 		struct mep *me = container_of(node, struct mep, nd);
631 
632 		if (metricgroups)
633 			printf("%s%s%s", me->name, metrics && !raw ? ":" : "", raw ? " " : "\n");
634 		if (metrics)
635 			metricgroup__print_strlist(me->metrics, raw);
636 		next = rb_next(node);
637 		rblist__remove_node(&groups, node);
638 	}
639 	if (!metricgroups)
640 		metricgroup__print_strlist(metriclist, raw);
641 	strlist__delete(metriclist);
642 }
643 
644 static const char *code_characters = ",-=@";
645 
646 static int encode_metric_id(struct strbuf *sb, const char *x)
647 {
648 	char *c;
649 	int ret = 0;
650 
651 	for (; *x; x++) {
652 		c = strchr(code_characters, *x);
653 		if (c) {
654 			ret = strbuf_addch(sb, '!');
655 			if (ret)
656 				break;
657 
658 			ret = strbuf_addch(sb, '0' + (c - code_characters));
659 			if (ret)
660 				break;
661 		} else {
662 			ret = strbuf_addch(sb, *x);
663 			if (ret)
664 				break;
665 		}
666 	}
667 	return ret;
668 }
669 
670 static int decode_metric_id(struct strbuf *sb, const char *x)
671 {
672 	const char *orig = x;
673 	size_t i;
674 	char c;
675 	int ret;
676 
677 	for (; *x; x++) {
678 		c = *x;
679 		if (*x == '!') {
680 			x++;
681 			i = *x - '0';
682 			if (i > strlen(code_characters)) {
683 				pr_err("Bad metric-id encoding in: '%s'", orig);
684 				return -1;
685 			}
686 			c = code_characters[i];
687 		}
688 		ret = strbuf_addch(sb, c);
689 		if (ret)
690 			return ret;
691 	}
692 	return 0;
693 }
694 
695 static int decode_all_metric_ids(struct evlist *perf_evlist, const char *modifier)
696 {
697 	struct evsel *ev;
698 	struct strbuf sb = STRBUF_INIT;
699 	char *cur;
700 	int ret = 0;
701 
702 	evlist__for_each_entry(perf_evlist, ev) {
703 		if (!ev->metric_id)
704 			continue;
705 
706 		ret = strbuf_setlen(&sb, 0);
707 		if (ret)
708 			break;
709 
710 		ret = decode_metric_id(&sb, ev->metric_id);
711 		if (ret)
712 			break;
713 
714 		free((char *)ev->metric_id);
715 		ev->metric_id = strdup(sb.buf);
716 		if (!ev->metric_id) {
717 			ret = -ENOMEM;
718 			break;
719 		}
720 		/*
721 		 * If the name is just the parsed event, use the metric-id to
722 		 * give a more friendly display version.
723 		 */
724 		if (strstr(ev->name, "metric-id=")) {
725 			bool has_slash = false;
726 
727 			free(ev->name);
728 			for (cur = strchr(sb.buf, '@') ; cur; cur = strchr(++cur, '@')) {
729 				*cur = '/';
730 				has_slash = true;
731 			}
732 
733 			if (modifier) {
734 				if (!has_slash && !strchr(sb.buf, ':')) {
735 					ret = strbuf_addch(&sb, ':');
736 					if (ret)
737 						break;
738 				}
739 				ret = strbuf_addstr(&sb, modifier);
740 				if (ret)
741 					break;
742 			}
743 			ev->name = strdup(sb.buf);
744 			if (!ev->name) {
745 				ret = -ENOMEM;
746 				break;
747 			}
748 		}
749 	}
750 	strbuf_release(&sb);
751 	return ret;
752 }
753 
754 static int metricgroup__build_event_string(struct strbuf *events,
755 					   const struct expr_parse_ctx *ctx,
756 					   const char *modifier,
757 					   bool has_constraint)
758 {
759 	struct hashmap_entry *cur;
760 	size_t bkt;
761 	bool no_group = true, has_tool_events = false;
762 	bool tool_events[PERF_TOOL_MAX] = {false};
763 	int ret = 0;
764 
765 #define RETURN_IF_NON_ZERO(x) do { if (x) return x; } while (0)
766 
767 	hashmap__for_each_entry(ctx->ids, cur, bkt) {
768 		const char *sep, *rsep, *id = cur->key;
769 		enum perf_tool_event ev;
770 
771 		pr_debug("found event %s\n", id);
772 
773 		/* Always move tool events outside of the group. */
774 		ev = perf_tool_event__from_str(id);
775 		if (ev != PERF_TOOL_NONE) {
776 			has_tool_events = true;
777 			tool_events[ev] = true;
778 			continue;
779 		}
780 		/* Separate events with commas and open the group if necessary. */
781 		if (no_group) {
782 			if (!has_constraint) {
783 				ret = strbuf_addch(events, '{');
784 				RETURN_IF_NON_ZERO(ret);
785 			}
786 
787 			no_group = false;
788 		} else {
789 			ret = strbuf_addch(events, ',');
790 			RETURN_IF_NON_ZERO(ret);
791 		}
792 		/*
793 		 * Encode the ID as an event string. Add a qualifier for
794 		 * metric_id that is the original name except with characters
795 		 * that parse-events can't parse replaced. For example,
796 		 * 'msr@tsc@' gets added as msr/tsc,metric-id=msr!3tsc!3/
797 		 */
798 		sep = strchr(id, '@');
799 		if (sep != NULL) {
800 			ret = strbuf_add(events, id, sep - id);
801 			RETURN_IF_NON_ZERO(ret);
802 			ret = strbuf_addch(events, '/');
803 			RETURN_IF_NON_ZERO(ret);
804 			rsep = strrchr(sep, '@');
805 			ret = strbuf_add(events, sep + 1, rsep - sep - 1);
806 			RETURN_IF_NON_ZERO(ret);
807 			ret = strbuf_addstr(events, ",metric-id=");
808 			RETURN_IF_NON_ZERO(ret);
809 			sep = rsep;
810 		} else {
811 			sep = strchr(id, ':');
812 			if (sep != NULL) {
813 				ret = strbuf_add(events, id, sep - id);
814 				RETURN_IF_NON_ZERO(ret);
815 			} else {
816 				ret = strbuf_addstr(events, id);
817 				RETURN_IF_NON_ZERO(ret);
818 			}
819 			ret = strbuf_addstr(events, "/metric-id=");
820 			RETURN_IF_NON_ZERO(ret);
821 		}
822 		ret = encode_metric_id(events, id);
823 		RETURN_IF_NON_ZERO(ret);
824 		ret = strbuf_addstr(events, "/");
825 		RETURN_IF_NON_ZERO(ret);
826 
827 		if (sep != NULL) {
828 			ret = strbuf_addstr(events, sep + 1);
829 			RETURN_IF_NON_ZERO(ret);
830 		}
831 		if (modifier) {
832 			ret = strbuf_addstr(events, modifier);
833 			RETURN_IF_NON_ZERO(ret);
834 		}
835 	}
836 	if (!no_group && !has_constraint) {
837 		ret = strbuf_addf(events, "}:W");
838 		RETURN_IF_NON_ZERO(ret);
839 	}
840 	if (has_tool_events) {
841 		int i;
842 
843 		perf_tool_event__for_each_event(i) {
844 			if (tool_events[i]) {
845 				if (!no_group) {
846 					ret = strbuf_addch(events, ',');
847 					RETURN_IF_NON_ZERO(ret);
848 				}
849 				no_group = false;
850 				ret = strbuf_addstr(events, perf_tool_event__to_str(i));
851 				RETURN_IF_NON_ZERO(ret);
852 			}
853 		}
854 	}
855 
856 	return ret;
857 #undef RETURN_IF_NON_ZERO
858 }
859 
860 int __weak arch_get_runtimeparam(const struct pmu_event *pe __maybe_unused)
861 {
862 	return 1;
863 }
864 
865 /*
866  * A singly linked list on the stack of the names of metrics being
867  * processed. Used to identify recursion.
868  */
869 struct visited_metric {
870 	const char *name;
871 	const struct visited_metric *parent;
872 };
873 
874 struct metricgroup_add_iter_data {
875 	struct list_head *metric_list;
876 	const char *metric_name;
877 	const char *modifier;
878 	int *ret;
879 	bool *has_match;
880 	bool metric_no_group;
881 	const char *user_requested_cpu_list;
882 	bool system_wide;
883 	struct metric *root_metric;
884 	const struct visited_metric *visited;
885 	const struct pmu_events_table *table;
886 };
887 
888 static bool metricgroup__find_metric(const char *metric,
889 				     const struct pmu_events_table *table,
890 				     struct pmu_event *pe);
891 
892 static int add_metric(struct list_head *metric_list,
893 		      const struct pmu_event *pe,
894 		      const char *modifier,
895 		      bool metric_no_group,
896 		      const char *user_requested_cpu_list,
897 		      bool system_wide,
898 		      struct metric *root_metric,
899 		      const struct visited_metric *visited,
900 		      const struct pmu_events_table *table);
901 
902 /**
903  * resolve_metric - Locate metrics within the root metric and recursively add
904  *                    references to them.
905  * @metric_list: The list the metric is added to.
906  * @modifier: if non-null event modifiers like "u".
907  * @metric_no_group: Should events written to events be grouped "{}" or
908  *                   global. Grouping is the default but due to multiplexing the
909  *                   user may override.
910  * @user_requested_cpu_list: Command line specified CPUs to record on.
911  * @system_wide: Are events for all processes recorded.
912  * @root_metric: Metrics may reference other metrics to form a tree. In this
913  *               case the root_metric holds all the IDs and a list of referenced
914  *               metrics. When adding a root this argument is NULL.
915  * @visited: A singly linked list of metric names being added that is used to
916  *           detect recursion.
917  * @table: The table that is searched for metrics, most commonly the table for the
918  *       architecture perf is running upon.
919  */
920 static int resolve_metric(struct list_head *metric_list,
921 			  const char *modifier,
922 			  bool metric_no_group,
923 			  const char *user_requested_cpu_list,
924 			  bool system_wide,
925 			  struct metric *root_metric,
926 			  const struct visited_metric *visited,
927 			  const struct pmu_events_table *table)
928 {
929 	struct hashmap_entry *cur;
930 	size_t bkt;
931 	struct to_resolve {
932 		/* The metric to resolve. */
933 		struct pmu_event pe;
934 		/*
935 		 * The key in the IDs map, this may differ from in case,
936 		 * etc. from pe->metric_name.
937 		 */
938 		const char *key;
939 	} *pending = NULL;
940 	int i, ret = 0, pending_cnt = 0;
941 
942 	/*
943 	 * Iterate all the parsed IDs and if there's a matching metric and it to
944 	 * the pending array.
945 	 */
946 	hashmap__for_each_entry(root_metric->pctx->ids, cur, bkt) {
947 		struct pmu_event pe;
948 
949 		if (metricgroup__find_metric(cur->key, table, &pe)) {
950 			pending = realloc(pending,
951 					(pending_cnt + 1) * sizeof(struct to_resolve));
952 			if (!pending)
953 				return -ENOMEM;
954 
955 			memcpy(&pending[pending_cnt].pe, &pe, sizeof(pe));
956 			pending[pending_cnt].key = cur->key;
957 			pending_cnt++;
958 		}
959 	}
960 
961 	/* Remove the metric IDs from the context. */
962 	for (i = 0; i < pending_cnt; i++)
963 		expr__del_id(root_metric->pctx, pending[i].key);
964 
965 	/*
966 	 * Recursively add all the metrics, IDs are added to the root metric's
967 	 * context.
968 	 */
969 	for (i = 0; i < pending_cnt; i++) {
970 		ret = add_metric(metric_list, &pending[i].pe, modifier, metric_no_group,
971 				 user_requested_cpu_list, system_wide, root_metric, visited,
972 				 table);
973 		if (ret)
974 			break;
975 	}
976 
977 	free(pending);
978 	return ret;
979 }
980 
981 /**
982  * __add_metric - Add a metric to metric_list.
983  * @metric_list: The list the metric is added to.
984  * @pe: The pmu_event containing the metric to be added.
985  * @modifier: if non-null event modifiers like "u".
986  * @metric_no_group: Should events written to events be grouped "{}" or
987  *                   global. Grouping is the default but due to multiplexing the
988  *                   user may override.
989  * @runtime: A special argument for the parser only known at runtime.
990  * @user_requested_cpu_list: Command line specified CPUs to record on.
991  * @system_wide: Are events for all processes recorded.
992  * @root_metric: Metrics may reference other metrics to form a tree. In this
993  *               case the root_metric holds all the IDs and a list of referenced
994  *               metrics. When adding a root this argument is NULL.
995  * @visited: A singly linked list of metric names being added that is used to
996  *           detect recursion.
997  * @table: The table that is searched for metrics, most commonly the table for the
998  *       architecture perf is running upon.
999  */
1000 static int __add_metric(struct list_head *metric_list,
1001 			const struct pmu_event *pe,
1002 			const char *modifier,
1003 			bool metric_no_group,
1004 			int runtime,
1005 			const char *user_requested_cpu_list,
1006 			bool system_wide,
1007 			struct metric *root_metric,
1008 			const struct visited_metric *visited,
1009 			const struct pmu_events_table *table)
1010 {
1011 	const struct visited_metric *vm;
1012 	int ret;
1013 	bool is_root = !root_metric;
1014 	struct visited_metric visited_node = {
1015 		.name = pe->metric_name,
1016 		.parent = visited,
1017 	};
1018 
1019 	for (vm = visited; vm; vm = vm->parent) {
1020 		if (!strcmp(pe->metric_name, vm->name)) {
1021 			pr_err("failed: recursion detected for %s\n", pe->metric_name);
1022 			return -1;
1023 		}
1024 	}
1025 
1026 	if (is_root) {
1027 		/*
1028 		 * This metric is the root of a tree and may reference other
1029 		 * metrics that are added recursively.
1030 		 */
1031 		root_metric = metric__new(pe, modifier, metric_no_group, runtime,
1032 					  user_requested_cpu_list, system_wide);
1033 		if (!root_metric)
1034 			return -ENOMEM;
1035 
1036 	} else {
1037 		int cnt = 0;
1038 
1039 		/*
1040 		 * This metric was referenced in a metric higher in the
1041 		 * tree. Check if the same metric is already resolved in the
1042 		 * metric_refs list.
1043 		 */
1044 		if (root_metric->metric_refs) {
1045 			for (; root_metric->metric_refs[cnt].metric_name; cnt++) {
1046 				if (!strcmp(pe->metric_name,
1047 					    root_metric->metric_refs[cnt].metric_name))
1048 					return 0;
1049 			}
1050 		}
1051 
1052 		/* Create reference. Need space for the entry and the terminator. */
1053 		root_metric->metric_refs = realloc(root_metric->metric_refs,
1054 						(cnt + 2) * sizeof(struct metric_ref));
1055 		if (!root_metric->metric_refs)
1056 			return -ENOMEM;
1057 
1058 		/*
1059 		 * Intentionally passing just const char pointers,
1060 		 * from 'pe' object, so they never go away. We don't
1061 		 * need to change them, so there's no need to create
1062 		 * our own copy.
1063 		 */
1064 		root_metric->metric_refs[cnt].metric_name = pe->metric_name;
1065 		root_metric->metric_refs[cnt].metric_expr = pe->metric_expr;
1066 
1067 		/* Null terminate array. */
1068 		root_metric->metric_refs[cnt+1].metric_name = NULL;
1069 		root_metric->metric_refs[cnt+1].metric_expr = NULL;
1070 	}
1071 
1072 	/*
1073 	 * For both the parent and referenced metrics, we parse
1074 	 * all the metric's IDs and add it to the root context.
1075 	 */
1076 	if (expr__find_ids(pe->metric_expr, NULL, root_metric->pctx) < 0) {
1077 		/* Broken metric. */
1078 		ret = -EINVAL;
1079 	} else {
1080 		/* Resolve referenced metrics. */
1081 		ret = resolve_metric(metric_list, modifier, metric_no_group,
1082 				     user_requested_cpu_list, system_wide,
1083 				     root_metric, &visited_node, table);
1084 	}
1085 
1086 	if (ret) {
1087 		if (is_root)
1088 			metric__free(root_metric);
1089 
1090 	} else if (is_root)
1091 		list_add(&root_metric->nd, metric_list);
1092 
1093 	return ret;
1094 }
1095 
1096 struct metricgroup__find_metric_data {
1097 	const char *metric;
1098 	struct pmu_event *pe;
1099 };
1100 
1101 static int metricgroup__find_metric_callback(const struct pmu_event *pe,
1102 					     const struct pmu_events_table *table  __maybe_unused,
1103 					     void *vdata)
1104 {
1105 	struct metricgroup__find_metric_data *data = vdata;
1106 
1107 	if (!match_metric(pe->metric_name, data->metric))
1108 		return 0;
1109 
1110 	memcpy(data->pe, pe, sizeof(*pe));
1111 	return 1;
1112 }
1113 
1114 static bool metricgroup__find_metric(const char *metric,
1115 				     const struct pmu_events_table *table,
1116 				     struct pmu_event *pe)
1117 {
1118 	struct metricgroup__find_metric_data data = {
1119 		.metric = metric,
1120 		.pe = pe,
1121 	};
1122 
1123 	return pmu_events_table_for_each_event(table, metricgroup__find_metric_callback, &data)
1124 		? true : false;
1125 }
1126 
1127 static int add_metric(struct list_head *metric_list,
1128 		      const struct pmu_event *pe,
1129 		      const char *modifier,
1130 		      bool metric_no_group,
1131 		      const char *user_requested_cpu_list,
1132 		      bool system_wide,
1133 		      struct metric *root_metric,
1134 		      const struct visited_metric *visited,
1135 		      const struct pmu_events_table *table)
1136 {
1137 	int ret = 0;
1138 
1139 	pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name);
1140 
1141 	if (!strstr(pe->metric_expr, "?")) {
1142 		ret = __add_metric(metric_list, pe, modifier, metric_no_group, 0,
1143 				   user_requested_cpu_list, system_wide, root_metric,
1144 				   visited, table);
1145 	} else {
1146 		int j, count;
1147 
1148 		count = arch_get_runtimeparam(pe);
1149 
1150 		/* This loop is added to create multiple
1151 		 * events depend on count value and add
1152 		 * those events to metric_list.
1153 		 */
1154 
1155 		for (j = 0; j < count && !ret; j++)
1156 			ret = __add_metric(metric_list, pe, modifier, metric_no_group, j,
1157 					   user_requested_cpu_list, system_wide,
1158 					   root_metric, visited, table);
1159 	}
1160 
1161 	return ret;
1162 }
1163 
1164 static int metricgroup__add_metric_sys_event_iter(const struct pmu_event *pe,
1165 						const struct pmu_events_table *table __maybe_unused,
1166 						void *data)
1167 {
1168 	struct metricgroup_add_iter_data *d = data;
1169 	int ret;
1170 
1171 	if (!match_pe_metric(pe, d->metric_name))
1172 		return 0;
1173 
1174 	ret = add_metric(d->metric_list, pe, d->modifier, d->metric_no_group,
1175 			 d->user_requested_cpu_list, d->system_wide,
1176 			 d->root_metric, d->visited, d->table);
1177 	if (ret)
1178 		goto out;
1179 
1180 	*(d->has_match) = true;
1181 
1182 out:
1183 	*(d->ret) = ret;
1184 	return ret;
1185 }
1186 
1187 /**
1188  * metric_list_cmp - list_sort comparator that sorts metrics with more events to
1189  *                   the front. tool events are excluded from the count.
1190  */
1191 static int metric_list_cmp(void *priv __maybe_unused, const struct list_head *l,
1192 			   const struct list_head *r)
1193 {
1194 	const struct metric *left = container_of(l, struct metric, nd);
1195 	const struct metric *right = container_of(r, struct metric, nd);
1196 	struct expr_id_data *data;
1197 	int i, left_count, right_count;
1198 
1199 	left_count = hashmap__size(left->pctx->ids);
1200 	perf_tool_event__for_each_event(i) {
1201 		if (!expr__get_id(left->pctx, perf_tool_event__to_str(i), &data))
1202 			left_count--;
1203 	}
1204 
1205 	right_count = hashmap__size(right->pctx->ids);
1206 	perf_tool_event__for_each_event(i) {
1207 		if (!expr__get_id(right->pctx, perf_tool_event__to_str(i), &data))
1208 			right_count--;
1209 	}
1210 
1211 	return right_count - left_count;
1212 }
1213 
1214 struct metricgroup__add_metric_data {
1215 	struct list_head *list;
1216 	const char *metric_name;
1217 	const char *modifier;
1218 	const char *user_requested_cpu_list;
1219 	bool metric_no_group;
1220 	bool system_wide;
1221 	bool has_match;
1222 };
1223 
1224 static int metricgroup__add_metric_callback(const struct pmu_event *pe,
1225 					    const struct pmu_events_table *table,
1226 					    void *vdata)
1227 {
1228 	struct metricgroup__add_metric_data *data = vdata;
1229 	int ret = 0;
1230 
1231 	if (pe->metric_expr &&
1232 		(match_metric(pe->metric_group, data->metric_name) ||
1233 		 match_metric(pe->metric_name, data->metric_name))) {
1234 
1235 		data->has_match = true;
1236 		ret = add_metric(data->list, pe, data->modifier, data->metric_no_group,
1237 				 data->user_requested_cpu_list, data->system_wide,
1238 				 /*root_metric=*/NULL, /*visited_metrics=*/NULL, table);
1239 	}
1240 	return ret;
1241 }
1242 
1243 /**
1244  * metricgroup__add_metric - Find and add a metric, or a metric group.
1245  * @metric_name: The name of the metric or metric group. For example, "IPC"
1246  *               could be the name of a metric and "TopDownL1" the name of a
1247  *               metric group.
1248  * @modifier: if non-null event modifiers like "u".
1249  * @metric_no_group: Should events written to events be grouped "{}" or
1250  *                   global. Grouping is the default but due to multiplexing the
1251  *                   user may override.
1252  * @user_requested_cpu_list: Command line specified CPUs to record on.
1253  * @system_wide: Are events for all processes recorded.
1254  * @metric_list: The list that the metric or metric group are added to.
1255  * @table: The table that is searched for metrics, most commonly the table for the
1256  *       architecture perf is running upon.
1257  */
1258 static int metricgroup__add_metric(const char *metric_name, const char *modifier,
1259 				   bool metric_no_group,
1260 				   const char *user_requested_cpu_list,
1261 				   bool system_wide,
1262 				   struct list_head *metric_list,
1263 				   const struct pmu_events_table *table)
1264 {
1265 	LIST_HEAD(list);
1266 	int ret;
1267 	bool has_match = false;
1268 
1269 	{
1270 		struct metricgroup__add_metric_data data = {
1271 			.list = &list,
1272 			.metric_name = metric_name,
1273 			.modifier = modifier,
1274 			.metric_no_group = metric_no_group,
1275 			.user_requested_cpu_list = user_requested_cpu_list,
1276 			.system_wide = system_wide,
1277 			.has_match = false,
1278 		};
1279 		/*
1280 		 * Iterate over all metrics seeing if metric matches either the
1281 		 * name or group. When it does add the metric to the list.
1282 		 */
1283 		ret = pmu_events_table_for_each_event(table, metricgroup__add_metric_callback,
1284 						      &data);
1285 		if (ret)
1286 			goto out;
1287 
1288 		has_match = data.has_match;
1289 	}
1290 	{
1291 		struct metricgroup_iter_data data = {
1292 			.fn = metricgroup__add_metric_sys_event_iter,
1293 			.data = (void *) &(struct metricgroup_add_iter_data) {
1294 				.metric_list = &list,
1295 				.metric_name = metric_name,
1296 				.modifier = modifier,
1297 				.metric_no_group = metric_no_group,
1298 				.user_requested_cpu_list = user_requested_cpu_list,
1299 				.system_wide = system_wide,
1300 				.has_match = &has_match,
1301 				.ret = &ret,
1302 				.table = table,
1303 			},
1304 		};
1305 
1306 		pmu_for_each_sys_event(metricgroup__sys_event_iter, &data);
1307 	}
1308 	/* End of pmu events. */
1309 	if (!has_match)
1310 		ret = -EINVAL;
1311 
1312 out:
1313 	/*
1314 	 * add to metric_list so that they can be released
1315 	 * even if it's failed
1316 	 */
1317 	list_splice(&list, metric_list);
1318 	return ret;
1319 }
1320 
1321 /**
1322  * metricgroup__add_metric_list - Find and add metrics, or metric groups,
1323  *                                specified in a list.
1324  * @list: the list of metrics or metric groups. For example, "IPC,CPI,TopDownL1"
1325  *        would match the IPC and CPI metrics, and TopDownL1 would match all
1326  *        the metrics in the TopDownL1 group.
1327  * @metric_no_group: Should events written to events be grouped "{}" or
1328  *                   global. Grouping is the default but due to multiplexing the
1329  *                   user may override.
1330  * @user_requested_cpu_list: Command line specified CPUs to record on.
1331  * @system_wide: Are events for all processes recorded.
1332  * @metric_list: The list that metrics are added to.
1333  * @table: The table that is searched for metrics, most commonly the table for the
1334  *       architecture perf is running upon.
1335  */
1336 static int metricgroup__add_metric_list(const char *list, bool metric_no_group,
1337 					const char *user_requested_cpu_list,
1338 					bool system_wide, struct list_head *metric_list,
1339 					const struct pmu_events_table *table)
1340 {
1341 	char *list_itr, *list_copy, *metric_name, *modifier;
1342 	int ret, count = 0;
1343 
1344 	list_copy = strdup(list);
1345 	if (!list_copy)
1346 		return -ENOMEM;
1347 	list_itr = list_copy;
1348 
1349 	while ((metric_name = strsep(&list_itr, ",")) != NULL) {
1350 		modifier = strchr(metric_name, ':');
1351 		if (modifier)
1352 			*modifier++ = '\0';
1353 
1354 		ret = metricgroup__add_metric(metric_name, modifier,
1355 					      metric_no_group, user_requested_cpu_list,
1356 					      system_wide, metric_list, table);
1357 		if (ret == -EINVAL)
1358 			pr_err("Cannot find metric or group `%s'\n", metric_name);
1359 
1360 		if (ret)
1361 			break;
1362 
1363 		count++;
1364 	}
1365 	free(list_copy);
1366 
1367 	if (!ret) {
1368 		/*
1369 		 * Warn about nmi_watchdog if any parsed metrics had the
1370 		 * NO_NMI_WATCHDOG constraint.
1371 		 */
1372 		metricgroup___watchdog_constraint_hint(NULL, true);
1373 		/* No metrics. */
1374 		if (count == 0)
1375 			return -EINVAL;
1376 	}
1377 	return ret;
1378 }
1379 
1380 static void metricgroup__free_metrics(struct list_head *metric_list)
1381 {
1382 	struct metric *m, *tmp;
1383 
1384 	list_for_each_entry_safe (m, tmp, metric_list, nd) {
1385 		list_del_init(&m->nd);
1386 		metric__free(m);
1387 	}
1388 }
1389 
1390 /**
1391  * find_tool_events - Search for the pressence of tool events in metric_list.
1392  * @metric_list: List to take metrics from.
1393  * @tool_events: Array of false values, indices corresponding to tool events set
1394  *               to true if tool event is found.
1395  */
1396 static void find_tool_events(const struct list_head *metric_list,
1397 			     bool tool_events[PERF_TOOL_MAX])
1398 {
1399 	struct metric *m;
1400 
1401 	list_for_each_entry(m, metric_list, nd) {
1402 		int i;
1403 
1404 		perf_tool_event__for_each_event(i) {
1405 			struct expr_id_data *data;
1406 
1407 			if (!tool_events[i] &&
1408 			    !expr__get_id(m->pctx, perf_tool_event__to_str(i), &data))
1409 				tool_events[i] = true;
1410 		}
1411 	}
1412 }
1413 
1414 /**
1415  * build_combined_expr_ctx - Make an expr_parse_ctx with all has_constraint
1416  *                           metric IDs, as the IDs are held in a set,
1417  *                           duplicates will be removed.
1418  * @metric_list: List to take metrics from.
1419  * @combined: Out argument for result.
1420  */
1421 static int build_combined_expr_ctx(const struct list_head *metric_list,
1422 				   struct expr_parse_ctx **combined)
1423 {
1424 	struct hashmap_entry *cur;
1425 	size_t bkt;
1426 	struct metric *m;
1427 	char *dup;
1428 	int ret;
1429 
1430 	*combined = expr__ctx_new();
1431 	if (!*combined)
1432 		return -ENOMEM;
1433 
1434 	list_for_each_entry(m, metric_list, nd) {
1435 		if (m->has_constraint && !m->modifier) {
1436 			hashmap__for_each_entry(m->pctx->ids, cur, bkt) {
1437 				dup = strdup(cur->key);
1438 				if (!dup) {
1439 					ret = -ENOMEM;
1440 					goto err_out;
1441 				}
1442 				ret = expr__add_id(*combined, dup);
1443 				if (ret)
1444 					goto err_out;
1445 			}
1446 		}
1447 	}
1448 	return 0;
1449 err_out:
1450 	expr__ctx_free(*combined);
1451 	*combined = NULL;
1452 	return ret;
1453 }
1454 
1455 /**
1456  * parse_ids - Build the event string for the ids and parse them creating an
1457  *             evlist. The encoded metric_ids are decoded.
1458  * @metric_no_merge: is metric sharing explicitly disabled.
1459  * @fake_pmu: used when testing metrics not supported by the current CPU.
1460  * @ids: the event identifiers parsed from a metric.
1461  * @modifier: any modifiers added to the events.
1462  * @has_constraint: false if events should be placed in a weak group.
1463  * @tool_events: entries set true if the tool event of index could be present in
1464  *               the overall list of metrics.
1465  * @out_evlist: the created list of events.
1466  */
1467 static int parse_ids(bool metric_no_merge, struct perf_pmu *fake_pmu,
1468 		     struct expr_parse_ctx *ids, const char *modifier,
1469 		     bool has_constraint, const bool tool_events[PERF_TOOL_MAX],
1470 		     struct evlist **out_evlist)
1471 {
1472 	struct parse_events_error parse_error;
1473 	struct evlist *parsed_evlist;
1474 	struct strbuf events = STRBUF_INIT;
1475 	int ret;
1476 
1477 	*out_evlist = NULL;
1478 	if (!metric_no_merge || hashmap__size(ids->ids) == 0) {
1479 		bool added_event = false;
1480 		int i;
1481 		/*
1482 		 * We may fail to share events between metrics because a tool
1483 		 * event isn't present in one metric. For example, a ratio of
1484 		 * cache misses doesn't need duration_time but the same events
1485 		 * may be used for a misses per second. Events without sharing
1486 		 * implies multiplexing, that is best avoided, so place
1487 		 * all tool events in every group.
1488 		 *
1489 		 * Also, there may be no ids/events in the expression parsing
1490 		 * context because of constant evaluation, e.g.:
1491 		 *    event1 if #smt_on else 0
1492 		 * Add a tool event to avoid a parse error on an empty string.
1493 		 */
1494 		perf_tool_event__for_each_event(i) {
1495 			if (tool_events[i]) {
1496 				char *tmp = strdup(perf_tool_event__to_str(i));
1497 
1498 				if (!tmp)
1499 					return -ENOMEM;
1500 				ids__insert(ids->ids, tmp);
1501 				added_event = true;
1502 			}
1503 		}
1504 		if (!added_event && hashmap__size(ids->ids) == 0) {
1505 			char *tmp = strdup("duration_time");
1506 
1507 			if (!tmp)
1508 				return -ENOMEM;
1509 			ids__insert(ids->ids, tmp);
1510 		}
1511 	}
1512 	ret = metricgroup__build_event_string(&events, ids, modifier,
1513 					      has_constraint);
1514 	if (ret)
1515 		return ret;
1516 
1517 	parsed_evlist = evlist__new();
1518 	if (!parsed_evlist) {
1519 		ret = -ENOMEM;
1520 		goto err_out;
1521 	}
1522 	pr_debug("Parsing metric events '%s'\n", events.buf);
1523 	parse_events_error__init(&parse_error);
1524 	ret = __parse_events(parsed_evlist, events.buf, &parse_error, fake_pmu);
1525 	if (ret) {
1526 		parse_events_error__print(&parse_error, events.buf);
1527 		goto err_out;
1528 	}
1529 	ret = decode_all_metric_ids(parsed_evlist, modifier);
1530 	if (ret)
1531 		goto err_out;
1532 
1533 	*out_evlist = parsed_evlist;
1534 	parsed_evlist = NULL;
1535 err_out:
1536 	parse_events_error__exit(&parse_error);
1537 	evlist__delete(parsed_evlist);
1538 	strbuf_release(&events);
1539 	return ret;
1540 }
1541 
1542 static int parse_groups(struct evlist *perf_evlist, const char *str,
1543 			bool metric_no_group,
1544 			bool metric_no_merge,
1545 			const char *user_requested_cpu_list,
1546 			bool system_wide,
1547 			struct perf_pmu *fake_pmu,
1548 			struct rblist *metric_events_list,
1549 			const struct pmu_events_table *table)
1550 {
1551 	struct evlist *combined_evlist = NULL;
1552 	LIST_HEAD(metric_list);
1553 	struct metric *m;
1554 	bool tool_events[PERF_TOOL_MAX] = {false};
1555 	int ret;
1556 
1557 	if (metric_events_list->nr_entries == 0)
1558 		metricgroup__rblist_init(metric_events_list);
1559 	ret = metricgroup__add_metric_list(str, metric_no_group,
1560 					   user_requested_cpu_list,
1561 					   system_wide, &metric_list, table);
1562 	if (ret)
1563 		goto out;
1564 
1565 	/* Sort metrics from largest to smallest. */
1566 	list_sort(NULL, &metric_list, metric_list_cmp);
1567 
1568 	if (!metric_no_merge) {
1569 		struct expr_parse_ctx *combined = NULL;
1570 
1571 		find_tool_events(&metric_list, tool_events);
1572 
1573 		ret = build_combined_expr_ctx(&metric_list, &combined);
1574 
1575 		if (!ret && combined && hashmap__size(combined->ids)) {
1576 			ret = parse_ids(metric_no_merge, fake_pmu, combined,
1577 					/*modifier=*/NULL,
1578 					/*has_constraint=*/true,
1579 					tool_events,
1580 					&combined_evlist);
1581 		}
1582 		if (combined)
1583 			expr__ctx_free(combined);
1584 
1585 		if (ret)
1586 			goto out;
1587 	}
1588 
1589 	list_for_each_entry(m, &metric_list, nd) {
1590 		struct metric_event *me;
1591 		struct evsel **metric_events;
1592 		struct evlist *metric_evlist = NULL;
1593 		struct metric *n;
1594 		struct metric_expr *expr;
1595 
1596 		if (combined_evlist && m->has_constraint) {
1597 			metric_evlist = combined_evlist;
1598 		} else if (!metric_no_merge) {
1599 			/*
1600 			 * See if the IDs for this metric are a subset of an
1601 			 * earlier metric.
1602 			 */
1603 			list_for_each_entry(n, &metric_list, nd) {
1604 				if (m == n)
1605 					break;
1606 
1607 				if (n->evlist == NULL)
1608 					continue;
1609 
1610 				if ((!m->modifier && n->modifier) ||
1611 				    (m->modifier && !n->modifier) ||
1612 				    (m->modifier && n->modifier &&
1613 					    strcmp(m->modifier, n->modifier)))
1614 					continue;
1615 
1616 				if (expr__subset_of_ids(n->pctx, m->pctx)) {
1617 					pr_debug("Events in '%s' fully contained within '%s'\n",
1618 						 m->metric_name, n->metric_name);
1619 					metric_evlist = n->evlist;
1620 					break;
1621 				}
1622 
1623 			}
1624 		}
1625 		if (!metric_evlist) {
1626 			ret = parse_ids(metric_no_merge, fake_pmu, m->pctx, m->modifier,
1627 					m->has_constraint, tool_events, &m->evlist);
1628 			if (ret)
1629 				goto out;
1630 
1631 			metric_evlist = m->evlist;
1632 		}
1633 		ret = setup_metric_events(m->pctx->ids, metric_evlist, &metric_events);
1634 		if (ret) {
1635 			pr_debug("Cannot resolve IDs for %s: %s\n",
1636 				m->metric_name, m->metric_expr);
1637 			goto out;
1638 		}
1639 
1640 		me = metricgroup__lookup(metric_events_list, metric_events[0], true);
1641 
1642 		expr = malloc(sizeof(struct metric_expr));
1643 		if (!expr) {
1644 			ret = -ENOMEM;
1645 			free(metric_events);
1646 			goto out;
1647 		}
1648 
1649 		expr->metric_refs = m->metric_refs;
1650 		m->metric_refs = NULL;
1651 		expr->metric_expr = m->metric_expr;
1652 		if (m->modifier) {
1653 			char *tmp;
1654 
1655 			if (asprintf(&tmp, "%s:%s", m->metric_name, m->modifier) < 0)
1656 				expr->metric_name = NULL;
1657 			else
1658 				expr->metric_name = tmp;
1659 		} else
1660 			expr->metric_name = strdup(m->metric_name);
1661 
1662 		if (!expr->metric_name) {
1663 			ret = -ENOMEM;
1664 			free(metric_events);
1665 			goto out;
1666 		}
1667 		expr->metric_unit = m->metric_unit;
1668 		expr->metric_events = metric_events;
1669 		expr->runtime = m->pctx->sctx.runtime;
1670 		list_add(&expr->nd, &me->head);
1671 	}
1672 
1673 
1674 	if (combined_evlist) {
1675 		evlist__splice_list_tail(perf_evlist, &combined_evlist->core.entries);
1676 		evlist__delete(combined_evlist);
1677 	}
1678 
1679 	list_for_each_entry(m, &metric_list, nd) {
1680 		if (m->evlist)
1681 			evlist__splice_list_tail(perf_evlist, &m->evlist->core.entries);
1682 	}
1683 
1684 out:
1685 	metricgroup__free_metrics(&metric_list);
1686 	return ret;
1687 }
1688 
1689 int metricgroup__parse_groups(struct evlist *perf_evlist,
1690 			      const char *str,
1691 			      bool metric_no_group,
1692 			      bool metric_no_merge,
1693 			      const char *user_requested_cpu_list,
1694 			      bool system_wide,
1695 			      struct rblist *metric_events)
1696 {
1697 	const struct pmu_events_table *table = pmu_events_table__find();
1698 
1699 	if (!table)
1700 		return -EINVAL;
1701 
1702 	return parse_groups(perf_evlist, str, metric_no_group, metric_no_merge,
1703 			    user_requested_cpu_list, system_wide,
1704 			    /*fake_pmu=*/NULL, metric_events, table);
1705 }
1706 
1707 int metricgroup__parse_groups_test(struct evlist *evlist,
1708 				   const struct pmu_events_table *table,
1709 				   const char *str,
1710 				   bool metric_no_group,
1711 				   bool metric_no_merge,
1712 				   struct rblist *metric_events)
1713 {
1714 	return parse_groups(evlist, str, metric_no_group, metric_no_merge,
1715 			    /*user_requested_cpu_list=*/NULL,
1716 			    /*system_wide=*/false,
1717 			    &perf_pmu__fake, metric_events, table);
1718 }
1719 
1720 static int metricgroup__has_metric_callback(const struct pmu_event *pe,
1721 					    const struct pmu_events_table *table __maybe_unused,
1722 					    void *vdata)
1723 {
1724 	const char *metric = vdata;
1725 
1726 	if (!pe->metric_expr)
1727 		return 0;
1728 
1729 	if (match_metric(pe->metric_name, metric))
1730 		return 1;
1731 
1732 	return 0;
1733 }
1734 
1735 bool metricgroup__has_metric(const char *metric)
1736 {
1737 	const struct pmu_events_table *table = pmu_events_table__find();
1738 
1739 	if (!table)
1740 		return false;
1741 
1742 	return pmu_events_table_for_each_event(table, metricgroup__has_metric_callback,
1743 					       (void *)metric) ? true : false;
1744 }
1745 
1746 int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp,
1747 				    struct rblist *new_metric_events,
1748 				    struct rblist *old_metric_events)
1749 {
1750 	unsigned int i;
1751 
1752 	for (i = 0; i < rblist__nr_entries(old_metric_events); i++) {
1753 		struct rb_node *nd;
1754 		struct metric_event *old_me, *new_me;
1755 		struct metric_expr *old_expr, *new_expr;
1756 		struct evsel *evsel;
1757 		size_t alloc_size;
1758 		int idx, nr;
1759 
1760 		nd = rblist__entry(old_metric_events, i);
1761 		old_me = container_of(nd, struct metric_event, nd);
1762 
1763 		evsel = evlist__find_evsel(evlist, old_me->evsel->core.idx);
1764 		if (!evsel)
1765 			return -EINVAL;
1766 		new_me = metricgroup__lookup(new_metric_events, evsel, true);
1767 		if (!new_me)
1768 			return -ENOMEM;
1769 
1770 		pr_debug("copying metric event for cgroup '%s': %s (idx=%d)\n",
1771 			 cgrp ? cgrp->name : "root", evsel->name, evsel->core.idx);
1772 
1773 		list_for_each_entry(old_expr, &old_me->head, nd) {
1774 			new_expr = malloc(sizeof(*new_expr));
1775 			if (!new_expr)
1776 				return -ENOMEM;
1777 
1778 			new_expr->metric_expr = old_expr->metric_expr;
1779 			new_expr->metric_name = strdup(old_expr->metric_name);
1780 			if (!new_expr->metric_name)
1781 				return -ENOMEM;
1782 
1783 			new_expr->metric_unit = old_expr->metric_unit;
1784 			new_expr->runtime = old_expr->runtime;
1785 
1786 			if (old_expr->metric_refs) {
1787 				/* calculate number of metric_events */
1788 				for (nr = 0; old_expr->metric_refs[nr].metric_name; nr++)
1789 					continue;
1790 				alloc_size = sizeof(*new_expr->metric_refs);
1791 				new_expr->metric_refs = calloc(nr + 1, alloc_size);
1792 				if (!new_expr->metric_refs) {
1793 					free(new_expr);
1794 					return -ENOMEM;
1795 				}
1796 
1797 				memcpy(new_expr->metric_refs, old_expr->metric_refs,
1798 				       nr * alloc_size);
1799 			} else {
1800 				new_expr->metric_refs = NULL;
1801 			}
1802 
1803 			/* calculate number of metric_events */
1804 			for (nr = 0; old_expr->metric_events[nr]; nr++)
1805 				continue;
1806 			alloc_size = sizeof(*new_expr->metric_events);
1807 			new_expr->metric_events = calloc(nr + 1, alloc_size);
1808 			if (!new_expr->metric_events) {
1809 				free(new_expr->metric_refs);
1810 				free(new_expr);
1811 				return -ENOMEM;
1812 			}
1813 
1814 			/* copy evsel in the same position */
1815 			for (idx = 0; idx < nr; idx++) {
1816 				evsel = old_expr->metric_events[idx];
1817 				evsel = evlist__find_evsel(evlist, evsel->core.idx);
1818 				if (evsel == NULL) {
1819 					free(new_expr->metric_events);
1820 					free(new_expr->metric_refs);
1821 					free(new_expr);
1822 					return -EINVAL;
1823 				}
1824 				new_expr->metric_events[idx] = evsel;
1825 			}
1826 
1827 			list_add(&new_expr->nd, &new_me->head);
1828 		}
1829 	}
1830 	return 0;
1831 }
1832