blob: 78b16100567d3a88a3e45abd0af05e68f64ee0cd [file] [log] [blame]
Jiri Olsacd82a322012-03-15 20:09:17 +01001#include <linux/list.h>
Sukadev Bhattiproluc5de47f2015-06-10 00:25:07 -07002#include <linux/compiler.h>
Jiri Olsacd82a322012-03-15 20:09:17 +01003#include <sys/types.h>
Jiri Olsacd82a322012-03-15 20:09:17 +01004#include <unistd.h>
5#include <stdio.h>
Adrian Hunterdc0a6202014-07-31 09:00:49 +03006#include <stdbool.h>
Adrian Hunter7d4bdab2014-07-31 09:00:50 +03007#include <stdarg.h>
Jiri Olsacd82a322012-03-15 20:09:17 +01008#include <dirent.h>
Borislav Petkovcd0cfad2013-12-09 17:14:24 +01009#include <api/fs/fs.h>
Stephane Eranian410136f2013-11-12 17:58:49 +010010#include <locale.h>
Jiri Olsacd82a322012-03-15 20:09:17 +010011#include "util.h"
12#include "pmu.h"
13#include "parse-events.h"
Yan, Zheng7ae92e72012-09-10 15:53:50 +080014#include "cpumap.h"
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -070015#include "header.h"
16#include "pmu-events/pmu-events.h"
Andi Kleen61eb2eb2016-09-15 15:24:44 -070017#include "cache.h"
Jiri Olsacd82a322012-03-15 20:09:17 +010018
Arnaldo Carvalho de Meloab1bf6532013-01-18 17:05:09 -030019struct perf_pmu_format {
20 char *name;
21 int value;
22 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
23 struct list_head list;
24};
25
Robert Richter50a96672012-08-16 21:10:24 +020026#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
27
Jiri Olsacd82a322012-03-15 20:09:17 +010028int perf_pmu_parse(struct list_head *list, char *name);
29extern FILE *perf_pmu_in;
30
31static LIST_HEAD(pmus);
32
33/*
34 * Parse & process all the sysfs attributes located under
35 * the directory specified in 'dir' parameter.
36 */
Jiri Olsacff7f952012-11-10 01:46:50 +010037int perf_pmu__format_parse(char *dir, struct list_head *head)
Jiri Olsacd82a322012-03-15 20:09:17 +010038{
39 struct dirent *evt_ent;
40 DIR *format_dir;
41 int ret = 0;
42
43 format_dir = opendir(dir);
44 if (!format_dir)
45 return -EINVAL;
46
47 while (!ret && (evt_ent = readdir(format_dir))) {
48 char path[PATH_MAX];
49 char *name = evt_ent->d_name;
50 FILE *file;
51
52 if (!strcmp(name, ".") || !strcmp(name, ".."))
53 continue;
54
55 snprintf(path, PATH_MAX, "%s/%s", dir, name);
56
57 ret = -EINVAL;
58 file = fopen(path, "r");
59 if (!file)
60 break;
61
62 perf_pmu_in = file;
63 ret = perf_pmu_parse(head, name);
64 fclose(file);
65 }
66
67 closedir(format_dir);
68 return ret;
69}
70
71/*
72 * Reading/parsing the default pmu format definition, which should be
73 * located at:
74 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
75 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +030076static int pmu_format(const char *name, struct list_head *format)
Jiri Olsacd82a322012-03-15 20:09:17 +010077{
78 struct stat st;
79 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -030080 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +010081
Jiri Olsacd82a322012-03-15 20:09:17 +010082 if (!sysfs)
83 return -1;
84
85 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +020086 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +010087
88 if (stat(path, &st) < 0)
Robert Richter9bc8f9f2012-06-14 22:38:37 +020089 return 0; /* no error if format does not exist */
Jiri Olsacd82a322012-03-15 20:09:17 +010090
Jiri Olsacff7f952012-11-10 01:46:50 +010091 if (perf_pmu__format_parse(path, format))
Jiri Olsacd82a322012-03-15 20:09:17 +010092 return -1;
93
94 return 0;
95}
96
Andi Kleend02fc6b2017-01-03 07:08:23 -080097static int convert_scale(const char *scale, char **end, double *sval)
98{
99 char *lc;
100 int ret = 0;
101
102 /*
103 * save current locale
104 */
105 lc = setlocale(LC_NUMERIC, NULL);
106
107 /*
108 * The lc string may be allocated in static storage,
109 * so get a dynamic copy to make it survive setlocale
110 * call below.
111 */
112 lc = strdup(lc);
113 if (!lc) {
114 ret = -ENOMEM;
115 goto out;
116 }
117
118 /*
119 * force to C locale to ensure kernel
120 * scale string is converted correctly.
121 * kernel uses default C locale.
122 */
123 setlocale(LC_NUMERIC, "C");
124
125 *sval = strtod(scale, end);
126
127out:
128 /* restore locale */
129 setlocale(LC_NUMERIC, lc);
130 free(lc);
131 return ret;
132}
133
Stephane Eranian410136f2013-11-12 17:58:49 +0100134static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
135{
136 struct stat st;
137 ssize_t sret;
138 char scale[128];
139 int fd, ret = -1;
140 char path[PATH_MAX];
Stephane Eranian410136f2013-11-12 17:58:49 +0100141
142 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
143
144 fd = open(path, O_RDONLY);
145 if (fd == -1)
146 return -1;
147
148 if (fstat(fd, &st) < 0)
149 goto error;
150
151 sret = read(fd, scale, sizeof(scale)-1);
152 if (sret < 0)
153 goto error;
154
Madhavan Srinivasan9ecae062015-05-31 11:36:23 +0530155 if (scale[sret - 1] == '\n')
156 scale[sret - 1] = '\0';
157 else
158 scale[sret] = '\0';
159
Andi Kleend02fc6b2017-01-03 07:08:23 -0800160 ret = convert_scale(scale, NULL, &alias->scale);
Stephane Eranian410136f2013-11-12 17:58:49 +0100161error:
162 close(fd);
163 return ret;
164}
165
166static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
167{
168 char path[PATH_MAX];
169 ssize_t sret;
170 int fd;
171
172 snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
173
174 fd = open(path, O_RDONLY);
175 if (fd == -1)
176 return -1;
177
Markus Trippelsdorfd85ce832015-12-14 16:44:40 +0100178 sret = read(fd, alias->unit, UNIT_MAX_LEN);
Stephane Eranian410136f2013-11-12 17:58:49 +0100179 if (sret < 0)
180 goto error;
181
182 close(fd);
183
Madhavan Srinivasan9ecae062015-05-31 11:36:23 +0530184 if (alias->unit[sret - 1] == '\n')
185 alias->unit[sret - 1] = '\0';
186 else
187 alias->unit[sret] = '\0';
Stephane Eranian410136f2013-11-12 17:58:49 +0100188
189 return 0;
190error:
191 close(fd);
192 alias->unit[0] = '\0';
193 return -1;
194}
195
Matt Fleming044330c2014-11-21 10:31:12 +0100196static int
197perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
198{
199 char path[PATH_MAX];
200 int fd;
201
202 snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
203
204 fd = open(path, O_RDONLY);
205 if (fd == -1)
206 return -1;
207
208 close(fd);
209
210 alias->per_pkg = true;
211 return 0;
212}
213
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100214static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
215 char *dir, char *name)
216{
217 char path[PATH_MAX];
218 int fd;
219
220 snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
221
222 fd = open(path, O_RDONLY);
223 if (fd == -1)
224 return -1;
225
226 alias->snapshot = true;
227 close(fd);
228 return 0;
229}
230
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700231static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
Andi Kleendd5f1032016-09-15 15:24:50 -0700232 char *desc, char *val, char *long_desc,
233 char *topic)
Zheng Yana6146d52012-06-15 14:31:41 +0800234{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300235 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800236 int ret;
237
Zheng Yana6146d52012-06-15 14:31:41 +0800238 alias = malloc(sizeof(*alias));
239 if (!alias)
240 return -ENOMEM;
241
242 INIT_LIST_HEAD(&alias->terms);
Stephane Eranian410136f2013-11-12 17:58:49 +0100243 alias->scale = 1.0;
244 alias->unit[0] = '\0';
Matt Fleming044330c2014-11-21 10:31:12 +0100245 alias->per_pkg = false;
Stephane Eranian84530922016-01-06 19:50:01 +0100246 alias->snapshot = false;
Stephane Eranian410136f2013-11-12 17:58:49 +0100247
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700248 ret = parse_events_terms(&alias->terms, val);
Zheng Yana6146d52012-06-15 14:31:41 +0800249 if (ret) {
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700250 pr_err("Cannot parse alias %s: %d\n", val, ret);
Zheng Yana6146d52012-06-15 14:31:41 +0800251 free(alias);
252 return ret;
253 }
254
255 alias->name = strdup(name);
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700256 if (dir) {
257 /*
258 * load unit name and scale if available
259 */
260 perf_pmu__parse_unit(alias, dir, name);
261 perf_pmu__parse_scale(alias, dir, name);
262 perf_pmu__parse_per_pkg(alias, dir, name);
263 perf_pmu__parse_snapshot(alias, dir, name);
264 }
Stephane Eranian410136f2013-11-12 17:58:49 +0100265
Andi Kleen08e60ed2016-09-15 15:24:43 -0700266 alias->desc = desc ? strdup(desc) : NULL;
Sukadev Bhattiproluc8d68282016-09-15 15:24:48 -0700267 alias->long_desc = long_desc ? strdup(long_desc) :
268 desc ? strdup(desc) : NULL;
Andi Kleendd5f1032016-09-15 15:24:50 -0700269 alias->topic = topic ? strdup(topic) : NULL;
Andi Kleen08e60ed2016-09-15 15:24:43 -0700270
Zheng Yana6146d52012-06-15 14:31:41 +0800271 list_add_tail(&alias->list, list);
Stephane Eranian410136f2013-11-12 17:58:49 +0100272
Zheng Yana6146d52012-06-15 14:31:41 +0800273 return 0;
274}
275
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700276static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
277{
278 char buf[256];
279 int ret;
280
281 ret = fread(buf, 1, sizeof(buf), file);
282 if (ret == 0)
283 return -EINVAL;
284
285 buf[ret] = 0;
286
Andi Kleendd5f1032016-09-15 15:24:50 -0700287 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL);
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700288}
289
Matt Fleming46441bd2014-09-24 15:04:06 +0100290static inline bool pmu_alias_info_file(char *name)
291{
292 size_t len;
293
294 len = strlen(name);
295 if (len > 5 && !strcmp(name + len - 5, ".unit"))
296 return true;
297 if (len > 6 && !strcmp(name + len - 6, ".scale"))
298 return true;
Matt Fleming044330c2014-11-21 10:31:12 +0100299 if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
300 return true;
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100301 if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
302 return true;
Matt Fleming46441bd2014-09-24 15:04:06 +0100303
304 return false;
305}
306
Zheng Yana6146d52012-06-15 14:31:41 +0800307/*
308 * Process all the sysfs attributes located under the directory
309 * specified in 'dir' parameter.
310 */
311static int pmu_aliases_parse(char *dir, struct list_head *head)
312{
313 struct dirent *evt_ent;
314 DIR *event_dir;
Zheng Yana6146d52012-06-15 14:31:41 +0800315
316 event_dir = opendir(dir);
317 if (!event_dir)
318 return -EINVAL;
319
Andi Kleen940db6d2016-02-17 14:44:55 -0800320 while ((evt_ent = readdir(event_dir))) {
Zheng Yana6146d52012-06-15 14:31:41 +0800321 char path[PATH_MAX];
322 char *name = evt_ent->d_name;
323 FILE *file;
324
325 if (!strcmp(name, ".") || !strcmp(name, ".."))
326 continue;
327
Stephane Eranian410136f2013-11-12 17:58:49 +0100328 /*
Matt Fleming46441bd2014-09-24 15:04:06 +0100329 * skip info files parsed in perf_pmu__new_alias()
Stephane Eranian410136f2013-11-12 17:58:49 +0100330 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100331 if (pmu_alias_info_file(name))
Stephane Eranian410136f2013-11-12 17:58:49 +0100332 continue;
333
Zheng Yana6146d52012-06-15 14:31:41 +0800334 snprintf(path, PATH_MAX, "%s/%s", dir, name);
335
Zheng Yana6146d52012-06-15 14:31:41 +0800336 file = fopen(path, "r");
Andi Kleen940db6d2016-02-17 14:44:55 -0800337 if (!file) {
338 pr_debug("Cannot open %s\n", path);
339 continue;
340 }
Stephane Eranian410136f2013-11-12 17:58:49 +0100341
Andi Kleen940db6d2016-02-17 14:44:55 -0800342 if (perf_pmu__new_alias(head, dir, name, file) < 0)
343 pr_debug("Cannot set up %s\n", name);
Zheng Yana6146d52012-06-15 14:31:41 +0800344 fclose(file);
345 }
346
347 closedir(event_dir);
Andi Kleen940db6d2016-02-17 14:44:55 -0800348 return 0;
Zheng Yana6146d52012-06-15 14:31:41 +0800349}
350
351/*
352 * Reading the pmu event aliases definition, which should be located at:
353 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
354 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300355static int pmu_aliases(const char *name, struct list_head *head)
Zheng Yana6146d52012-06-15 14:31:41 +0800356{
357 struct stat st;
358 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300359 const char *sysfs = sysfs__mountpoint();
Zheng Yana6146d52012-06-15 14:31:41 +0800360
Zheng Yana6146d52012-06-15 14:31:41 +0800361 if (!sysfs)
362 return -1;
363
364 snprintf(path, PATH_MAX,
365 "%s/bus/event_source/devices/%s/events", sysfs, name);
366
367 if (stat(path, &st) < 0)
Jiri Olsa3fded962012-10-10 14:53:16 +0200368 return 0; /* no error if 'events' does not exist */
Zheng Yana6146d52012-06-15 14:31:41 +0800369
370 if (pmu_aliases_parse(path, head))
371 return -1;
372
373 return 0;
374}
375
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300376static int pmu_alias_terms(struct perf_pmu_alias *alias,
Zheng Yana6146d52012-06-15 14:31:41 +0800377 struct list_head *terms)
378{
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200379 struct parse_events_term *term, *cloned;
Zheng Yana6146d52012-06-15 14:31:41 +0800380 LIST_HEAD(list);
381 int ret;
382
383 list_for_each_entry(term, &alias->terms, list) {
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200384 ret = parse_events_term__clone(&cloned, term);
Zheng Yana6146d52012-06-15 14:31:41 +0800385 if (ret) {
Arnaldo Carvalho de Melo682dc242016-02-12 16:48:00 -0300386 parse_events_terms__purge(&list);
Zheng Yana6146d52012-06-15 14:31:41 +0800387 return ret;
388 }
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200389 list_add_tail(&cloned->list, &list);
Zheng Yana6146d52012-06-15 14:31:41 +0800390 }
391 list_splice(&list, terms);
392 return 0;
393}
394
Jiri Olsacd82a322012-03-15 20:09:17 +0100395/*
396 * Reading/parsing the default pmu type value, which should be
397 * located at:
398 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
399 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300400static int pmu_type(const char *name, __u32 *type)
Jiri Olsacd82a322012-03-15 20:09:17 +0100401{
402 struct stat st;
403 char path[PATH_MAX];
Jiri Olsacd82a322012-03-15 20:09:17 +0100404 FILE *file;
405 int ret = 0;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300406 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +0100407
Jiri Olsacd82a322012-03-15 20:09:17 +0100408 if (!sysfs)
409 return -1;
410
411 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +0200412 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +0100413
414 if (stat(path, &st) < 0)
415 return -1;
416
417 file = fopen(path, "r");
418 if (!file)
419 return -EINVAL;
420
421 if (1 != fscanf(file, "%u", type))
422 ret = -1;
423
424 fclose(file);
425 return ret;
426}
427
Robert Richter50a96672012-08-16 21:10:24 +0200428/* Add all pmus in sysfs to pmu list: */
429static void pmu_read_sysfs(void)
430{
431 char path[PATH_MAX];
Robert Richter50a96672012-08-16 21:10:24 +0200432 DIR *dir;
433 struct dirent *dent;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300434 const char *sysfs = sysfs__mountpoint();
Robert Richter50a96672012-08-16 21:10:24 +0200435
Robert Richter50a96672012-08-16 21:10:24 +0200436 if (!sysfs)
437 return;
438
439 snprintf(path, PATH_MAX,
440 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
441
442 dir = opendir(path);
443 if (!dir)
444 return;
445
446 while ((dent = readdir(dir))) {
447 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
448 continue;
449 /* add to static LIST_HEAD(pmus): */
450 perf_pmu__find(dent->d_name);
451 }
452
453 closedir(dir);
454}
455
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300456static struct cpu_map *pmu_cpumask(const char *name)
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800457{
458 struct stat st;
459 char path[PATH_MAX];
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800460 FILE *file;
461 struct cpu_map *cpus;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300462 const char *sysfs = sysfs__mountpoint();
Mark Rutland7e3fcffe2016-09-08 11:21:52 +0100463 const char *templates[] = {
464 "%s/bus/event_source/devices/%s/cpumask",
465 "%s/bus/event_source/devices/%s/cpus",
466 NULL
467 };
468 const char **template;
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800469
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800470 if (!sysfs)
471 return NULL;
472
Mark Rutland7e3fcffe2016-09-08 11:21:52 +0100473 for (template = templates; *template; template++) {
474 snprintf(path, PATH_MAX, *template, sysfs, name);
475 if (stat(path, &st) == 0)
476 break;
477 }
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800478
Mark Rutland7e3fcffe2016-09-08 11:21:52 +0100479 if (!*template)
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800480 return NULL;
481
482 file = fopen(path, "r");
483 if (!file)
484 return NULL;
485
486 cpus = cpu_map__read(file);
487 fclose(file);
488 return cpus;
489}
490
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -0700491/*
492 * Return the CPU id as a raw string.
493 *
494 * Each architecture should provide a more precise id string that
495 * can be use to match the architecture's "mapfile".
496 */
497char * __weak get_cpuid_str(void)
498{
499 return NULL;
500}
501
502/*
503 * From the pmu_events_map, find the table of PMU events that corresponds
504 * to the current running CPU. Then, add all PMU events from that table
505 * as aliases.
506 */
507static void pmu_add_cpu_aliases(struct list_head *head)
508{
509 int i;
510 struct pmu_events_map *map;
511 struct pmu_event *pe;
512 char *cpuid;
Andi Kleenfb967062016-10-13 14:15:24 -0700513 static bool printed;
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -0700514
Andi Kleenfc06e2a2016-09-15 15:24:46 -0700515 cpuid = getenv("PERF_CPUID");
516 if (cpuid)
517 cpuid = strdup(cpuid);
518 if (!cpuid)
519 cpuid = get_cpuid_str();
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -0700520 if (!cpuid)
521 return;
522
Andi Kleenfb967062016-10-13 14:15:24 -0700523 if (!printed) {
524 pr_debug("Using CPUID %s\n", cpuid);
525 printed = true;
526 }
Andi Kleenfc06e2a2016-09-15 15:24:46 -0700527
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -0700528 i = 0;
529 while (1) {
530 map = &pmu_events_map[i++];
531 if (!map->table)
532 goto out;
533
534 if (!strcmp(map->cpuid, cpuid))
535 break;
536 }
537
538 /*
539 * Found a matching PMU events table. Create aliases
540 */
541 i = 0;
542 while (1) {
543 pe = &map->table[i++];
544 if (!pe->name)
545 break;
546
547 /* need type casts to override 'const' */
548 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
Sukadev Bhattiproluc8d68282016-09-15 15:24:48 -0700549 (char *)pe->desc, (char *)pe->event,
Andi Kleendd5f1032016-09-15 15:24:50 -0700550 (char *)pe->long_desc, (char *)pe->topic);
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -0700551 }
552
553out:
554 free(cpuid);
555}
556
Sukadev Bhattiproluc5de47f2015-06-10 00:25:07 -0700557struct perf_event_attr * __weak
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300558perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
559{
560 return NULL;
561}
562
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300563static struct perf_pmu *pmu_lookup(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100564{
565 struct perf_pmu *pmu;
566 LIST_HEAD(format);
Zheng Yana6146d52012-06-15 14:31:41 +0800567 LIST_HEAD(aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100568 __u32 type;
569
570 /*
571 * The pmu data we store & need consists of the pmu
572 * type value and format definitions. Load both right
573 * now.
574 */
575 if (pmu_format(name, &format))
576 return NULL;
577
Jiri Olsa3fded962012-10-10 14:53:16 +0200578 if (pmu_aliases(name, &aliases))
579 return NULL;
580
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -0700581 if (!strcmp(name, "cpu"))
582 pmu_add_cpu_aliases(&aliases);
583
Jiri Olsacd82a322012-03-15 20:09:17 +0100584 if (pmu_type(name, &type))
585 return NULL;
586
587 pmu = zalloc(sizeof(*pmu));
588 if (!pmu)
589 return NULL;
590
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800591 pmu->cpus = pmu_cpumask(name);
592
Jiri Olsacd82a322012-03-15 20:09:17 +0100593 INIT_LIST_HEAD(&pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800594 INIT_LIST_HEAD(&pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100595 list_splice(&format, &pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800596 list_splice(&aliases, &pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100597 pmu->name = strdup(name);
598 pmu->type = type;
Robert Richter9bc8f9f2012-06-14 22:38:37 +0200599 list_add_tail(&pmu->list, &pmus);
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300600
601 pmu->default_config = perf_pmu__get_default_config(pmu);
602
Jiri Olsacd82a322012-03-15 20:09:17 +0100603 return pmu;
604}
605
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300606static struct perf_pmu *pmu_find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100607{
608 struct perf_pmu *pmu;
609
610 list_for_each_entry(pmu, &pmus, list)
611 if (!strcmp(pmu->name, name))
612 return pmu;
613
614 return NULL;
615}
616
Robert Richter50a96672012-08-16 21:10:24 +0200617struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
618{
619 /*
620 * pmu iterator: If pmu is NULL, we start at the begin,
621 * otherwise return the next pmu. Returns NULL on end.
622 */
623 if (!pmu) {
624 pmu_read_sysfs();
625 pmu = list_prepare_entry(pmu, &pmus, list);
626 }
627 list_for_each_entry_continue(pmu, &pmus, list)
628 return pmu;
629 return NULL;
630}
631
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300632struct perf_pmu *perf_pmu__find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100633{
634 struct perf_pmu *pmu;
635
636 /*
637 * Once PMU is loaded it stays in the list,
638 * so we keep us from multiple reading/parsing
639 * the pmu format definitions.
640 */
641 pmu = pmu_find(name);
642 if (pmu)
643 return pmu;
644
645 return pmu_lookup(name);
646}
647
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300648static struct perf_pmu_format *
Adrian Hunter09ff6072015-07-17 19:33:49 +0300649pmu_find_format(struct list_head *formats, const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100650{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300651 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100652
653 list_for_each_entry(format, formats, list)
654 if (!strcmp(format->name, name))
655 return format;
656
657 return NULL;
658}
659
Adrian Hunter09ff6072015-07-17 19:33:49 +0300660__u64 perf_pmu__format_bits(struct list_head *formats, const char *name)
661{
662 struct perf_pmu_format *format = pmu_find_format(formats, name);
663 __u64 bits = 0;
664 int fbit;
665
666 if (!format)
667 return 0;
668
669 for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS)
670 bits |= 1ULL << fbit;
671
672 return bits;
673}
674
Jiri Olsacd82a322012-03-15 20:09:17 +0100675/*
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300676 * Sets value based on the format definition (format parameter)
Jiri Olsacd82a322012-03-15 20:09:17 +0100677 * and unformated value (value parameter).
Jiri Olsacd82a322012-03-15 20:09:17 +0100678 */
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300679static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
680 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100681{
682 unsigned long fbit, vbit;
Jiri Olsacd82a322012-03-15 20:09:17 +0100683
684 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
685
686 if (!test_bit(fbit, format))
687 continue;
688
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300689 if (value & (1llu << vbit++))
690 *v |= (1llu << fbit);
691 else if (zero)
692 *v &= ~(1llu << fbit);
Jiri Olsacd82a322012-03-15 20:09:17 +0100693 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100694}
695
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300696static __u64 pmu_format_max_value(const unsigned long *format)
697{
Kan Liangac0e2cd2016-03-30 12:16:15 -0700698 __u64 w = 0;
699 int fbit;
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300700
Kan Liangac0e2cd2016-03-30 12:16:15 -0700701 for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS)
702 w |= (1ULL << fbit);
703
704 return w;
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300705}
706
Jiri Olsacd82a322012-03-15 20:09:17 +0100707/*
Cody P Schafer688d4df2015-01-07 17:13:50 -0800708 * Term is a string term, and might be a param-term. Try to look up it's value
709 * in the remaining terms.
710 * - We have a term like "base-or-format-term=param-term",
711 * - We need to find the value supplied for "param-term" (with param-term named
712 * in a config string) later on in the term list.
713 */
714static int pmu_resolve_param_term(struct parse_events_term *term,
715 struct list_head *head_terms,
716 __u64 *value)
717{
718 struct parse_events_term *t;
719
720 list_for_each_entry(t, head_terms, list) {
721 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
722 if (!strcmp(t->config, term->config)) {
723 t->used = true;
724 *value = t->val.num;
725 return 0;
726 }
727 }
728 }
729
730 if (verbose)
731 printf("Required parameter '%s' not specified\n", term->config);
732
733 return -1;
734}
735
He Kuangffeb8832015-09-28 03:52:14 +0000736static char *pmu_formats_string(struct list_head *formats)
Jiri Olsae64b0202015-04-22 21:10:21 +0200737{
738 struct perf_pmu_format *format;
Masami Hiramatsu11db4e22016-05-10 14:47:44 +0900739 char *str = NULL;
740 struct strbuf buf = STRBUF_INIT;
Jiri Olsae64b0202015-04-22 21:10:21 +0200741 unsigned i = 0;
742
He Kuangffeb8832015-09-28 03:52:14 +0000743 if (!formats)
Jiri Olsae64b0202015-04-22 21:10:21 +0200744 return NULL;
745
746 /* sysfs exported terms */
He Kuangffeb8832015-09-28 03:52:14 +0000747 list_for_each_entry(format, formats, list)
Masami Hiramatsu11db4e22016-05-10 14:47:44 +0900748 if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0)
749 goto error;
Jiri Olsae64b0202015-04-22 21:10:21 +0200750
He Kuangffeb8832015-09-28 03:52:14 +0000751 str = strbuf_detach(&buf, NULL);
Masami Hiramatsu11db4e22016-05-10 14:47:44 +0900752error:
He Kuangffeb8832015-09-28 03:52:14 +0000753 strbuf_release(&buf);
Jiri Olsae64b0202015-04-22 21:10:21 +0200754
Jiri Olsae64b0202015-04-22 21:10:21 +0200755 return str;
Jiri Olsae64b0202015-04-22 21:10:21 +0200756}
757
Cody P Schafer688d4df2015-01-07 17:13:50 -0800758/*
Jiri Olsacd82a322012-03-15 20:09:17 +0100759 * Setup one of config[12] attr members based on the
Cody P Schafer88aca8d2014-01-08 08:43:51 -0800760 * user input data - term parameter.
Jiri Olsacd82a322012-03-15 20:09:17 +0100761 */
762static int pmu_config_term(struct list_head *formats,
763 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300764 struct parse_events_term *term,
Cody P Schafer688d4df2015-01-07 17:13:50 -0800765 struct list_head *head_terms,
Jiri Olsae64b0202015-04-22 21:10:21 +0200766 bool zero, struct parse_events_error *err)
Jiri Olsacd82a322012-03-15 20:09:17 +0100767{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300768 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100769 __u64 *vp;
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300770 __u64 val, max_val;
Jiri Olsacd82a322012-03-15 20:09:17 +0100771
772 /*
Cody P Schafer688d4df2015-01-07 17:13:50 -0800773 * If this is a parameter we've already used for parameterized-eval,
774 * skip it in normal eval.
775 */
776 if (term->used)
777 return 0;
778
779 /*
Jiri Olsacd82a322012-03-15 20:09:17 +0100780 * Hardcoded terms should be already in, so nothing
781 * to be done for them.
782 */
783 if (parse_events__is_hardcoded_term(term))
784 return 0;
785
Jiri Olsacd82a322012-03-15 20:09:17 +0100786 format = pmu_find_format(formats, term->config);
Cody P Schafer688d4df2015-01-07 17:13:50 -0800787 if (!format) {
788 if (verbose)
789 printf("Invalid event/parameter '%s'\n", term->config);
Jiri Olsae64b0202015-04-22 21:10:21 +0200790 if (err) {
He Kuangffeb8832015-09-28 03:52:14 +0000791 char *pmu_term = pmu_formats_string(formats);
792
Jiri Olsae64b0202015-04-22 21:10:21 +0200793 err->idx = term->err_term;
794 err->str = strdup("unknown term");
He Kuangffeb8832015-09-28 03:52:14 +0000795 err->help = parse_events_formats_error_string(pmu_term);
796 free(pmu_term);
Jiri Olsae64b0202015-04-22 21:10:21 +0200797 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100798 return -EINVAL;
Cody P Schafer688d4df2015-01-07 17:13:50 -0800799 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100800
801 switch (format->value) {
802 case PERF_PMU_FORMAT_VALUE_CONFIG:
803 vp = &attr->config;
804 break;
805 case PERF_PMU_FORMAT_VALUE_CONFIG1:
806 vp = &attr->config1;
807 break;
808 case PERF_PMU_FORMAT_VALUE_CONFIG2:
809 vp = &attr->config2;
810 break;
811 default:
812 return -EINVAL;
813 }
814
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200815 /*
Cody P Schafer688d4df2015-01-07 17:13:50 -0800816 * Either directly use a numeric term, or try to translate string terms
817 * using event parameters.
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200818 */
Cody P Schafer688d4df2015-01-07 17:13:50 -0800819 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
820 val = term->val.num;
821 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
822 if (strcmp(term->val.str, "?")) {
Jiri Olsae64b0202015-04-22 21:10:21 +0200823 if (verbose) {
Cody P Schafer688d4df2015-01-07 17:13:50 -0800824 pr_info("Invalid sysfs entry %s=%s\n",
825 term->config, term->val.str);
Jiri Olsae64b0202015-04-22 21:10:21 +0200826 }
827 if (err) {
828 err->idx = term->err_val;
829 err->str = strdup("expected numeric value");
830 }
Cody P Schafer688d4df2015-01-07 17:13:50 -0800831 return -EINVAL;
832 }
833
834 if (pmu_resolve_param_term(term, head_terms, &val))
835 return -EINVAL;
836 } else
837 return -EINVAL;
838
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300839 max_val = pmu_format_max_value(format->bits);
840 if (val > max_val) {
841 if (err) {
842 err->idx = term->err_val;
843 if (asprintf(&err->str,
844 "value too big for format, maximum is %llu",
845 (unsigned long long)max_val) < 0)
846 err->str = strdup("value too big for format");
847 return -EINVAL;
848 }
849 /*
850 * Assume we don't care if !err, in which case the value will be
851 * silently truncated.
852 */
853 }
854
Cody P Schafer688d4df2015-01-07 17:13:50 -0800855 pmu_format_value(format->bits, val, vp, zero);
Jiri Olsacd82a322012-03-15 20:09:17 +0100856 return 0;
857}
858
Jiri Olsacff7f952012-11-10 01:46:50 +0100859int perf_pmu__config_terms(struct list_head *formats,
860 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300861 struct list_head *head_terms,
Jiri Olsae64b0202015-04-22 21:10:21 +0200862 bool zero, struct parse_events_error *err)
Jiri Olsacd82a322012-03-15 20:09:17 +0100863{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300864 struct parse_events_term *term;
Jiri Olsacd82a322012-03-15 20:09:17 +0100865
Cody P Schafer688d4df2015-01-07 17:13:50 -0800866 list_for_each_entry(term, head_terms, list) {
Jiri Olsae64b0202015-04-22 21:10:21 +0200867 if (pmu_config_term(formats, attr, term, head_terms,
868 zero, err))
Jiri Olsacd82a322012-03-15 20:09:17 +0100869 return -EINVAL;
Cody P Schafer688d4df2015-01-07 17:13:50 -0800870 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100871
872 return 0;
873}
874
875/*
876 * Configures event's 'attr' parameter based on the:
877 * 1) users input - specified in terms parameter
878 * 2) pmu format definitions - specified by pmu parameter
879 */
880int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
Jiri Olsae64b0202015-04-22 21:10:21 +0200881 struct list_head *head_terms,
882 struct parse_events_error *err)
Jiri Olsacd82a322012-03-15 20:09:17 +0100883{
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300884 bool zero = !!pmu->default_config;
885
Jiri Olsacd82a322012-03-15 20:09:17 +0100886 attr->type = pmu->type;
Jiri Olsae64b0202015-04-22 21:10:21 +0200887 return perf_pmu__config_terms(&pmu->format, attr, head_terms,
888 zero, err);
Jiri Olsacd82a322012-03-15 20:09:17 +0100889}
890
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300891static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
892 struct parse_events_term *term)
Zheng Yana6146d52012-06-15 14:31:41 +0800893{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300894 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800895 char *name;
896
897 if (parse_events__is_hardcoded_term(term))
898 return NULL;
899
900 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
901 if (term->val.num != 1)
902 return NULL;
903 if (pmu_find_format(&pmu->format, term->config))
904 return NULL;
905 name = term->config;
906 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
907 if (strcasecmp(term->config, "event"))
908 return NULL;
909 name = term->val.str;
910 } else {
911 return NULL;
912 }
913
914 list_for_each_entry(alias, &pmu->aliases, list) {
915 if (!strcasecmp(alias->name, name))
916 return alias;
917 }
918 return NULL;
919}
920
Stephane Eranian410136f2013-11-12 17:58:49 +0100921
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100922static int check_info_data(struct perf_pmu_alias *alias,
923 struct perf_pmu_info *info)
Stephane Eranian410136f2013-11-12 17:58:49 +0100924{
925 /*
926 * Only one term in event definition can
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100927 * define unit, scale and snapshot, fail
928 * if there's more than one.
Stephane Eranian410136f2013-11-12 17:58:49 +0100929 */
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100930 if ((info->unit && alias->unit) ||
931 (info->scale && alias->scale) ||
932 (info->snapshot && alias->snapshot))
Stephane Eranian410136f2013-11-12 17:58:49 +0100933 return -EINVAL;
934
935 if (alias->unit)
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100936 info->unit = alias->unit;
Stephane Eranian410136f2013-11-12 17:58:49 +0100937
938 if (alias->scale)
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100939 info->scale = alias->scale;
940
941 if (alias->snapshot)
942 info->snapshot = alias->snapshot;
Stephane Eranian410136f2013-11-12 17:58:49 +0100943
944 return 0;
945}
946
Zheng Yana6146d52012-06-15 14:31:41 +0800947/*
948 * Find alias in the terms list and replace it with the terms
949 * defined for the alias
950 */
Stephane Eranian410136f2013-11-12 17:58:49 +0100951int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
Matt Fleming46441bd2014-09-24 15:04:06 +0100952 struct perf_pmu_info *info)
Zheng Yana6146d52012-06-15 14:31:41 +0800953{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300954 struct parse_events_term *term, *h;
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300955 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800956 int ret;
957
Matt Fleming044330c2014-11-21 10:31:12 +0100958 info->per_pkg = false;
959
Stephane Eranian8a398892014-01-17 16:34:05 +0100960 /*
961 * Mark unit and scale as not set
962 * (different from default values, see below)
963 */
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100964 info->unit = NULL;
965 info->scale = 0.0;
966 info->snapshot = false;
Stephane Eranian410136f2013-11-12 17:58:49 +0100967
Zheng Yana6146d52012-06-15 14:31:41 +0800968 list_for_each_entry_safe(term, h, head_terms, list) {
969 alias = pmu_find_alias(pmu, term);
970 if (!alias)
971 continue;
972 ret = pmu_alias_terms(alias, &term->list);
973 if (ret)
974 return ret;
Stephane Eranian410136f2013-11-12 17:58:49 +0100975
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100976 ret = check_info_data(alias, info);
Stephane Eranian410136f2013-11-12 17:58:49 +0100977 if (ret)
978 return ret;
979
Matt Fleming044330c2014-11-21 10:31:12 +0100980 if (alias->per_pkg)
981 info->per_pkg = true;
982
Zheng Yana6146d52012-06-15 14:31:41 +0800983 list_del(&term->list);
984 free(term);
985 }
Stephane Eranian8a398892014-01-17 16:34:05 +0100986
987 /*
988 * if no unit or scale foundin aliases, then
989 * set defaults as for evsel
990 * unit cannot left to NULL
991 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100992 if (info->unit == NULL)
993 info->unit = "";
Stephane Eranian8a398892014-01-17 16:34:05 +0100994
Matt Fleming46441bd2014-09-24 15:04:06 +0100995 if (info->scale == 0.0)
996 info->scale = 1.0;
Stephane Eranian8a398892014-01-17 16:34:05 +0100997
Zheng Yana6146d52012-06-15 14:31:41 +0800998 return 0;
999}
1000
Jiri Olsacd82a322012-03-15 20:09:17 +01001001int perf_pmu__new_format(struct list_head *list, char *name,
1002 int config, unsigned long *bits)
1003{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -03001004 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +01001005
1006 format = zalloc(sizeof(*format));
1007 if (!format)
1008 return -ENOMEM;
1009
1010 format->name = strdup(name);
1011 format->value = config;
1012 memcpy(format->bits, bits, sizeof(format->bits));
1013
1014 list_add_tail(&format->list, list);
1015 return 0;
1016}
1017
1018void perf_pmu__set_format(unsigned long *bits, long from, long to)
1019{
1020 long b;
1021
1022 if (!to)
1023 to = from;
1024
Sukadev Bhattiprolu15268132013-01-17 09:11:30 -08001025 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
Jiri Olsacd82a322012-03-15 20:09:17 +01001026 for (b = from; b <= to; b++)
1027 set_bit(b, bits);
1028}
Andi Kleendc098b32013-04-20 11:02:29 -07001029
Cody P Schaferaaea3612015-01-07 17:13:51 -08001030static int sub_non_neg(int a, int b)
1031{
1032 if (b > a)
1033 return 0;
1034 return a - b;
1035}
1036
Andi Kleendc098b32013-04-20 11:02:29 -07001037static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
1038 struct perf_pmu_alias *alias)
1039{
Cody P Schaferaaea3612015-01-07 17:13:51 -08001040 struct parse_events_term *term;
1041 int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
1042
1043 list_for_each_entry(term, &alias->terms, list) {
1044 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
1045 used += snprintf(buf + used, sub_non_neg(len, used),
1046 ",%s=%s", term->config,
1047 term->val.str);
1048 }
1049
1050 if (sub_non_neg(len, used) > 0) {
1051 buf[used] = '/';
1052 used++;
1053 }
1054 if (sub_non_neg(len, used) > 0) {
1055 buf[used] = '\0';
1056 used++;
1057 } else
1058 buf[len - 1] = '\0';
1059
Andi Kleendc098b32013-04-20 11:02:29 -07001060 return buf;
1061}
1062
1063static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
1064 struct perf_pmu_alias *alias)
1065{
1066 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
1067 return buf;
1068}
1069
Andi Kleendd5f1032016-09-15 15:24:50 -07001070struct sevent {
Andi Kleen08e60ed2016-09-15 15:24:43 -07001071 char *name;
1072 char *desc;
Andi Kleendd5f1032016-09-15 15:24:50 -07001073 char *topic;
Andi Kleen08e60ed2016-09-15 15:24:43 -07001074};
1075
Andi Kleendd5f1032016-09-15 15:24:50 -07001076static int cmp_sevent(const void *a, const void *b)
Andi Kleendc098b32013-04-20 11:02:29 -07001077{
Andi Kleendd5f1032016-09-15 15:24:50 -07001078 const struct sevent *as = a;
1079 const struct sevent *bs = b;
Andi Kleen08e60ed2016-09-15 15:24:43 -07001080
1081 /* Put extra events last */
1082 if (!!as->desc != !!bs->desc)
1083 return !!as->desc - !!bs->desc;
Andi Kleendd5f1032016-09-15 15:24:50 -07001084 if (as->topic && bs->topic) {
1085 int n = strcmp(as->topic, bs->topic);
1086
1087 if (n)
1088 return n;
1089 }
Andi Kleen08e60ed2016-09-15 15:24:43 -07001090 return strcmp(as->name, bs->name);
1091}
1092
1093static void wordwrap(char *s, int start, int max, int corr)
1094{
1095 int column = start;
1096 int n;
1097
1098 while (*s) {
1099 int wlen = strcspn(s, " \t");
1100
1101 if (column + wlen >= max && column > start) {
1102 printf("\n%*s", start, "");
1103 column = start + corr;
1104 }
1105 n = printf("%s%.*s", column > start ? " " : "", wlen, s);
1106 if (n <= 0)
1107 break;
1108 s += wlen;
1109 column += n;
1110 while (isspace(*s))
1111 s++;
1112 }
Andi Kleendc098b32013-04-20 11:02:29 -07001113}
1114
Sukadev Bhattiproluc8d68282016-09-15 15:24:48 -07001115void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1116 bool long_desc)
Andi Kleendc098b32013-04-20 11:02:29 -07001117{
1118 struct perf_pmu *pmu;
1119 struct perf_pmu_alias *alias;
1120 char buf[1024];
1121 int printed = 0;
1122 int len, j;
Andi Kleendd5f1032016-09-15 15:24:50 -07001123 struct sevent *aliases;
Andi Kleen08e60ed2016-09-15 15:24:43 -07001124 int numdesc = 0;
Andi Kleen61eb2eb2016-09-15 15:24:44 -07001125 int columns = pager_get_columns();
Andi Kleendd5f1032016-09-15 15:24:50 -07001126 char *topic = NULL;
Andi Kleendc098b32013-04-20 11:02:29 -07001127
1128 pmu = NULL;
1129 len = 0;
Adrian Hunter42634bc2014-10-23 13:45:10 +03001130 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
Andi Kleendc098b32013-04-20 11:02:29 -07001131 list_for_each_entry(alias, &pmu->aliases, list)
1132 len++;
Adrian Hunter42634bc2014-10-23 13:45:10 +03001133 if (pmu->selectable)
1134 len++;
1135 }
Andi Kleendd5f1032016-09-15 15:24:50 -07001136 aliases = zalloc(sizeof(struct sevent) * len);
Andi Kleendc098b32013-04-20 11:02:29 -07001137 if (!aliases)
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001138 goto out_enomem;
Andi Kleendc098b32013-04-20 11:02:29 -07001139 pmu = NULL;
1140 j = 0;
Adrian Hunter42634bc2014-10-23 13:45:10 +03001141 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
Andi Kleendc098b32013-04-20 11:02:29 -07001142 list_for_each_entry(alias, &pmu->aliases, list) {
Andi Kleen08e60ed2016-09-15 15:24:43 -07001143 char *name = alias->desc ? alias->name :
1144 format_alias(buf, sizeof(buf), pmu, alias);
Andi Kleendc098b32013-04-20 11:02:29 -07001145 bool is_cpu = !strcmp(pmu->name, "cpu");
1146
1147 if (event_glob != NULL &&
Andi Kleen38d14f02016-10-19 10:50:01 -07001148 !(strglobmatch_nocase(name, event_glob) ||
1149 (!is_cpu && strglobmatch_nocase(alias->name,
Andi Kleen67bdc352016-10-19 11:45:23 -07001150 event_glob)) ||
1151 (alias->topic &&
1152 strglobmatch_nocase(alias->topic, event_glob))))
Andi Kleendc098b32013-04-20 11:02:29 -07001153 continue;
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001154
Andi Kleen08e60ed2016-09-15 15:24:43 -07001155 if (is_cpu && !name_only && !alias->desc)
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001156 name = format_alias_or(buf, sizeof(buf), pmu, alias);
1157
Andi Kleen08e60ed2016-09-15 15:24:43 -07001158 aliases[j].name = name;
1159 if (is_cpu && !name_only && !alias->desc)
1160 aliases[j].name = format_alias_or(buf,
1161 sizeof(buf),
1162 pmu, alias);
1163 aliases[j].name = strdup(aliases[j].name);
1164 if (!aliases[j].name)
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001165 goto out_enomem;
Andi Kleen08e60ed2016-09-15 15:24:43 -07001166
Sukadev Bhattiproluc8d68282016-09-15 15:24:48 -07001167 aliases[j].desc = long_desc ? alias->long_desc :
1168 alias->desc;
Andi Kleendd5f1032016-09-15 15:24:50 -07001169 aliases[j].topic = alias->topic;
Andi Kleendc098b32013-04-20 11:02:29 -07001170 j++;
1171 }
Arnaldo Carvalho de Melofa52cea2015-10-02 15:28:16 -03001172 if (pmu->selectable &&
1173 (event_glob == NULL || strglobmatch(pmu->name, event_glob))) {
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001174 char *s;
1175 if (asprintf(&s, "%s//", pmu->name) < 0)
1176 goto out_enomem;
Andi Kleen08e60ed2016-09-15 15:24:43 -07001177 aliases[j].name = s;
Adrian Hunter42634bc2014-10-23 13:45:10 +03001178 j++;
1179 }
1180 }
Andi Kleendc098b32013-04-20 11:02:29 -07001181 len = j;
Andi Kleendd5f1032016-09-15 15:24:50 -07001182 qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
Andi Kleendc098b32013-04-20 11:02:29 -07001183 for (j = 0; j < len; j++) {
1184 if (name_only) {
Andi Kleen08e60ed2016-09-15 15:24:43 -07001185 printf("%s ", aliases[j].name);
Andi Kleendc098b32013-04-20 11:02:29 -07001186 continue;
1187 }
Andi Kleen1c5f01f2016-09-15 15:24:45 -07001188 if (aliases[j].desc && !quiet_flag) {
Andi Kleen08e60ed2016-09-15 15:24:43 -07001189 if (numdesc++ == 0)
1190 printf("\n");
Andi Kleendd5f1032016-09-15 15:24:50 -07001191 if (aliases[j].topic && (!topic ||
1192 strcmp(topic, aliases[j].topic))) {
1193 printf("%s%s:\n", topic ? "\n" : "",
1194 aliases[j].topic);
1195 topic = aliases[j].topic;
1196 }
Andi Kleen08e60ed2016-09-15 15:24:43 -07001197 printf(" %-50s\n", aliases[j].name);
1198 printf("%*s", 8, "[");
1199 wordwrap(aliases[j].desc, 8, columns, 0);
1200 printf("]\n");
1201 } else
1202 printf(" %-50s [Kernel PMU event]\n", aliases[j].name);
Andi Kleendc098b32013-04-20 11:02:29 -07001203 printed++;
1204 }
Arnaldo Carvalho de Melodfc431c2015-09-30 17:13:26 -03001205 if (printed && pager_in_use())
Andi Kleendc098b32013-04-20 11:02:29 -07001206 printf("\n");
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001207out_free:
1208 for (j = 0; j < len; j++)
Andi Kleen08e60ed2016-09-15 15:24:43 -07001209 zfree(&aliases[j].name);
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001210 zfree(&aliases);
1211 return;
1212
1213out_enomem:
1214 printf("FATAL: not enough memory to print PMU events\n");
1215 if (aliases)
1216 goto out_free;
Andi Kleendc098b32013-04-20 11:02:29 -07001217}
Andi Kleen4cabc3d2013-08-21 16:47:26 -07001218
1219bool pmu_have_event(const char *pname, const char *name)
1220{
1221 struct perf_pmu *pmu;
1222 struct perf_pmu_alias *alias;
1223
1224 pmu = NULL;
1225 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1226 if (strcmp(pname, pmu->name))
1227 continue;
1228 list_for_each_entry(alias, &pmu->aliases, list)
1229 if (!strcmp(alias->name, name))
1230 return true;
1231 }
1232 return false;
1233}
Adrian Hunter7d4bdab2014-07-31 09:00:50 +03001234
1235static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
1236{
1237 struct stat st;
1238 char path[PATH_MAX];
1239 const char *sysfs;
1240
1241 sysfs = sysfs__mountpoint();
1242 if (!sysfs)
1243 return NULL;
1244
1245 snprintf(path, PATH_MAX,
1246 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
1247
1248 if (stat(path, &st) < 0)
1249 return NULL;
1250
1251 return fopen(path, "r");
1252}
1253
1254int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
1255 ...)
1256{
1257 va_list args;
1258 FILE *file;
1259 int ret = EOF;
1260
1261 va_start(args, fmt);
1262 file = perf_pmu__open_file(pmu, name);
1263 if (file) {
1264 ret = vfscanf(file, fmt, args);
1265 fclose(file);
1266 }
1267 va_end(args);
1268 return ret;
1269}