hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/tools/perf/util/pmu.c
....@@ -1,6 +1,9 @@
11 // SPDX-License-Identifier: GPL-2.0
22 #include <linux/list.h>
33 #include <linux/compiler.h>
4
+#include <linux/string.h>
5
+#include <linux/zalloc.h>
6
+#include <subcmd/pager.h>
47 #include <sys/types.h>
58 #include <errno.h>
69 #include <fcntl.h>
....@@ -13,14 +16,17 @@
1316 #include <api/fs/fs.h>
1417 #include <locale.h>
1518 #include <regex.h>
16
-#include "util.h"
19
+#include <perf/cpumap.h>
20
+#include "debug.h"
21
+#include "evsel.h"
1722 #include "pmu.h"
1823 #include "parse-events.h"
19
-#include "cpumap.h"
2024 #include "header.h"
21
-#include "pmu-events/pmu-events.h"
22
-#include "cache.h"
2325 #include "string2.h"
26
+#include "strbuf.h"
27
+#include "fncache.h"
28
+
29
+struct perf_pmu perf_pmu__fake;
2430
2531 struct perf_pmu_format {
2632 char *name;
....@@ -28,8 +34,6 @@
2834 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
2935 struct list_head list;
3036 };
31
-
32
-#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
3337
3438 int perf_pmu_parse(struct list_head *list, char *name);
3539 extern FILE *perf_pmu_in;
....@@ -81,7 +85,6 @@
8185 */
8286 static int pmu_format(const char *name, struct list_head *format)
8387 {
84
- struct stat st;
8588 char path[PATH_MAX];
8689 const char *sysfs = sysfs__mountpoint();
8790
....@@ -91,8 +94,8 @@
9194 snprintf(path, PATH_MAX,
9295 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
9396
94
- if (stat(path, &st) < 0)
95
- return 0; /* no error if format does not exist */
97
+ if (!file_available(path))
98
+ return 0;
9699
97100 if (perf_pmu__format_parse(path, format))
98101 return -1;
....@@ -100,7 +103,7 @@
100103 return 0;
101104 }
102105
103
-static int convert_scale(const char *scale, char **end, double *sval)
106
+int perf_pmu__convert_scale(const char *scale, char **end, double *sval)
104107 {
105108 char *lc;
106109 int ret = 0;
....@@ -163,7 +166,7 @@
163166 else
164167 scale[sret] = '\0';
165168
166
- ret = convert_scale(scale, NULL, &alias->scale);
169
+ ret = perf_pmu__convert_scale(scale, NULL, &alias->scale);
167170 error:
168171 close(fd);
169172 return ret;
....@@ -271,7 +274,7 @@
271274 }
272275
273276 /* Delete an alias entry. */
274
-static void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
277
+void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
275278 {
276279 zfree(&newalias->name);
277280 zfree(&newalias->desc);
....@@ -307,7 +310,8 @@
307310 char *long_desc, char *topic,
308311 char *unit, char *perpkg,
309312 char *metric_expr,
310
- char *metric_name)
313
+ char *metric_name,
314
+ char *deprecated)
311315 {
312316 struct parse_events_term *term;
313317 struct perf_pmu_alias *alias;
....@@ -324,6 +328,7 @@
324328 alias->unit[0] = '\0';
325329 alias->per_pkg = false;
326330 alias->snapshot = false;
331
+ alias->deprecated = false;
327332
328333 ret = parse_events_terms(&alias->terms, val);
329334 if (ret) {
....@@ -371,12 +376,15 @@
371376 desc ? strdup(desc) : NULL;
372377 alias->topic = topic ? strdup(topic) : NULL;
373378 if (unit) {
374
- if (convert_scale(unit, &unit, &alias->scale) < 0)
379
+ if (perf_pmu__convert_scale(unit, &unit, &alias->scale) < 0)
375380 return -1;
376381 snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
377382 }
378383 alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1;
379384 alias->str = strdup(newval);
385
+
386
+ if (deprecated)
387
+ alias->deprecated = true;
380388
381389 if (!perf_pmu_merge_alias(alias, list))
382390 list_add_tail(&alias->list, list);
....@@ -396,10 +404,10 @@
396404 buf[ret] = 0;
397405
398406 /* Remove trailing newline from sysfs file */
399
- rtrim(buf);
407
+ strim(buf);
400408
401409 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
402
- NULL, NULL, NULL);
410
+ NULL, NULL, NULL, NULL);
403411 }
404412
405413 static inline bool pmu_alias_info_file(char *name)
....@@ -469,7 +477,6 @@
469477 */
470478 static int pmu_aliases(const char *name, struct list_head *head)
471479 {
472
- struct stat st;
473480 char path[PATH_MAX];
474481 const char *sysfs = sysfs__mountpoint();
475482
....@@ -479,8 +486,8 @@
479486 snprintf(path, PATH_MAX,
480487 "%s/bus/event_source/devices/%s/events", sysfs, name);
481488
482
- if (stat(path, &st) < 0)
483
- return 0; /* no error if 'events' does not exist */
489
+ if (!file_available(path))
490
+ return 0;
484491
485492 if (pmu_aliases_parse(path, head))
486493 return -1;
....@@ -519,7 +526,6 @@
519526 */
520527 static int pmu_type(const char *name, __u32 *type)
521528 {
522
- struct stat st;
523529 char path[PATH_MAX];
524530 FILE *file;
525531 int ret = 0;
....@@ -531,7 +537,7 @@
531537 snprintf(path, PATH_MAX,
532538 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
533539
534
- if (stat(path, &st) < 0)
540
+ if (access(path, R_OK) < 0)
535541 return -1;
536542
537543 file = fopen(path, "r");
....@@ -573,16 +579,16 @@
573579 closedir(dir);
574580 }
575581
576
-static struct cpu_map *__pmu_cpumask(const char *path)
582
+static struct perf_cpu_map *__pmu_cpumask(const char *path)
577583 {
578584 FILE *file;
579
- struct cpu_map *cpus;
585
+ struct perf_cpu_map *cpus;
580586
581587 file = fopen(path, "r");
582588 if (!file)
583589 return NULL;
584590
585
- cpus = cpu_map__read(file);
591
+ cpus = perf_cpu_map__read(file);
586592 fclose(file);
587593 return cpus;
588594 }
....@@ -594,10 +600,10 @@
594600 #define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask"
595601 #define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus"
596602
597
-static struct cpu_map *pmu_cpumask(const char *name)
603
+static struct perf_cpu_map *pmu_cpumask(const char *name)
598604 {
599605 char path[PATH_MAX];
600
- struct cpu_map *cpus;
606
+ struct perf_cpu_map *cpus;
601607 const char *sysfs = sysfs__mountpoint();
602608 const char *templates[] = {
603609 CPUS_TEMPLATE_UNCORE,
....@@ -622,14 +628,11 @@
622628 static bool pmu_is_uncore(const char *name)
623629 {
624630 char path[PATH_MAX];
625
- struct cpu_map *cpus;
626
- const char *sysfs = sysfs__mountpoint();
631
+ const char *sysfs;
627632
633
+ sysfs = sysfs__mountpoint();
628634 snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
629
- cpus = __pmu_cpumask(path);
630
- cpu_map__put(cpus);
631
-
632
- return !!cpus;
635
+ return file_available(path);
633636 }
634637
635638 /*
....@@ -639,7 +642,6 @@
639642 */
640643 static int is_arm_pmu_core(const char *name)
641644 {
642
- struct stat st;
643645 char path[PATH_MAX];
644646 const char *sysfs = sysfs__mountpoint();
645647
....@@ -649,49 +651,7 @@
649651 /* Look for cpu sysfs (specific to arm) */
650652 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus",
651653 sysfs, name);
652
- if (stat(path, &st) == 0)
653
- return 1;
654
-
655
- return 0;
656
-}
657
-
658
-/*
659
- * Return the CPU id as a raw string.
660
- *
661
- * Each architecture should provide a more precise id string that
662
- * can be use to match the architecture's "mapfile".
663
- */
664
-char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
665
-{
666
- return NULL;
667
-}
668
-
669
-/* Return zero when the cpuid from the mapfile.csv matches the
670
- * cpuid string generated on this platform.
671
- * Otherwise return non-zero.
672
- */
673
-int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
674
-{
675
- regex_t re;
676
- regmatch_t pmatch[1];
677
- int match;
678
-
679
- if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
680
- /* Warn unable to generate match particular string. */
681
- pr_info("Invalid regular expression %s\n", mapcpuid);
682
- return 1;
683
- }
684
-
685
- match = !regexec(&re, cpuid, 1, pmatch, 0);
686
- regfree(&re);
687
- if (match) {
688
- size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
689
-
690
- /* Verify the entire string matched. */
691
- if (match_len == strlen(cpuid))
692
- return 0;
693
- }
694
- return 1;
654
+ return file_available(path);
695655 }
696656
697657 static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
....@@ -741,21 +701,56 @@
741701 return map;
742702 }
743703
704
+bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
705
+{
706
+ char *tmp = NULL, *tok, *str;
707
+ bool res;
708
+
709
+ str = strdup(pmu_name);
710
+ if (!str)
711
+ return false;
712
+
713
+ /*
714
+ * uncore alias may be from different PMU with common prefix
715
+ */
716
+ tok = strtok_r(str, ",", &tmp);
717
+ if (strncmp(pmu_name, tok, strlen(tok))) {
718
+ res = false;
719
+ goto out;
720
+ }
721
+
722
+ /*
723
+ * Match more complex aliases where the alias name is a comma-delimited
724
+ * list of tokens, orderly contained in the matching PMU name.
725
+ *
726
+ * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we
727
+ * match "socket" in "socketX_pmunameY" and then "pmuname" in
728
+ * "pmunameY".
729
+ */
730
+ for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) {
731
+ name = strstr(name, tok);
732
+ if (!name) {
733
+ res = false;
734
+ goto out;
735
+ }
736
+ }
737
+
738
+ res = true;
739
+out:
740
+ free(str);
741
+ return res;
742
+}
743
+
744744 /*
745745 * From the pmu_events_map, find the table of PMU events that corresponds
746746 * to the current running CPU. Then, add all PMU events from that table
747747 * as aliases.
748748 */
749
-static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
749
+void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu,
750
+ struct pmu_events_map *map)
750751 {
751752 int i;
752
- struct pmu_events_map *map;
753753 const char *name = pmu->name;
754
-
755
- map = perf_pmu__find_map(pmu);
756
- if (!map)
757
- return;
758
-
759754 /*
760755 * Found a matching PMU events table. Create aliases
761756 */
....@@ -771,12 +766,8 @@
771766 break;
772767 }
773768
774
- /*
775
- * uncore alias may be from different PMU
776
- * with common prefix
777
- */
778769 if (pmu_is_uncore(name) &&
779
- !strncmp(pname, name, strlen(pname)))
770
+ pmu_uncore_alias_match(pname, name))
780771 goto new_alias;
781772
782773 if (strcmp(pname, name))
....@@ -789,14 +780,39 @@
789780 (char *)pe->long_desc, (char *)pe->topic,
790781 (char *)pe->unit, (char *)pe->perpkg,
791782 (char *)pe->metric_expr,
792
- (char *)pe->metric_name);
783
+ (char *)pe->metric_name,
784
+ (char *)pe->deprecated);
793785 }
786
+}
787
+
788
+static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
789
+{
790
+ struct pmu_events_map *map;
791
+
792
+ map = perf_pmu__find_map(pmu);
793
+ if (!map)
794
+ return;
795
+
796
+ pmu_add_cpu_aliases_map(head, pmu, map);
794797 }
795798
796799 struct perf_event_attr * __weak
797800 perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
798801 {
799802 return NULL;
803
+}
804
+
805
+static int pmu_max_precise(const char *name)
806
+{
807
+ char path[PATH_MAX];
808
+ int max_precise = -1;
809
+
810
+ scnprintf(path, PATH_MAX,
811
+ "bus/event_source/devices/%s/caps/max_precise",
812
+ name);
813
+
814
+ sysfs__read_int(path, &max_precise);
815
+ return max_precise;
800816 }
801817
802818 static struct perf_pmu *pmu_lookup(const char *name)
....@@ -831,10 +847,12 @@
831847 pmu->name = strdup(name);
832848 pmu->type = type;
833849 pmu->is_uncore = pmu_is_uncore(name);
850
+ pmu->max_precise = pmu_max_precise(name);
834851 pmu_add_cpu_aliases(&aliases, pmu);
835852
836853 INIT_LIST_HEAD(&pmu->format);
837854 INIT_LIST_HEAD(&pmu->aliases);
855
+ INIT_LIST_HEAD(&pmu->caps);
838856 list_splice(&format, &pmu->format);
839857 list_splice(&aliases, &pmu->aliases);
840858 list_add_tail(&pmu->list, &pmus);
....@@ -844,12 +862,40 @@
844862 return pmu;
845863 }
846864
865
+void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu)
866
+{
867
+ struct perf_pmu_format *format;
868
+
869
+ /* fake pmu doesn't have format list */
870
+ if (pmu == &perf_pmu__fake)
871
+ return;
872
+
873
+ list_for_each_entry(format, &pmu->format, list)
874
+ if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) {
875
+ pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'"
876
+ "which is not supported by this version of perf!\n",
877
+ pmu->name, format->name, format->value);
878
+ return;
879
+ }
880
+}
881
+
847882 static struct perf_pmu *pmu_find(const char *name)
848883 {
849884 struct perf_pmu *pmu;
850885
851886 list_for_each_entry(pmu, &pmus, list)
852887 if (!strcmp(pmu->name, name))
888
+ return pmu;
889
+
890
+ return NULL;
891
+}
892
+
893
+struct perf_pmu *perf_pmu__find_by_type(unsigned int type)
894
+{
895
+ struct perf_pmu *pmu;
896
+
897
+ list_for_each_entry(pmu, &pmus, list)
898
+ if (pmu->type == type)
853899 return pmu;
854900
855901 return NULL;
....@@ -868,6 +914,25 @@
868914 list_for_each_entry_continue(pmu, &pmus, list)
869915 return pmu;
870916 return NULL;
917
+}
918
+
919
+struct perf_pmu *evsel__find_pmu(struct evsel *evsel)
920
+{
921
+ struct perf_pmu *pmu = NULL;
922
+
923
+ while ((pmu = perf_pmu__scan(pmu)) != NULL) {
924
+ if (pmu->type == evsel->core.attr.type)
925
+ break;
926
+ }
927
+
928
+ return pmu;
929
+}
930
+
931
+bool evsel__is_aux_event(struct evsel *evsel)
932
+{
933
+ struct perf_pmu *pmu = evsel__find_pmu(evsel);
934
+
935
+ return pmu && pmu->auxtrace;
871936 }
872937
873938 struct perf_pmu *perf_pmu__find(const char *name)
....@@ -911,6 +976,16 @@
911976 bits |= 1ULL << fbit;
912977
913978 return bits;
979
+}
980
+
981
+int perf_pmu__format_type(struct list_head *formats, const char *name)
982
+{
983
+ struct perf_pmu_format *format = pmu_find_format(formats, name);
984
+
985
+ if (!format)
986
+ return -1;
987
+
988
+ return format->value;
914989 }
915990
916991 /*
....@@ -960,12 +1035,11 @@
9601035 struct parse_events_term *t;
9611036
9621037 list_for_each_entry(t, head_terms, list) {
963
- if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
964
- if (!strcmp(t->config, term->config)) {
965
- t->used = true;
966
- *value = t->val.num;
967
- return 0;
968
- }
1038
+ if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM &&
1039
+ t->config && !strcmp(t->config, term->config)) {
1040
+ t->used = true;
1041
+ *value = t->val.num;
1042
+ return 0;
9691043 }
9701044 }
9711045
....@@ -1001,7 +1075,8 @@
10011075 * Setup one of config[12] attr members based on the
10021076 * user input data - term parameter.
10031077 */
1004
-static int pmu_config_term(struct list_head *formats,
1078
+static int pmu_config_term(const char *pmu_name,
1079
+ struct list_head *formats,
10051080 struct perf_event_attr *attr,
10061081 struct parse_events_term *term,
10071082 struct list_head *head_terms,
....@@ -1027,16 +1102,24 @@
10271102
10281103 format = pmu_find_format(formats, term->config);
10291104 if (!format) {
1030
- if (verbose > 0)
1031
- printf("Invalid event/parameter '%s'\n", term->config);
1032
- if (err) {
1033
- char *pmu_term = pmu_formats_string(formats);
1105
+ char *pmu_term = pmu_formats_string(formats);
1106
+ char *unknown_term;
1107
+ char *help_msg;
10341108
1035
- err->idx = term->err_term;
1036
- err->str = strdup("unknown term");
1037
- err->help = parse_events_formats_error_string(pmu_term);
1038
- free(pmu_term);
1109
+ if (asprintf(&unknown_term,
1110
+ "unknown term '%s' for pmu '%s'",
1111
+ term->config, pmu_name) < 0)
1112
+ unknown_term = NULL;
1113
+ help_msg = parse_events_formats_error_string(pmu_term);
1114
+ if (err) {
1115
+ parse_events__handle_error(err, term->err_term,
1116
+ unknown_term,
1117
+ help_msg);
1118
+ } else {
1119
+ pr_debug("%s (%s)\n", unknown_term, help_msg);
1120
+ free(unknown_term);
10391121 }
1122
+ free(pmu_term);
10401123 return -EINVAL;
10411124 }
10421125
....@@ -1062,8 +1145,9 @@
10621145 if (term->no_value &&
10631146 bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) {
10641147 if (err) {
1065
- err->idx = term->err_val;
1066
- err->str = strdup("no value assigned for term");
1148
+ parse_events__handle_error(err, term->err_val,
1149
+ strdup("no value assigned for term"),
1150
+ NULL);
10671151 }
10681152 return -EINVAL;
10691153 }
....@@ -1076,8 +1160,9 @@
10761160 term->config, term->val.str);
10771161 }
10781162 if (err) {
1079
- err->idx = term->err_val;
1080
- err->str = strdup("expected numeric value");
1163
+ parse_events__handle_error(err, term->err_val,
1164
+ strdup("expected numeric value"),
1165
+ NULL);
10811166 }
10821167 return -EINVAL;
10831168 }
....@@ -1090,11 +1175,15 @@
10901175 max_val = pmu_format_max_value(format->bits);
10911176 if (val > max_val) {
10921177 if (err) {
1093
- err->idx = term->err_val;
1094
- if (asprintf(&err->str,
1095
- "value too big for format, maximum is %llu",
1096
- (unsigned long long)max_val) < 0)
1097
- err->str = strdup("value too big for format");
1178
+ char *err_str;
1179
+
1180
+ parse_events__handle_error(err, term->err_val,
1181
+ asprintf(&err_str,
1182
+ "value too big for format, maximum is %llu",
1183
+ (unsigned long long)max_val) < 0
1184
+ ? strdup("value too big for format")
1185
+ : err_str,
1186
+ NULL);
10981187 return -EINVAL;
10991188 }
11001189 /*
....@@ -1107,7 +1196,7 @@
11071196 return 0;
11081197 }
11091198
1110
-int perf_pmu__config_terms(struct list_head *formats,
1199
+int perf_pmu__config_terms(const char *pmu_name, struct list_head *formats,
11111200 struct perf_event_attr *attr,
11121201 struct list_head *head_terms,
11131202 bool zero, struct parse_events_error *err)
....@@ -1115,7 +1204,7 @@
11151204 struct parse_events_term *term;
11161205
11171206 list_for_each_entry(term, head_terms, list) {
1118
- if (pmu_config_term(formats, attr, term, head_terms,
1207
+ if (pmu_config_term(pmu_name, formats, attr, term, head_terms,
11191208 zero, err))
11201209 return -EINVAL;
11211210 }
....@@ -1135,8 +1224,8 @@
11351224 bool zero = !!pmu->default_config;
11361225
11371226 attr->type = pmu->type;
1138
- return perf_pmu__config_terms(&pmu->format, attr, head_terms,
1139
- zero, err);
1227
+ return perf_pmu__config_terms(pmu->name, &pmu->format, attr,
1228
+ head_terms, zero, err);
11401229 }
11411230
11421231 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
....@@ -1235,8 +1324,8 @@
12351324 info->metric_expr = alias->metric_expr;
12361325 info->metric_name = alias->metric_name;
12371326
1238
- list_del(&term->list);
1239
- free(term);
1327
+ list_del_init(&term->list);
1328
+ parse_events_term__delete(term);
12401329 }
12411330
12421331 /*
....@@ -1341,6 +1430,7 @@
13411430 char *pmu;
13421431 char *metric_expr;
13431432 char *metric_name;
1433
+ int is_cpu;
13441434 };
13451435
13461436 static int cmp_sevent(const void *a, const void *b)
....@@ -1357,6 +1447,11 @@
13571447 if (n)
13581448 return n;
13591449 }
1450
+
1451
+ /* Order CPU core events to be first */
1452
+ if (as->is_cpu != bs->is_cpu)
1453
+ return bs->is_cpu - as->is_cpu;
1454
+
13601455 return strcmp(as->name, bs->name);
13611456 }
13621457
....@@ -1377,12 +1472,17 @@
13771472 break;
13781473 s += wlen;
13791474 column += n;
1380
- s = ltrim(s);
1475
+ s = skip_spaces(s);
13811476 }
13821477 }
13831478
1479
+bool is_pmu_core(const char *name)
1480
+{
1481
+ return !strcmp(name, "cpu") || is_arm_pmu_core(name);
1482
+}
1483
+
13841484 void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1385
- bool long_desc, bool details_flag)
1485
+ bool long_desc, bool details_flag, bool deprecated)
13861486 {
13871487 struct perf_pmu *pmu;
13881488 struct perf_pmu_alias *alias;
....@@ -1411,7 +1511,10 @@
14111511 list_for_each_entry(alias, &pmu->aliases, list) {
14121512 char *name = alias->desc ? alias->name :
14131513 format_alias(buf, sizeof(buf), pmu, alias);
1414
- bool is_cpu = !strcmp(pmu->name, "cpu");
1514
+ bool is_cpu = is_pmu_core(pmu->name);
1515
+
1516
+ if (alias->deprecated && !deprecated)
1517
+ continue;
14151518
14161519 if (event_glob != NULL &&
14171520 !(strglobmatch_nocase(name, event_glob) ||
....@@ -1440,6 +1543,7 @@
14401543 aliases[j].pmu = pmu->name;
14411544 aliases[j].metric_expr = alias->metric_expr;
14421545 aliases[j].metric_name = alias->metric_name;
1546
+ aliases[j].is_cpu = is_cpu;
14431547 j++;
14441548 }
14451549 if (pmu->selectable &&
....@@ -1518,7 +1622,6 @@
15181622
15191623 static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
15201624 {
1521
- struct stat st;
15221625 char path[PATH_MAX];
15231626 const char *sysfs;
15241627
....@@ -1528,10 +1631,8 @@
15281631
15291632 snprintf(path, PATH_MAX,
15301633 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
1531
-
1532
- if (stat(path, &st) < 0)
1634
+ if (!file_available(path))
15331635 return NULL;
1534
-
15351636 return fopen(path, "r");
15361637 }
15371638
....@@ -1551,3 +1652,117 @@
15511652 va_end(args);
15521653 return ret;
15531654 }
1655
+
1656
+static int perf_pmu__new_caps(struct list_head *list, char *name, char *value)
1657
+{
1658
+ struct perf_pmu_caps *caps = zalloc(sizeof(*caps));
1659
+
1660
+ if (!caps)
1661
+ return -ENOMEM;
1662
+
1663
+ caps->name = strdup(name);
1664
+ if (!caps->name)
1665
+ goto free_caps;
1666
+ caps->value = strndup(value, strlen(value) - 1);
1667
+ if (!caps->value)
1668
+ goto free_name;
1669
+ list_add_tail(&caps->list, list);
1670
+ return 0;
1671
+
1672
+free_name:
1673
+ zfree(caps->name);
1674
+free_caps:
1675
+ free(caps);
1676
+
1677
+ return -ENOMEM;
1678
+}
1679
+
1680
+/*
1681
+ * Reading/parsing the given pmu capabilities, which should be located at:
1682
+ * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes.
1683
+ * Return the number of capabilities
1684
+ */
1685
+int perf_pmu__caps_parse(struct perf_pmu *pmu)
1686
+{
1687
+ struct stat st;
1688
+ char caps_path[PATH_MAX];
1689
+ const char *sysfs = sysfs__mountpoint();
1690
+ DIR *caps_dir;
1691
+ struct dirent *evt_ent;
1692
+ int nr_caps = 0;
1693
+
1694
+ if (!sysfs)
1695
+ return -1;
1696
+
1697
+ snprintf(caps_path, PATH_MAX,
1698
+ "%s" EVENT_SOURCE_DEVICE_PATH "%s/caps", sysfs, pmu->name);
1699
+
1700
+ if (stat(caps_path, &st) < 0)
1701
+ return 0; /* no error if caps does not exist */
1702
+
1703
+ caps_dir = opendir(caps_path);
1704
+ if (!caps_dir)
1705
+ return -EINVAL;
1706
+
1707
+ while ((evt_ent = readdir(caps_dir)) != NULL) {
1708
+ char path[PATH_MAX + NAME_MAX + 1];
1709
+ char *name = evt_ent->d_name;
1710
+ char value[128];
1711
+ FILE *file;
1712
+
1713
+ if (!strcmp(name, ".") || !strcmp(name, ".."))
1714
+ continue;
1715
+
1716
+ snprintf(path, sizeof(path), "%s/%s", caps_path, name);
1717
+
1718
+ file = fopen(path, "r");
1719
+ if (!file)
1720
+ continue;
1721
+
1722
+ if (!fgets(value, sizeof(value), file) ||
1723
+ (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) {
1724
+ fclose(file);
1725
+ continue;
1726
+ }
1727
+
1728
+ nr_caps++;
1729
+ fclose(file);
1730
+ }
1731
+
1732
+ closedir(caps_dir);
1733
+
1734
+ return nr_caps;
1735
+}
1736
+
1737
+void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
1738
+ char *name)
1739
+{
1740
+ struct perf_pmu_format *format;
1741
+ __u64 masks = 0, bits;
1742
+ char buf[100];
1743
+ unsigned int i;
1744
+
1745
+ list_for_each_entry(format, &pmu->format, list) {
1746
+ if (format->value != PERF_PMU_FORMAT_VALUE_CONFIG)
1747
+ continue;
1748
+
1749
+ for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS)
1750
+ masks |= 1ULL << i;
1751
+ }
1752
+
1753
+ /*
1754
+ * Kernel doesn't export any valid format bits.
1755
+ */
1756
+ if (masks == 0)
1757
+ return;
1758
+
1759
+ bits = config & ~masks;
1760
+ if (bits == 0)
1761
+ return;
1762
+
1763
+ bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf));
1764
+
1765
+ pr_warning("WARNING: event '%s' not valid (bits %s of config "
1766
+ "'%llx' not supported by kernel)!\n",
1767
+ name ?: "N/A", buf, config);
1768
+}