xref: /openbmc/linux/tools/perf/util/print-events.c (revision 5ee9cd065836e5934710ca35653bce7905add20b)
19b7c7728SIan Rogers // SPDX-License-Identifier: GPL-2.0
29b7c7728SIan Rogers #include <dirent.h>
39b7c7728SIan Rogers #include <errno.h>
49b7c7728SIan Rogers #include <stdio.h>
59b7c7728SIan Rogers #include <stdlib.h>
69b7c7728SIan Rogers #include <string.h>
700462d8eSNamhyung Kim #include <fcntl.h>
89b7c7728SIan Rogers #include <sys/param.h>
900462d8eSNamhyung Kim #include <unistd.h>
109b7c7728SIan Rogers 
119b7c7728SIan Rogers #include <api/fs/tracing_path.h>
129b7c7728SIan Rogers #include <linux/stddef.h>
139b7c7728SIan Rogers #include <linux/perf_event.h>
149b7c7728SIan Rogers #include <linux/zalloc.h>
159b7c7728SIan Rogers #include <subcmd/pager.h>
169b7c7728SIan Rogers 
179b7c7728SIan Rogers #include "build-id.h"
189b7c7728SIan Rogers #include "debug.h"
199b7c7728SIan Rogers #include "evsel.h"
209b7c7728SIan Rogers #include "metricgroup.h"
219b7c7728SIan Rogers #include "parse-events.h"
229b7c7728SIan Rogers #include "pmu.h"
231eaf496eSIan Rogers #include "pmus.h"
249b7c7728SIan Rogers #include "print-events.h"
259b7c7728SIan Rogers #include "probe-file.h"
269b7c7728SIan Rogers #include "string2.h"
279b7c7728SIan Rogers #include "strlist.h"
289b7c7728SIan Rogers #include "tracepoint.h"
299b7c7728SIan Rogers #include "pfm.h"
309a1bc9eaSIan Rogers #include "thread_map.h"
319b7c7728SIan Rogers 
329b7c7728SIan Rogers #define MAX_NAME_LEN 100
339b7c7728SIan Rogers 
34e5c6109fSIan Rogers /** Strings corresponding to enum perf_type_id. */
359b7c7728SIan Rogers static const char * const event_type_descriptors[] = {
369b7c7728SIan Rogers 	"Hardware event",
379b7c7728SIan Rogers 	"Software event",
389b7c7728SIan Rogers 	"Tracepoint event",
399b7c7728SIan Rogers 	"Hardware cache event",
409b7c7728SIan Rogers 	"Raw hardware event descriptor",
419b7c7728SIan Rogers 	"Hardware breakpoint",
429b7c7728SIan Rogers };
439b7c7728SIan Rogers 
449b7c7728SIan Rogers static const struct event_symbol event_symbols_tool[PERF_TOOL_MAX] = {
459b7c7728SIan Rogers 	[PERF_TOOL_DURATION_TIME] = {
469b7c7728SIan Rogers 		.symbol = "duration_time",
479b7c7728SIan Rogers 		.alias  = "",
489b7c7728SIan Rogers 	},
499b7c7728SIan Rogers 	[PERF_TOOL_USER_TIME] = {
509b7c7728SIan Rogers 		.symbol = "user_time",
519b7c7728SIan Rogers 		.alias  = "",
529b7c7728SIan Rogers 	},
539b7c7728SIan Rogers 	[PERF_TOOL_SYSTEM_TIME] = {
549b7c7728SIan Rogers 		.symbol = "system_time",
559b7c7728SIan Rogers 		.alias  = "",
569b7c7728SIan Rogers 	},
579b7c7728SIan Rogers };
589b7c7728SIan Rogers 
599b7c7728SIan Rogers /*
609b7c7728SIan Rogers  * Print the events from <debugfs_mount_point>/tracing/events
619b7c7728SIan Rogers  */
print_tracepoint_events(const struct print_callbacks * print_cb __maybe_unused,void * print_state __maybe_unused)6200462d8eSNamhyung Kim void print_tracepoint_events(const struct print_callbacks *print_cb __maybe_unused, void *print_state __maybe_unused)
6300462d8eSNamhyung Kim {
6400462d8eSNamhyung Kim 	char *events_path = get_tracing_file("events");
6500462d8eSNamhyung Kim 	int events_fd = open(events_path, O_PATH);
6600462d8eSNamhyung Kim 
6700462d8eSNamhyung Kim 	put_tracing_file(events_path);
6800462d8eSNamhyung Kim 	if (events_fd < 0) {
6900462d8eSNamhyung Kim 		printf("Error: failed to open tracing events directory\n");
7000462d8eSNamhyung Kim 		return;
7100462d8eSNamhyung Kim 	}
7200462d8eSNamhyung Kim 
7300462d8eSNamhyung Kim #ifdef HAVE_SCANDIRAT_SUPPORT
749b7c7728SIan Rogers {
75d74060c0SIan Rogers 	struct dirent **sys_namelist = NULL;
76d74060c0SIan Rogers 	int sys_items = tracing_events__scandir_alphasort(&sys_namelist);
77d74060c0SIan Rogers 
78d74060c0SIan Rogers 	for (int i = 0; i < sys_items; i++) {
79d74060c0SIan Rogers 		struct dirent *sys_dirent = sys_namelist[i];
80d74060c0SIan Rogers 		struct dirent **evt_namelist = NULL;
8100462d8eSNamhyung Kim 		int dir_fd;
82d74060c0SIan Rogers 		int evt_items;
839b7c7728SIan Rogers 
84d74060c0SIan Rogers 		if (sys_dirent->d_type != DT_DIR ||
85d74060c0SIan Rogers 		    !strcmp(sys_dirent->d_name, ".") ||
86d74060c0SIan Rogers 		    !strcmp(sys_dirent->d_name, ".."))
877586d11dSNamhyung Kim 			goto next_sys;
889b7c7728SIan Rogers 
8900462d8eSNamhyung Kim 		dir_fd = openat(events_fd, sys_dirent->d_name, O_PATH);
9000462d8eSNamhyung Kim 		if (dir_fd < 0)
917586d11dSNamhyung Kim 			goto next_sys;
929b7c7728SIan Rogers 
9300462d8eSNamhyung Kim 		evt_items = scandirat(events_fd, sys_dirent->d_name, &evt_namelist, NULL, alphasort);
94d74060c0SIan Rogers 		for (int j = 0; j < evt_items; j++) {
95d74060c0SIan Rogers 			struct dirent *evt_dirent = evt_namelist[j];
96d74060c0SIan Rogers 			char evt_path[MAXPATHLEN];
9700462d8eSNamhyung Kim 			int evt_fd;
98d74060c0SIan Rogers 
99d74060c0SIan Rogers 			if (evt_dirent->d_type != DT_DIR ||
100d74060c0SIan Rogers 			    !strcmp(evt_dirent->d_name, ".") ||
101d74060c0SIan Rogers 			    !strcmp(evt_dirent->d_name, ".."))
1027586d11dSNamhyung Kim 				goto next_evt;
103d74060c0SIan Rogers 
10400462d8eSNamhyung Kim 			snprintf(evt_path, sizeof(evt_path), "%s/id", evt_dirent->d_name);
10500462d8eSNamhyung Kim 			evt_fd = openat(dir_fd, evt_path, O_RDONLY);
10600462d8eSNamhyung Kim 			if (evt_fd < 0)
1077586d11dSNamhyung Kim 				goto next_evt;
10800462d8eSNamhyung Kim 			close(evt_fd);
109d74060c0SIan Rogers 
1109b7c7728SIan Rogers 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
1119b7c7728SIan Rogers 				 sys_dirent->d_name, evt_dirent->d_name);
112e5c6109fSIan Rogers 			print_cb->print_event(print_state,
113e5c6109fSIan Rogers 					/*topic=*/NULL,
114e5c6109fSIan Rogers 					/*pmu_name=*/NULL,
115e5c6109fSIan Rogers 					evt_path,
116e5c6109fSIan Rogers 					/*event_alias=*/NULL,
117e5c6109fSIan Rogers 					/*scale_unit=*/NULL,
118e5c6109fSIan Rogers 					/*deprecated=*/false,
119e5c6109fSIan Rogers 					"Tracepoint event",
120e5c6109fSIan Rogers 					/*desc=*/NULL,
121e5c6109fSIan Rogers 					/*long_desc=*/NULL,
122d9dc8874SIan Rogers 					/*encoding_desc=*/NULL);
1237586d11dSNamhyung Kim next_evt:
1247586d11dSNamhyung Kim 			free(evt_namelist[j]);
125d74060c0SIan Rogers 		}
12600462d8eSNamhyung Kim 		close(dir_fd);
127d74060c0SIan Rogers 		free(evt_namelist);
1287586d11dSNamhyung Kim next_sys:
1297586d11dSNamhyung Kim 		free(sys_namelist[i]);
130d74060c0SIan Rogers 	}
13100462d8eSNamhyung Kim 
132d74060c0SIan Rogers 	free(sys_namelist);
1339b7c7728SIan Rogers }
13400462d8eSNamhyung Kim #else
1356a7b57d8SNamhyung Kim 	printf("\nWARNING: Your libc doesn't have the scandirat function, please ask its maintainers to implement it.\n"
13600462d8eSNamhyung Kim 	       "         As a rough fallback, please do 'ls %s' to see the available tracepoint events.\n", events_path);
13700462d8eSNamhyung Kim #endif
13800462d8eSNamhyung Kim 	close(events_fd);
13900462d8eSNamhyung Kim }
1409b7c7728SIan Rogers 
print_sdt_events(const struct print_callbacks * print_cb,void * print_state)141e5c6109fSIan Rogers void print_sdt_events(const struct print_callbacks *print_cb, void *print_state)
1429b7c7728SIan Rogers {
1439b7c7728SIan Rogers 	struct strlist *bidlist, *sdtlist;
144e5c6109fSIan Rogers 	struct str_node *bid_nd, *sdt_name, *next_sdt_name;
145e5c6109fSIan Rogers 	const char *last_sdt_name = NULL;
1469b7c7728SIan Rogers 
147e5c6109fSIan Rogers 	/*
148e5c6109fSIan Rogers 	 * The implicitly sorted sdtlist will hold the tracepoint name followed
149e5c6109fSIan Rogers 	 * by @<buildid>. If the tracepoint name is unique (determined by
150e5c6109fSIan Rogers 	 * looking at the adjacent nodes) the @<buildid> is dropped otherwise
151e5c6109fSIan Rogers 	 * the executable path and buildid are added to the name.
152e5c6109fSIan Rogers 	 */
153e5c6109fSIan Rogers 	sdtlist = strlist__new(NULL, NULL);
1549b7c7728SIan Rogers 	if (!sdtlist) {
1559b7c7728SIan Rogers 		pr_debug("Failed to allocate new strlist for SDT\n");
1569b7c7728SIan Rogers 		return;
1579b7c7728SIan Rogers 	}
1589b7c7728SIan Rogers 	bidlist = build_id_cache__list_all(true);
1599b7c7728SIan Rogers 	if (!bidlist) {
1609b7c7728SIan Rogers 		pr_debug("Failed to get buildids: %d\n", errno);
1619b7c7728SIan Rogers 		return;
1629b7c7728SIan Rogers 	}
163e5c6109fSIan Rogers 	strlist__for_each_entry(bid_nd, bidlist) {
164e5c6109fSIan Rogers 		struct probe_cache *pcache;
165e5c6109fSIan Rogers 		struct probe_cache_entry *ent;
166e5c6109fSIan Rogers 
167e5c6109fSIan Rogers 		pcache = probe_cache__new(bid_nd->s, NULL);
1689b7c7728SIan Rogers 		if (!pcache)
1699b7c7728SIan Rogers 			continue;
1709b7c7728SIan Rogers 		list_for_each_entry(ent, &pcache->entries, node) {
171e5c6109fSIan Rogers 			char buf[1024];
172e5c6109fSIan Rogers 
173e5c6109fSIan Rogers 			snprintf(buf, sizeof(buf), "%s:%s@%s",
174e5c6109fSIan Rogers 				 ent->pev.group, ent->pev.event, bid_nd->s);
1759b7c7728SIan Rogers 			strlist__add(sdtlist, buf);
1769b7c7728SIan Rogers 		}
1779b7c7728SIan Rogers 		probe_cache__delete(pcache);
1789b7c7728SIan Rogers 	}
1799b7c7728SIan Rogers 	strlist__delete(bidlist);
1809b7c7728SIan Rogers 
181e5c6109fSIan Rogers 	strlist__for_each_entry(sdt_name, sdtlist) {
182e5c6109fSIan Rogers 		bool show_detail = false;
183e5c6109fSIan Rogers 		char *bid = strchr(sdt_name->s, '@');
184e5c6109fSIan Rogers 		char *evt_name = NULL;
185e5c6109fSIan Rogers 
186e5c6109fSIan Rogers 		if (bid)
187e5c6109fSIan Rogers 			*(bid++) = '\0';
188e5c6109fSIan Rogers 
189e5c6109fSIan Rogers 		if (last_sdt_name && !strcmp(last_sdt_name, sdt_name->s)) {
1909b7c7728SIan Rogers 			show_detail = true;
191e5c6109fSIan Rogers 		} else {
192e5c6109fSIan Rogers 			next_sdt_name = strlist__next(sdt_name);
193e5c6109fSIan Rogers 			if (next_sdt_name) {
194e5c6109fSIan Rogers 				char *bid2 = strchr(next_sdt_name->s, '@');
195e5c6109fSIan Rogers 
196e5c6109fSIan Rogers 				if (bid2)
197e5c6109fSIan Rogers 					*bid2 = '\0';
198e5c6109fSIan Rogers 				if (strcmp(sdt_name->s, next_sdt_name->s) == 0)
199e5c6109fSIan Rogers 					show_detail = true;
200e5c6109fSIan Rogers 				if (bid2)
201e5c6109fSIan Rogers 					*bid2 = '@';
2029b7c7728SIan Rogers 			}
203e5c6109fSIan Rogers 		}
204e5c6109fSIan Rogers 		last_sdt_name = sdt_name->s;
205e5c6109fSIan Rogers 
2069b7c7728SIan Rogers 		if (show_detail) {
207e5c6109fSIan Rogers 			char *path = build_id_cache__origname(bid);
208e5c6109fSIan Rogers 
209e5c6109fSIan Rogers 			if (path) {
210e5c6109fSIan Rogers 				if (asprintf(&evt_name, "%s@%s(%.12s)", sdt_name->s, path, bid) < 0)
211e5c6109fSIan Rogers 					evt_name = NULL;
2129b7c7728SIan Rogers 				free(path);
2139b7c7728SIan Rogers 			}
2149b7c7728SIan Rogers 		}
215e5c6109fSIan Rogers 		print_cb->print_event(print_state,
216e5c6109fSIan Rogers 				/*topic=*/NULL,
217e5c6109fSIan Rogers 				/*pmu_name=*/NULL,
218e5c6109fSIan Rogers 				evt_name ?: sdt_name->s,
219e5c6109fSIan Rogers 				/*event_alias=*/NULL,
220e5c6109fSIan Rogers 				/*deprecated=*/false,
221e5c6109fSIan Rogers 				/*scale_unit=*/NULL,
222e5c6109fSIan Rogers 				"SDT event",
223e5c6109fSIan Rogers 				/*desc=*/NULL,
224e5c6109fSIan Rogers 				/*long_desc=*/NULL,
225d9dc8874SIan Rogers 				/*encoding_desc=*/NULL);
226e5c6109fSIan Rogers 
227e5c6109fSIan Rogers 		free(evt_name);
228e5c6109fSIan Rogers 	}
2299b7c7728SIan Rogers 	strlist__delete(sdtlist);
2309b7c7728SIan Rogers }
2319b7c7728SIan Rogers 
is_event_supported(u8 type,u64 config)232e2be0666SArnaldo Carvalho de Melo bool is_event_supported(u8 type, u64 config)
2339a1bc9eaSIan Rogers {
2349a1bc9eaSIan Rogers 	bool ret = true;
2359a1bc9eaSIan Rogers 	struct evsel *evsel;
2369a1bc9eaSIan Rogers 	struct perf_event_attr attr = {
2379a1bc9eaSIan Rogers 		.type = type,
2389a1bc9eaSIan Rogers 		.config = config,
2399a1bc9eaSIan Rogers 		.disabled = 1,
2409a1bc9eaSIan Rogers 	};
2419a1bc9eaSIan Rogers 	struct perf_thread_map *tmap = thread_map__new_by_tid(0);
2429a1bc9eaSIan Rogers 
2439a1bc9eaSIan Rogers 	if (tmap == NULL)
2449a1bc9eaSIan Rogers 		return false;
2459a1bc9eaSIan Rogers 
2469a1bc9eaSIan Rogers 	evsel = evsel__new(&attr);
2479a1bc9eaSIan Rogers 	if (evsel) {
248*f88698d6SMark Rutland 		ret = evsel__open(evsel, NULL, tmap) >= 0;
2499a1bc9eaSIan Rogers 
250*f88698d6SMark Rutland 		if (!ret) {
2519a1bc9eaSIan Rogers 			/*
252*f88698d6SMark Rutland 			 * The event may fail to open if the paranoid value
2539a1bc9eaSIan Rogers 			 * /proc/sys/kernel/perf_event_paranoid is set to 2
254*f88698d6SMark Rutland 			 * Re-run with exclude_kernel set; we don't do that by
255*f88698d6SMark Rutland 			 * default as some ARM machines do not support it.
2569a1bc9eaSIan Rogers 			 */
2579a1bc9eaSIan Rogers 			evsel->core.attr.exclude_kernel = 1;
2589a1bc9eaSIan Rogers 			ret = evsel__open(evsel, NULL, tmap) >= 0;
2599a1bc9eaSIan Rogers 		}
260*f88698d6SMark Rutland 
261*f88698d6SMark Rutland 		if (!ret) {
262*f88698d6SMark Rutland 			/*
263*f88698d6SMark Rutland 			 * The event may fail to open if the PMU requires
264*f88698d6SMark Rutland 			 * exclude_guest to be set (e.g. as the Apple M1 PMU
265*f88698d6SMark Rutland 			 * requires).
266*f88698d6SMark Rutland 			 * Re-run with exclude_guest set; we don't do that by
267*f88698d6SMark Rutland 			 * default as it's equally legitimate for another PMU
268*f88698d6SMark Rutland 			 * driver to require that exclude_guest is clear.
269*f88698d6SMark Rutland 			 */
270*f88698d6SMark Rutland 			evsel->core.attr.exclude_guest = 1;
271*f88698d6SMark Rutland 			ret = evsel__open(evsel, NULL, tmap) >= 0;
272*f88698d6SMark Rutland 		}
273*f88698d6SMark Rutland 
2749a1bc9eaSIan Rogers 		evsel__delete(evsel);
2759a1bc9eaSIan Rogers 	}
2769a1bc9eaSIan Rogers 
2779a1bc9eaSIan Rogers 	perf_thread_map__put(tmap);
2789a1bc9eaSIan Rogers 	return ret;
2799a1bc9eaSIan Rogers }
2809a1bc9eaSIan Rogers 
print_hwcache_events(const struct print_callbacks * print_cb,void * print_state)281e5c6109fSIan Rogers int print_hwcache_events(const struct print_callbacks *print_cb, void *print_state)
2829b7c7728SIan Rogers {
283d7f21df0SIan Rogers 	struct perf_pmu *pmu = NULL;
284442eeb77SIan Rogers 	const char *event_type_descriptor = event_type_descriptors[PERF_TYPE_HW_CACHE];
2859b7c7728SIan Rogers 
286d7f21df0SIan Rogers 	/*
2879d6a1df9SIan Rogers 	 * Only print core PMUs, skipping uncore for performance and
2889d6a1df9SIan Rogers 	 * PERF_TYPE_SOFTWARE that can succeed in opening legacy cache evenst.
289d7f21df0SIan Rogers 	 */
2909d6a1df9SIan Rogers 	while ((pmu = perf_pmus__scan_core(pmu)) != NULL) {
291d7f21df0SIan Rogers 		if (pmu->is_uncore || pmu->type == PERF_TYPE_SOFTWARE)
292d7f21df0SIan Rogers 			continue;
293d7f21df0SIan Rogers 
2943301b3feSIan Rogers 		for (int type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
2953301b3feSIan Rogers 			for (int op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
2969b7c7728SIan Rogers 				/* skip invalid cache type */
2979b7c7728SIan Rogers 				if (!evsel__is_cache_op_valid(type, op))
2989b7c7728SIan Rogers 					continue;
2999b7c7728SIan Rogers 
300442eeb77SIan Rogers 				for (int res = 0; res < PERF_COUNT_HW_CACHE_RESULT_MAX; res++) {
3013301b3feSIan Rogers 					char name[64];
302d7f21df0SIan Rogers 					char alias_name[128];
303d7f21df0SIan Rogers 					__u64 config;
304d7f21df0SIan Rogers 					int ret;
3059b7c7728SIan Rogers 
306442eeb77SIan Rogers 					__evsel__hw_cache_type_op_res_name(type, op, res,
307442eeb77SIan Rogers 									name, sizeof(name));
308d7f21df0SIan Rogers 
309d7f21df0SIan Rogers 					ret = parse_events__decode_legacy_cache(name, pmu->type,
310d7f21df0SIan Rogers 										&config);
311d7f21df0SIan Rogers 					if (ret || !is_event_supported(PERF_TYPE_HW_CACHE, config))
312442eeb77SIan Rogers 						continue;
313d7f21df0SIan Rogers 					snprintf(alias_name, sizeof(alias_name), "%s/%s/",
314d7f21df0SIan Rogers 						 pmu->name, name);
315442eeb77SIan Rogers 					print_cb->print_event(print_state,
316442eeb77SIan Rogers 							"cache",
317442eeb77SIan Rogers 							pmu->name,
318442eeb77SIan Rogers 							name,
319d7f21df0SIan Rogers 							alias_name,
320442eeb77SIan Rogers 							/*scale_unit=*/NULL,
321442eeb77SIan Rogers 							/*deprecated=*/false,
322442eeb77SIan Rogers 							event_type_descriptor,
323442eeb77SIan Rogers 							/*desc=*/NULL,
324442eeb77SIan Rogers 							/*long_desc=*/NULL,
325442eeb77SIan Rogers 							/*encoding_desc=*/NULL);
326442eeb77SIan Rogers 				}
327442eeb77SIan Rogers 			}
328442eeb77SIan Rogers 		}
329442eeb77SIan Rogers 	}
3303301b3feSIan Rogers 	return 0;
3319b7c7728SIan Rogers }
3329b7c7728SIan Rogers 
print_tool_events(const struct print_callbacks * print_cb,void * print_state)333e5c6109fSIan Rogers void print_tool_events(const struct print_callbacks *print_cb, void *print_state)
3349b7c7728SIan Rogers {
3359b7c7728SIan Rogers 	// Start at 1 because the first enum entry means no tool event.
336e5c6109fSIan Rogers 	for (int i = 1; i < PERF_TOOL_MAX; ++i) {
337e5c6109fSIan Rogers 		print_cb->print_event(print_state,
338e5c6109fSIan Rogers 				"tool",
339e5c6109fSIan Rogers 				/*pmu_name=*/NULL,
340e5c6109fSIan Rogers 				event_symbols_tool[i].symbol,
341e5c6109fSIan Rogers 				event_symbols_tool[i].alias,
342e5c6109fSIan Rogers 				/*scale_unit=*/NULL,
343e5c6109fSIan Rogers 				/*deprecated=*/false,
344e5c6109fSIan Rogers 				"Tool event",
345e5c6109fSIan Rogers 				/*desc=*/NULL,
346e5c6109fSIan Rogers 				/*long_desc=*/NULL,
347d9dc8874SIan Rogers 				/*encoding_desc=*/NULL);
348e5c6109fSIan Rogers 	}
3499b7c7728SIan Rogers }
3509b7c7728SIan Rogers 
print_symbol_events(const struct print_callbacks * print_cb,void * print_state,unsigned int type,const struct event_symbol * syms,unsigned int max)351e5c6109fSIan Rogers void print_symbol_events(const struct print_callbacks *print_cb, void *print_state,
352e5c6109fSIan Rogers 			 unsigned int type, const struct event_symbol *syms,
353e5c6109fSIan Rogers 			 unsigned int max)
3549b7c7728SIan Rogers {
355de3752a7SIan Rogers 	struct strlist *evt_name_list = strlist__new(NULL, NULL);
356de3752a7SIan Rogers 	struct str_node *nd;
3579b7c7728SIan Rogers 
358de3752a7SIan Rogers 	if (!evt_name_list) {
359de3752a7SIan Rogers 		pr_debug("Failed to allocate new strlist for symbol events\n");
360de3752a7SIan Rogers 		return;
3619b7c7728SIan Rogers 	}
362de3752a7SIan Rogers 	for (unsigned int i = 0; i < max; i++) {
3639b7c7728SIan Rogers 		/*
3649b7c7728SIan Rogers 		 * New attr.config still not supported here, the latest
3659b7c7728SIan Rogers 		 * example was PERF_COUNT_SW_CGROUP_SWITCHES
3669b7c7728SIan Rogers 		 */
367de3752a7SIan Rogers 		if (syms[i].symbol == NULL)
3689b7c7728SIan Rogers 			continue;
3699b7c7728SIan Rogers 
3709b7c7728SIan Rogers 		if (!is_event_supported(type, i))
3719b7c7728SIan Rogers 			continue;
3729b7c7728SIan Rogers 
373de3752a7SIan Rogers 		if (strlen(syms[i].alias)) {
374de3752a7SIan Rogers 			char name[MAX_NAME_LEN];
375de3752a7SIan Rogers 
376de3752a7SIan Rogers 			snprintf(name, MAX_NAME_LEN, "%s OR %s", syms[i].symbol, syms[i].alias);
377de3752a7SIan Rogers 			strlist__add(evt_name_list, name);
378de3752a7SIan Rogers 		} else
379de3752a7SIan Rogers 			strlist__add(evt_name_list, syms[i].symbol);
3809b7c7728SIan Rogers 	}
3819b7c7728SIan Rogers 
382de3752a7SIan Rogers 	strlist__for_each_entry(nd, evt_name_list) {
383e5c6109fSIan Rogers 		char *alias = strstr(nd->s, " OR ");
3849b7c7728SIan Rogers 
385e5c6109fSIan Rogers 		if (alias) {
386e5c6109fSIan Rogers 			*alias = '\0';
387e5c6109fSIan Rogers 			alias += 4;
388e5c6109fSIan Rogers 		}
389e5c6109fSIan Rogers 		print_cb->print_event(print_state,
390e5c6109fSIan Rogers 				/*topic=*/NULL,
391e5c6109fSIan Rogers 				/*pmu_name=*/NULL,
392e5c6109fSIan Rogers 				nd->s,
393e5c6109fSIan Rogers 				alias,
394e5c6109fSIan Rogers 				/*scale_unit=*/NULL,
395e5c6109fSIan Rogers 				/*deprecated=*/false,
396e5c6109fSIan Rogers 				event_type_descriptors[type],
397e5c6109fSIan Rogers 				/*desc=*/NULL,
398e5c6109fSIan Rogers 				/*long_desc=*/NULL,
399d9dc8874SIan Rogers 				/*encoding_desc=*/NULL);
400e5c6109fSIan Rogers 	}
401de3752a7SIan Rogers 	strlist__delete(evt_name_list);
4029b7c7728SIan Rogers }
4039b7c7728SIan Rogers 
4049b7c7728SIan Rogers /*
4059b7c7728SIan Rogers  * Print the help text for the event symbols:
4069b7c7728SIan Rogers  */
print_events(const struct print_callbacks * print_cb,void * print_state)407e5c6109fSIan Rogers void print_events(const struct print_callbacks *print_cb, void *print_state)
4089b7c7728SIan Rogers {
409e5c6109fSIan Rogers 	print_symbol_events(print_cb, print_state, PERF_TYPE_HARDWARE,
410e5c6109fSIan Rogers 			event_symbols_hw, PERF_COUNT_HW_MAX);
411e5c6109fSIan Rogers 	print_symbol_events(print_cb, print_state, PERF_TYPE_SOFTWARE,
412e5c6109fSIan Rogers 			event_symbols_sw, PERF_COUNT_SW_MAX);
4139b7c7728SIan Rogers 
414e5c6109fSIan Rogers 	print_tool_events(print_cb, print_state);
4159b7c7728SIan Rogers 
416e5c6109fSIan Rogers 	print_hwcache_events(print_cb, print_state);
4179b7c7728SIan Rogers 
4181eaf496eSIan Rogers 	perf_pmus__print_pmu_events(print_cb, print_state);
4199b7c7728SIan Rogers 
420e5c6109fSIan Rogers 	print_cb->print_event(print_state,
421e5c6109fSIan Rogers 			/*topic=*/NULL,
422e5c6109fSIan Rogers 			/*pmu_name=*/NULL,
4239b7c7728SIan Rogers 			"rNNN",
424e5c6109fSIan Rogers 			/*event_alias=*/NULL,
425e5c6109fSIan Rogers 			/*scale_unit=*/NULL,
426e5c6109fSIan Rogers 			/*deprecated=*/false,
427e5c6109fSIan Rogers 			event_type_descriptors[PERF_TYPE_RAW],
428e5c6109fSIan Rogers 			/*desc=*/NULL,
429e5c6109fSIan Rogers 			/*long_desc=*/NULL,
430d9dc8874SIan Rogers 			/*encoding_desc=*/NULL);
431e5c6109fSIan Rogers 
432e5c6109fSIan Rogers 	print_cb->print_event(print_state,
433e5c6109fSIan Rogers 			/*topic=*/NULL,
434e5c6109fSIan Rogers 			/*pmu_name=*/NULL,
4359b7c7728SIan Rogers 			"cpu/t1=v1[,t2=v2,t3 ...]/modifier",
436e5c6109fSIan Rogers 			/*event_alias=*/NULL,
437e5c6109fSIan Rogers 			/*scale_unit=*/NULL,
438e5c6109fSIan Rogers 			/*deprecated=*/false,
439e5c6109fSIan Rogers 			event_type_descriptors[PERF_TYPE_RAW],
440e5c6109fSIan Rogers 			"(see 'man perf-list' on how to encode it)",
441e5c6109fSIan Rogers 			/*long_desc=*/NULL,
442d9dc8874SIan Rogers 			/*encoding_desc=*/NULL);
4439b7c7728SIan Rogers 
444e5c6109fSIan Rogers 	print_cb->print_event(print_state,
445e5c6109fSIan Rogers 			/*topic=*/NULL,
446e5c6109fSIan Rogers 			/*pmu_name=*/NULL,
4479b7c7728SIan Rogers 			"mem:<addr>[/len][:access]",
448e5c6109fSIan Rogers 			/*scale_unit=*/NULL,
449e5c6109fSIan Rogers 			/*event_alias=*/NULL,
450e5c6109fSIan Rogers 			/*deprecated=*/false,
451e5c6109fSIan Rogers 			event_type_descriptors[PERF_TYPE_BREAKPOINT],
452e5c6109fSIan Rogers 			/*desc=*/NULL,
453e5c6109fSIan Rogers 			/*long_desc=*/NULL,
454d9dc8874SIan Rogers 			/*encoding_desc=*/NULL);
4559b7c7728SIan Rogers 
456e5c6109fSIan Rogers 	print_tracepoint_events(print_cb, print_state);
4579b7c7728SIan Rogers 
458e5c6109fSIan Rogers 	print_sdt_events(print_cb, print_state);
4599b7c7728SIan Rogers 
460e5c6109fSIan Rogers 	metricgroup__print(print_cb, print_state);
4619b7c7728SIan Rogers 
462e5c6109fSIan Rogers 	print_libpfm_events(print_cb, print_state);
4639b7c7728SIan Rogers }
464