c58ba9fb6a3697da4f4838ee5ad154930004064e
[platform/kernel/linux-starfive.git] / tools / perf / util / pmus.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/list.h>
3 #include <linux/zalloc.h>
4 #include <subcmd/pager.h>
5 #include <sys/types.h>
6 #include <dirent.h>
7 #include <pthread.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include "debug.h"
11 #include "evsel.h"
12 #include "pmus.h"
13 #include "pmu.h"
14 #include "print-events.h"
15
16 /*
17  * core_pmus:  A PMU belongs to core_pmus if it's name is "cpu" or it's sysfs
18  *             directory contains "cpus" file. All PMUs belonging to core_pmus
19  *             must have pmu->is_core=1. If there are more than one PMU in
20  *             this list, perf interprets it as a heterogeneous platform.
21  *             (FWIW, certain ARM platforms having heterogeneous cores uses
22  *             homogeneous PMU, and thus they are treated as homogeneous
23  *             platform by perf because core_pmus will have only one entry)
24  * other_pmus: All other PMUs which are not part of core_pmus list. It doesn't
25  *             matter whether PMU is present per SMT-thread or outside of the
26  *             core in the hw. For e.g., an instance of AMD ibs_fetch// and
27  *             ibs_op// PMUs is present in each hw SMT thread, however they
28  *             are captured under other_pmus. PMUs belonging to other_pmus
29  *             must have pmu->is_core=0 but pmu->is_uncore could be 0 or 1.
30  */
31 static LIST_HEAD(core_pmus);
32 static LIST_HEAD(other_pmus);
33 static bool read_sysfs_core_pmus;
34 static bool read_sysfs_all_pmus;
35
36 void perf_pmus__destroy(void)
37 {
38         struct perf_pmu *pmu, *tmp;
39
40         list_for_each_entry_safe(pmu, tmp, &core_pmus, list) {
41                 list_del(&pmu->list);
42
43                 perf_pmu__delete(pmu);
44         }
45         list_for_each_entry_safe(pmu, tmp, &other_pmus, list) {
46                 list_del(&pmu->list);
47
48                 perf_pmu__delete(pmu);
49         }
50         read_sysfs_core_pmus = false;
51         read_sysfs_all_pmus = false;
52 }
53
54 static struct perf_pmu *pmu_find(const char *name)
55 {
56         struct perf_pmu *pmu;
57
58         list_for_each_entry(pmu, &core_pmus, list) {
59                 if (!strcmp(pmu->name, name) ||
60                     (pmu->alias_name && !strcmp(pmu->alias_name, name)))
61                         return pmu;
62         }
63         list_for_each_entry(pmu, &other_pmus, list) {
64                 if (!strcmp(pmu->name, name) ||
65                     (pmu->alias_name && !strcmp(pmu->alias_name, name)))
66                         return pmu;
67         }
68
69         return NULL;
70 }
71
72 struct perf_pmu *perf_pmus__find(const char *name)
73 {
74         struct perf_pmu *pmu;
75         int dirfd;
76         bool core_pmu;
77
78         /*
79          * Once PMU is loaded it stays in the list,
80          * so we keep us from multiple reading/parsing
81          * the pmu format definitions.
82          */
83         pmu = pmu_find(name);
84         if (pmu)
85                 return pmu;
86
87         if (read_sysfs_all_pmus)
88                 return NULL;
89
90         core_pmu = is_pmu_core(name);
91         if (core_pmu && read_sysfs_core_pmus)
92                 return NULL;
93
94         dirfd = perf_pmu__event_source_devices_fd();
95         pmu = perf_pmu__lookup(core_pmu ? &core_pmus : &other_pmus, dirfd, name);
96         close(dirfd);
97
98         return pmu;
99 }
100
101 static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name)
102 {
103         struct perf_pmu *pmu;
104         bool core_pmu;
105
106         /*
107          * Once PMU is loaded it stays in the list,
108          * so we keep us from multiple reading/parsing
109          * the pmu format definitions.
110          */
111         pmu = pmu_find(name);
112         if (pmu)
113                 return pmu;
114
115         if (read_sysfs_all_pmus)
116                 return NULL;
117
118         core_pmu = is_pmu_core(name);
119         if (core_pmu && read_sysfs_core_pmus)
120                 return NULL;
121
122         return perf_pmu__lookup(core_pmu ? &core_pmus : &other_pmus, dirfd, name);
123 }
124
125 /* Add all pmus in sysfs to pmu list: */
126 static void pmu_read_sysfs(bool core_only)
127 {
128         int fd;
129         DIR *dir;
130         struct dirent *dent;
131
132         if (read_sysfs_all_pmus || (core_only && read_sysfs_core_pmus))
133                 return;
134
135         fd = perf_pmu__event_source_devices_fd();
136         if (fd < 0)
137                 return;
138
139         dir = fdopendir(fd);
140         if (!dir) {
141                 close(fd);
142                 return;
143         }
144
145         while ((dent = readdir(dir))) {
146                 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
147                         continue;
148                 if (core_only && !is_pmu_core(dent->d_name))
149                         continue;
150                 /* add to static LIST_HEAD(core_pmus) or LIST_HEAD(other_pmus): */
151                 perf_pmu__find2(fd, dent->d_name);
152         }
153
154         closedir(dir);
155         if (list_empty(&core_pmus)) {
156                 if (!perf_pmu__create_placeholder_core_pmu(&core_pmus))
157                         pr_err("Failure to set up any core PMUs\n");
158         }
159         if (!list_empty(&core_pmus)) {
160                 read_sysfs_core_pmus = true;
161                 if (!core_only)
162                         read_sysfs_all_pmus = true;
163         }
164 }
165
166 static struct perf_pmu *__perf_pmus__find_by_type(unsigned int type)
167 {
168         struct perf_pmu *pmu;
169
170         list_for_each_entry(pmu, &core_pmus, list) {
171                 if (pmu->type == type)
172                         return pmu;
173         }
174
175         list_for_each_entry(pmu, &other_pmus, list) {
176                 if (pmu->type == type)
177                         return pmu;
178         }
179         return NULL;
180 }
181
182 struct perf_pmu *perf_pmus__find_by_type(unsigned int type)
183 {
184         struct perf_pmu *pmu = __perf_pmus__find_by_type(type);
185
186         if (pmu || read_sysfs_all_pmus)
187                 return pmu;
188
189         pmu_read_sysfs(/*core_only=*/false);
190         pmu = __perf_pmus__find_by_type(type);
191         return pmu;
192 }
193
194 /*
195  * pmu iterator: If pmu is NULL, we start at the begin, otherwise return the
196  * next pmu. Returns NULL on end.
197  */
198 struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu)
199 {
200         bool use_core_pmus = !pmu || pmu->is_core;
201
202         if (!pmu) {
203                 pmu_read_sysfs(/*core_only=*/false);
204                 pmu = list_prepare_entry(pmu, &core_pmus, list);
205         }
206         if (use_core_pmus) {
207                 list_for_each_entry_continue(pmu, &core_pmus, list)
208                         return pmu;
209
210                 pmu = NULL;
211                 pmu = list_prepare_entry(pmu, &other_pmus, list);
212         }
213         list_for_each_entry_continue(pmu, &other_pmus, list)
214                 return pmu;
215         return NULL;
216 }
217
218 struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu)
219 {
220         if (!pmu) {
221                 pmu_read_sysfs(/*core_only=*/true);
222                 pmu = list_prepare_entry(pmu, &core_pmus, list);
223         }
224         list_for_each_entry_continue(pmu, &core_pmus, list)
225                 return pmu;
226
227         return NULL;
228 }
229
230 const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str)
231 {
232         struct perf_pmu *pmu = NULL;
233
234         while ((pmu = perf_pmus__scan(pmu)) != NULL) {
235                 if (!strcmp(pmu->name, str))
236                         return pmu;
237                 /* Ignore "uncore_" prefix. */
238                 if (!strncmp(pmu->name, "uncore_", 7)) {
239                         if (!strcmp(pmu->name + 7, str))
240                                 return pmu;
241                 }
242                 /* Ignore "cpu_" prefix on Intel hybrid PMUs. */
243                 if (!strncmp(pmu->name, "cpu_", 4)) {
244                         if (!strcmp(pmu->name + 4, str))
245                                 return pmu;
246                 }
247         }
248         return NULL;
249 }
250
251 int __weak perf_pmus__num_mem_pmus(void)
252 {
253         /* All core PMUs are for mem events. */
254         return perf_pmus__num_core_pmus();
255 }
256
257 /** Struct for ordering events as output in perf list. */
258 struct sevent {
259         /** PMU for event. */
260         const struct perf_pmu *pmu;
261         /**
262          * Optional event for name, desc, etc. If not present then this is a
263          * selectable PMU and the event name is shown as "//".
264          */
265         const struct perf_pmu_alias *event;
266         /** Is the PMU for the CPU? */
267         bool is_cpu;
268 };
269
270 static int cmp_sevent(const void *a, const void *b)
271 {
272         const struct sevent *as = a;
273         const struct sevent *bs = b;
274         const char *a_pmu_name = NULL, *b_pmu_name = NULL;
275         const char *a_name = "//", *a_desc = NULL, *a_topic = "";
276         const char *b_name = "//", *b_desc = NULL, *b_topic = "";
277         int ret;
278
279         if (as->event) {
280                 a_name = as->event->name;
281                 a_desc = as->event->desc;
282                 a_topic = as->event->topic ?: "";
283                 a_pmu_name = as->event->pmu_name;
284         }
285         if (bs->event) {
286                 b_name = bs->event->name;
287                 b_desc = bs->event->desc;
288                 b_topic = bs->event->topic ?: "";
289                 b_pmu_name = bs->event->pmu_name;
290         }
291         /* Put extra events last. */
292         if (!!a_desc != !!b_desc)
293                 return !!a_desc - !!b_desc;
294
295         /* Order by topics. */
296         ret = strcmp(a_topic, b_topic);
297         if (ret)
298                 return ret;
299
300         /* Order CPU core events to be first */
301         if (as->is_cpu != bs->is_cpu)
302                 return as->is_cpu ? -1 : 1;
303
304         /* Order by PMU name. */
305         if (as->pmu != bs->pmu) {
306                 a_pmu_name = a_pmu_name ?: (as->pmu->name ?: "");
307                 b_pmu_name = b_pmu_name ?: (bs->pmu->name ?: "");
308                 ret = strcmp(a_pmu_name, b_pmu_name);
309                 if (ret)
310                         return ret;
311         }
312
313         /* Order by event name. */
314         return strcmp(a_name, b_name);
315 }
316
317 static bool pmu_alias_is_duplicate(struct sevent *alias_a,
318                                    struct sevent *alias_b)
319 {
320         const char *a_pmu_name = NULL, *b_pmu_name = NULL;
321         const char *a_name = "//", *b_name = "//";
322
323
324         if (alias_a->event) {
325                 a_name = alias_a->event->name;
326                 a_pmu_name = alias_a->event->pmu_name;
327         }
328         if (alias_b->event) {
329                 b_name = alias_b->event->name;
330                 b_pmu_name = alias_b->event->pmu_name;
331         }
332
333         /* Different names -> never duplicates */
334         if (strcmp(a_name, b_name))
335                 return false;
336
337         /* Don't remove duplicates for different PMUs */
338         a_pmu_name = a_pmu_name ?: (alias_a->pmu->name ?: "");
339         b_pmu_name = b_pmu_name ?: (alias_b->pmu->name ?: "");
340         return strcmp(a_pmu_name, b_pmu_name) == 0;
341 }
342
343 static int sub_non_neg(int a, int b)
344 {
345         if (b > a)
346                 return 0;
347         return a - b;
348 }
349
350 static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,
351                           const struct perf_pmu_alias *alias)
352 {
353         struct parse_events_term *term;
354         int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
355
356         list_for_each_entry(term, &alias->terms, list) {
357                 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
358                         used += snprintf(buf + used, sub_non_neg(len, used),
359                                         ",%s=%s", term->config,
360                                         term->val.str);
361         }
362
363         if (sub_non_neg(len, used) > 0) {
364                 buf[used] = '/';
365                 used++;
366         }
367         if (sub_non_neg(len, used) > 0) {
368                 buf[used] = '\0';
369                 used++;
370         } else
371                 buf[len - 1] = '\0';
372
373         return buf;
374 }
375
376 void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state)
377 {
378         struct perf_pmu *pmu;
379         struct perf_pmu_alias *event;
380         char buf[1024];
381         int printed = 0;
382         int len, j;
383         struct sevent *aliases;
384
385         pmu = NULL;
386         len = 0;
387         while ((pmu = perf_pmus__scan(pmu)) != NULL) {
388                 list_for_each_entry(event, &pmu->aliases, list)
389                         len++;
390                 if (pmu->selectable)
391                         len++;
392         }
393         aliases = zalloc(sizeof(struct sevent) * len);
394         if (!aliases) {
395                 pr_err("FATAL: not enough memory to print PMU events\n");
396                 return;
397         }
398         pmu = NULL;
399         j = 0;
400         while ((pmu = perf_pmus__scan(pmu)) != NULL) {
401                 bool is_cpu = pmu->is_core;
402
403                 list_for_each_entry(event, &pmu->aliases, list) {
404                         aliases[j].event = event;
405                         aliases[j].pmu = pmu;
406                         aliases[j].is_cpu = is_cpu;
407                         j++;
408                 }
409                 if (pmu->selectable) {
410                         aliases[j].event = NULL;
411                         aliases[j].pmu = pmu;
412                         aliases[j].is_cpu = is_cpu;
413                         j++;
414                 }
415         }
416         len = j;
417         qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
418         for (j = 0; j < len; j++) {
419                 const char *name, *alias = NULL, *scale_unit = NULL,
420                         *desc = NULL, *long_desc = NULL,
421                         *encoding_desc = NULL, *topic = NULL,
422                         *pmu_name = NULL;
423                 bool deprecated = false;
424                 size_t buf_used;
425
426                 /* Skip duplicates */
427                 if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1]))
428                         continue;
429
430                 if (!aliases[j].event) {
431                         /* A selectable event. */
432                         pmu_name = aliases[j].pmu->name;
433                         buf_used = snprintf(buf, sizeof(buf), "%s//", pmu_name) + 1;
434                         name = buf;
435                 } else {
436                         if (aliases[j].event->desc) {
437                                 name = aliases[j].event->name;
438                                 buf_used = 0;
439                         } else {
440                                 name = format_alias(buf, sizeof(buf), aliases[j].pmu,
441                                                     aliases[j].event);
442                                 if (aliases[j].is_cpu) {
443                                         alias = name;
444                                         name = aliases[j].event->name;
445                                 }
446                                 buf_used = strlen(buf) + 1;
447                         }
448                         pmu_name = aliases[j].event->pmu_name ?: (aliases[j].pmu->name ?: "");
449                         if (strlen(aliases[j].event->unit) || aliases[j].event->scale != 1.0) {
450                                 scale_unit = buf + buf_used;
451                                 buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
452                                                 "%G%s", aliases[j].event->scale,
453                                                 aliases[j].event->unit) + 1;
454                         }
455                         desc = aliases[j].event->desc;
456                         long_desc = aliases[j].event->long_desc;
457                         topic = aliases[j].event->topic;
458                         encoding_desc = buf + buf_used;
459                         buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,
460                                         "%s/%s/", pmu_name, aliases[j].event->str) + 1;
461                         deprecated = aliases[j].event->deprecated;
462                 }
463                 print_cb->print_event(print_state,
464                                 pmu_name,
465                                 topic,
466                                 name,
467                                 alias,
468                                 scale_unit,
469                                 deprecated,
470                                 "Kernel PMU event",
471                                 desc,
472                                 long_desc,
473                                 encoding_desc);
474         }
475         if (printed && pager_in_use())
476                 printf("\n");
477
478         zfree(&aliases);
479 }
480
481 bool perf_pmus__have_event(const char *pname, const char *name)
482 {
483         struct perf_pmu *pmu = perf_pmus__find(pname);
484
485         return pmu && perf_pmu__have_event(pmu, name);
486 }
487
488 int perf_pmus__num_core_pmus(void)
489 {
490         static int count;
491
492         if (!count) {
493                 struct perf_pmu *pmu = NULL;
494
495                 while ((pmu = perf_pmus__scan_core(pmu)) != NULL)
496                         count++;
497         }
498         return count;
499 }
500
501 static bool __perf_pmus__supports_extended_type(void)
502 {
503         struct perf_pmu *pmu = NULL;
504
505         if (perf_pmus__num_core_pmus() <= 1)
506                 return false;
507
508         while ((pmu = perf_pmus__scan_core(pmu)) != NULL) {
509                 if (!is_event_supported(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES | ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT)))
510                         return false;
511         }
512
513         return true;
514 }
515
516 static bool perf_pmus__do_support_extended_type;
517
518 static void perf_pmus__init_supports_extended_type(void)
519 {
520         perf_pmus__do_support_extended_type = __perf_pmus__supports_extended_type();
521 }
522
523 bool perf_pmus__supports_extended_type(void)
524 {
525         static pthread_once_t extended_type_once = PTHREAD_ONCE_INIT;
526
527         pthread_once(&extended_type_once, perf_pmus__init_supports_extended_type);
528
529         return perf_pmus__do_support_extended_type;
530 }
531
532 char *perf_pmus__default_pmu_name(void)
533 {
534         int fd;
535         DIR *dir;
536         struct dirent *dent;
537         char *result = NULL;
538
539         if (!list_empty(&core_pmus))
540                 return strdup(list_first_entry(&core_pmus, struct perf_pmu, list)->name);
541
542         fd = perf_pmu__event_source_devices_fd();
543         if (fd < 0)
544                 return strdup("cpu");
545
546         dir = fdopendir(fd);
547         if (!dir) {
548                 close(fd);
549                 return strdup("cpu");
550         }
551
552         while ((dent = readdir(dir))) {
553                 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
554                         continue;
555                 if (is_pmu_core(dent->d_name)) {
556                         result = strdup(dent->d_name);
557                         break;
558                 }
559         }
560
561         closedir(dir);
562         return result ?: strdup("cpu");
563 }
564
565 struct perf_pmu *evsel__find_pmu(const struct evsel *evsel)
566 {
567         struct perf_pmu *pmu = evsel->pmu;
568
569         if (!pmu) {
570                 pmu = perf_pmus__find_by_type(evsel->core.attr.type);
571                 ((struct evsel *)evsel)->pmu = pmu;
572         }
573         return pmu;
574 }