cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

metricgroup.c (43445B)


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