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