aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-stat.c8
-rw-r--r--tools/perf/util/header.c48
-rw-r--r--tools/perf/util/include/linux/bitops.h2
-rw-r--r--tools/perf/util/parse-events-test.c122
-rw-r--r--tools/perf/util/parse-events.c71
-rw-r--r--tools/perf/util/parse-events.h15
-rw-r--r--tools/perf/util/parse-events.l129
-rw-r--r--tools/perf/util/parse-events.y71
-rw-r--r--tools/perf/util/pmu.c166
-rw-r--r--tools/perf/util/pmu.h11
-rw-r--r--tools/perf/util/session.c10
-rw-r--r--tools/perf/util/session.h1
12 files changed, 558 insertions, 96 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 875bf2675326..861f0aec77ae 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1179,6 +1179,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1179 fprintf(stderr, "cannot use both --output and --log-fd\n"); 1179 fprintf(stderr, "cannot use both --output and --log-fd\n");
1180 usage_with_options(stat_usage, options); 1180 usage_with_options(stat_usage, options);
1181 } 1181 }
1182
1183 if (output_fd < 0) {
1184 fprintf(stderr, "argument to --log-fd must be a > 0\n");
1185 usage_with_options(stat_usage, options);
1186 }
1187
1182 if (!output) { 1188 if (!output) {
1183 struct timespec tm; 1189 struct timespec tm;
1184 mode = append_file ? "a" : "w"; 1190 mode = append_file ? "a" : "w";
@@ -1190,7 +1196,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1190 } 1196 }
1191 clock_gettime(CLOCK_REALTIME, &tm); 1197 clock_gettime(CLOCK_REALTIME, &tm);
1192 fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); 1198 fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
1193 } else if (output_fd != 2) { 1199 } else if (output_fd > 0) {
1194 mode = append_file ? "a" : "w"; 1200 mode = append_file ? "a" : "w";
1195 output = fdopen(output_fd, mode); 1201 output = fdopen(output_fd, mode);
1196 if (!output) { 1202 if (!output) {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 07c8f3792954..a5e2015319ee 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1942,7 +1942,6 @@ int perf_file_header__read(struct perf_file_header *header,
1942 else 1942 else
1943 return -1; 1943 return -1;
1944 } else if (ph->needs_swap) { 1944 } else if (ph->needs_swap) {
1945 unsigned int i;
1946 /* 1945 /*
1947 * feature bitmap is declared as an array of unsigned longs -- 1946 * feature bitmap is declared as an array of unsigned longs --
1948 * not good since its size can differ between the host that 1947 * not good since its size can differ between the host that
@@ -1958,14 +1957,17 @@ int perf_file_header__read(struct perf_file_header *header,
1958 * file), punt and fallback to the original behavior -- 1957 * file), punt and fallback to the original behavior --
1959 * clearing all feature bits and setting buildid. 1958 * clearing all feature bits and setting buildid.
1960 */ 1959 */
1961 for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) 1960 mem_bswap_64(&header->adds_features,
1962 header->adds_features[i] = bswap_64(header->adds_features[i]); 1961 BITS_TO_U64(HEADER_FEAT_BITS));
1963 1962
1964 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { 1963 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
1965 for (i = 0; i < BITS_TO_LONGS(HEADER_FEAT_BITS); ++i) { 1964 /* unswap as u64 */
1966 header->adds_features[i] = bswap_64(header->adds_features[i]); 1965 mem_bswap_64(&header->adds_features,
1967 header->adds_features[i] = bswap_32(header->adds_features[i]); 1966 BITS_TO_U64(HEADER_FEAT_BITS));
1968 } 1967
1968 /* unswap as u32 */
1969 mem_bswap_32(&header->adds_features,
1970 BITS_TO_U32(HEADER_FEAT_BITS));
1969 } 1971 }
1970 1972
1971 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) { 1973 if (!test_bit(HEADER_HOSTNAME, header->adds_features)) {
@@ -2091,6 +2093,35 @@ static int read_attr(int fd, struct perf_header *ph,
2091 return ret <= 0 ? -1 : 0; 2093 return ret <= 0 ? -1 : 0;
2092} 2094}
2093 2095
2096static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel)
2097{
2098 struct event_format *event = trace_find_event(evsel->attr.config);
2099 char bf[128];
2100
2101 if (event == NULL)
2102 return -1;
2103
2104 snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
2105 evsel->name = strdup(bf);
2106 if (event->name == NULL)
2107 return -1;
2108
2109 return 0;
2110}
2111
2112static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist)
2113{
2114 struct perf_evsel *pos;
2115
2116 list_for_each_entry(pos, &evlist->entries, node) {
2117 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2118 perf_evsel__set_tracepoint_name(pos))
2119 return -1;
2120 }
2121
2122 return 0;
2123}
2124
2094int perf_session__read_header(struct perf_session *session, int fd) 2125int perf_session__read_header(struct perf_session *session, int fd)
2095{ 2126{
2096 struct perf_header *header = &session->header; 2127 struct perf_header *header = &session->header;
@@ -2172,6 +2203,9 @@ int perf_session__read_header(struct perf_session *session, int fd)
2172 2203
2173 lseek(fd, header->data_offset, SEEK_SET); 2204 lseek(fd, header->data_offset, SEEK_SET);
2174 2205
2206 if (perf_evlist__set_tracepoint_names(session->evlist))
2207 goto out_delete_evlist;
2208
2175 header->frozen = 1; 2209 header->frozen = 1;
2176 return 0; 2210 return 0;
2177out_errno: 2211out_errno:
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index f1584833bd22..587a230d2075 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -8,6 +8,8 @@
8#define BITS_PER_LONG __WORDSIZE 8#define BITS_PER_LONG __WORDSIZE
9#define BITS_PER_BYTE 8 9#define BITS_PER_BYTE 8
10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) 10#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
11#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
12#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
11 13
12#define for_each_set_bit(bit, addr, size) \ 14#define for_each_set_bit(bit, addr, size) \
13 for ((bit) = find_first_bit((addr), (size)); \ 15 for ((bit) = find_first_bit((addr), (size)); \
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index d0cf7c1ed068..229af6da33a2 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -430,6 +430,49 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
430 return 0; 430 return 0;
431} 431}
432 432
433static int test__checkterms_simple(struct list_head *terms)
434{
435 struct parse_events__term *term;
436
437 /* config=10 */
438 term = list_entry(terms->next, struct parse_events__term, list);
439 TEST_ASSERT_VAL("wrong type term",
440 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG);
441 TEST_ASSERT_VAL("wrong type val",
442 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
443 TEST_ASSERT_VAL("wrong val", term->val.num == 10);
444 TEST_ASSERT_VAL("wrong config", !term->config);
445
446 /* config1 */
447 term = list_entry(term->list.next, struct parse_events__term, list);
448 TEST_ASSERT_VAL("wrong type term",
449 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1);
450 TEST_ASSERT_VAL("wrong type val",
451 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
452 TEST_ASSERT_VAL("wrong val", term->val.num == 1);
453 TEST_ASSERT_VAL("wrong config", !term->config);
454
455 /* config2=3 */
456 term = list_entry(term->list.next, struct parse_events__term, list);
457 TEST_ASSERT_VAL("wrong type term",
458 term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2);
459 TEST_ASSERT_VAL("wrong type val",
460 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
461 TEST_ASSERT_VAL("wrong val", term->val.num == 3);
462 TEST_ASSERT_VAL("wrong config", !term->config);
463
464 /* umask=1*/
465 term = list_entry(term->list.next, struct parse_events__term, list);
466 TEST_ASSERT_VAL("wrong type term",
467 term->type_term == PARSE_EVENTS__TERM_TYPE_USER);
468 TEST_ASSERT_VAL("wrong type val",
469 term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
470 TEST_ASSERT_VAL("wrong val", term->val.num == 1);
471 TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "umask"));
472
473 return 0;
474}
475
433struct test__event_st { 476struct test__event_st {
434 const char *name; 477 const char *name;
435 __u32 type; 478 __u32 type;
@@ -559,7 +602,23 @@ static struct test__event_st test__events_pmu[] = {
559#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \ 602#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \
560 sizeof(struct test__event_st)) 603 sizeof(struct test__event_st))
561 604
562static int test(struct test__event_st *e) 605struct test__term {
606 const char *str;
607 __u32 type;
608 int (*check)(struct list_head *terms);
609};
610
611static struct test__term test__terms[] = {
612 [0] = {
613 .str = "config=10,config1,config2=3,umask=1",
614 .check = test__checkterms_simple,
615 },
616};
617
618#define TEST__TERMS_CNT (sizeof(test__terms) / \
619 sizeof(struct test__term))
620
621static int test_event(struct test__event_st *e)
563{ 622{
564 struct perf_evlist *evlist; 623 struct perf_evlist *evlist;
565 int ret; 624 int ret;
@@ -590,7 +649,48 @@ static int test_events(struct test__event_st *events, unsigned cnt)
590 struct test__event_st *e = &events[i]; 649 struct test__event_st *e = &events[i];
591 650
592 pr_debug("running test %d '%s'\n", i, e->name); 651 pr_debug("running test %d '%s'\n", i, e->name);
593 ret = test(e); 652 ret = test_event(e);
653 if (ret)
654 break;
655 }
656
657 return ret;
658}
659
660static int test_term(struct test__term *t)
661{
662 struct list_head *terms;
663 int ret;
664
665 terms = malloc(sizeof(*terms));
666 if (!terms)
667 return -ENOMEM;
668
669 INIT_LIST_HEAD(terms);
670
671 ret = parse_events_terms(terms, t->str);
672 if (ret) {
673 pr_debug("failed to parse terms '%s', err %d\n",
674 t->str , ret);
675 return ret;
676 }
677
678 ret = t->check(terms);
679 parse_events__free_terms(terms);
680
681 return ret;
682}
683
684static int test_terms(struct test__term *terms, unsigned cnt)
685{
686 int ret = 0;
687 unsigned i;
688
689 for (i = 0; i < cnt; i++) {
690 struct test__term *t = &terms[i];
691
692 pr_debug("running test %d '%s'\n", i, t->str);
693 ret = test_term(t);
594 if (ret) 694 if (ret)
595 break; 695 break;
596 } 696 }
@@ -617,9 +717,21 @@ int parse_events__test(void)
617{ 717{
618 int ret; 718 int ret;
619 719
620 ret = test_events(test__events, TEST__EVENTS_CNT); 720 do {
621 if (!ret && test_pmu()) 721 ret = test_events(test__events, TEST__EVENTS_CNT);
622 ret = test_events(test__events_pmu, TEST__EVENTS_PMU_CNT); 722 if (ret)
723 break;
724
725 if (test_pmu()) {
726 ret = test_events(test__events_pmu,
727 TEST__EVENTS_PMU_CNT);
728 if (ret)
729 break;
730 }
731
732 ret = test_terms(test__terms, TEST__TERMS_CNT);
733
734 } while (0);
623 735
624 return ret; 736 return ret;
625} 737}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index eacf932a36a0..0cc27da30ddb 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -11,6 +11,8 @@
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debugfs.h" 13#include "debugfs.h"
14#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int
14#include "parse-events-flex.h" 16#include "parse-events-flex.h"
15#include "pmu.h" 17#include "pmu.h"
16 18
@@ -26,7 +28,7 @@ struct event_symbol {
26#ifdef PARSER_DEBUG 28#ifdef PARSER_DEBUG
27extern int parse_events_debug; 29extern int parse_events_debug;
28#endif 30#endif
29int parse_events_parse(struct list_head *list, int *idx); 31int parse_events_parse(void *data, void *scanner);
30 32
31#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 33#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
32#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 34#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
@@ -529,6 +531,9 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
529 531
530 memset(&attr, 0, sizeof(attr)); 532 memset(&attr, 0, sizeof(attr));
531 533
534 if (perf_pmu__check_alias(pmu, head_config))
535 return -EINVAL;
536
532 /* 537 /*
533 * Configure hardcoded terms first, no need to check 538 * Configure hardcoded terms first, no need to check
534 * return value when called with fail == 0 ;) 539 * return value when called with fail == 0 ;)
@@ -617,27 +622,62 @@ int parse_events_modifier(struct list_head *list, char *str)
617 return 0; 622 return 0;
618} 623}
619 624
620int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) 625static int parse_events__scanner(const char *str, void *data, int start_token)
621{ 626{
622 LIST_HEAD(list);
623 LIST_HEAD(list_tmp);
624 YY_BUFFER_STATE buffer; 627 YY_BUFFER_STATE buffer;
625 int ret, idx = evlist->nr_entries; 628 void *scanner;
629 int ret;
630
631 ret = parse_events_lex_init_extra(start_token, &scanner);
632 if (ret)
633 return ret;
626 634
627 buffer = parse_events__scan_string(str); 635 buffer = parse_events__scan_string(str, scanner);
628 636
629#ifdef PARSER_DEBUG 637#ifdef PARSER_DEBUG
630 parse_events_debug = 1; 638 parse_events_debug = 1;
631#endif 639#endif
632 ret = parse_events_parse(&list, &idx); 640 ret = parse_events_parse(data, scanner);
641
642 parse_events__flush_buffer(buffer, scanner);
643 parse_events__delete_buffer(buffer, scanner);
644 parse_events_lex_destroy(scanner);
645 return ret;
646}
647
648/*
649 * parse event config string, return a list of event terms.
650 */
651int parse_events_terms(struct list_head *terms, const char *str)
652{
653 struct parse_events_data__terms data = {
654 .terms = NULL,
655 };
656 int ret;
657
658 ret = parse_events__scanner(str, &data, PE_START_TERMS);
659 if (!ret) {
660 list_splice(data.terms, terms);
661 free(data.terms);
662 return 0;
663 }
664
665 parse_events__free_terms(data.terms);
666 return ret;
667}
633 668
634 parse_events__flush_buffer(buffer); 669int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
635 parse_events__delete_buffer(buffer); 670{
636 parse_events_lex_destroy(); 671 struct parse_events_data__events data = {
672 .list = LIST_HEAD_INIT(data.list),
673 .idx = evlist->nr_entries,
674 };
675 int ret;
637 676
677 ret = parse_events__scanner(str, &data, PE_START_EVENTS);
638 if (!ret) { 678 if (!ret) {
639 int entries = idx - evlist->nr_entries; 679 int entries = data.idx - evlist->nr_entries;
640 perf_evlist__splice_list_tail(evlist, &list, entries); 680 perf_evlist__splice_list_tail(evlist, &data.list, entries);
641 return 0; 681 return 0;
642 } 682 }
643 683
@@ -937,6 +977,13 @@ int parse_events__term_str(struct parse_events__term **term,
937 config, str, 0); 977 config, str, 0);
938} 978}
939 979
980int parse_events__term_clone(struct parse_events__term **new,
981 struct parse_events__term *term)
982{
983 return new_term(new, term->type_val, term->type_term, term->config,
984 term->val.str, term->val.num);
985}
986
940void parse_events__free_terms(struct list_head *terms) 987void parse_events__free_terms(struct list_head *terms)
941{ 988{
942 struct parse_events__term *term, *h; 989 struct parse_events__term *term, *h;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 1784f06e3a6a..ee9c218a193c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -31,6 +31,7 @@ extern int parse_events_option(const struct option *opt, const char *str,
31 int unset); 31 int unset);
32extern int parse_events(struct perf_evlist *evlist, const char *str, 32extern int parse_events(struct perf_evlist *evlist, const char *str,
33 int unset); 33 int unset);
34extern int parse_events_terms(struct list_head *terms, const char *str);
34extern int parse_filter(const struct option *opt, const char *str, int unset); 35extern int parse_filter(const struct option *opt, const char *str, int unset);
35 36
36#define EVENTS_HELP_MAX (128*1024) 37#define EVENTS_HELP_MAX (128*1024)
@@ -61,11 +62,22 @@ struct parse_events__term {
61 struct list_head list; 62 struct list_head list;
62}; 63};
63 64
65struct parse_events_data__events {
66 struct list_head list;
67 int idx;
68};
69
70struct parse_events_data__terms {
71 struct list_head *terms;
72};
73
64int parse_events__is_hardcoded_term(struct parse_events__term *term); 74int parse_events__is_hardcoded_term(struct parse_events__term *term);
65int parse_events__term_num(struct parse_events__term **_term, 75int parse_events__term_num(struct parse_events__term **_term,
66 int type_term, char *config, long num); 76 int type_term, char *config, long num);
67int parse_events__term_str(struct parse_events__term **_term, 77int parse_events__term_str(struct parse_events__term **_term,
68 int type_term, char *config, char *str); 78 int type_term, char *config, char *str);
79int parse_events__term_clone(struct parse_events__term **new,
80 struct parse_events__term *term);
69void parse_events__free_terms(struct list_head *terms); 81void parse_events__free_terms(struct list_head *terms);
70int parse_events_modifier(struct list_head *list, char *str); 82int parse_events_modifier(struct list_head *list, char *str);
71int parse_events_add_tracepoint(struct list_head **list, int *idx, 83int parse_events_add_tracepoint(struct list_head **list, int *idx,
@@ -81,8 +93,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
81 char *pmu , struct list_head *head_config); 93 char *pmu , struct list_head *head_config);
82void parse_events_update_lists(struct list_head *list_event, 94void parse_events_update_lists(struct list_head *list_event,
83 struct list_head *list_all); 95 struct list_head *list_all);
84void parse_events_error(struct list_head *list_all, 96void parse_events_error(void *data, void *scanner, char const *msg);
85 int *idx, char const *msg);
86int parse_events__test(void); 97int parse_events__test(void);
87 98
88void print_events(const char *event_glob); 99void print_events(const char *event_glob);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 618a8e788399..488362e14133 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -1,4 +1,6 @@
1 1
2%option reentrant
3%option bison-bridge
2%option prefix="parse_events_" 4%option prefix="parse_events_"
3%option stack 5%option stack
4 6
@@ -8,7 +10,10 @@
8#include "parse-events-bison.h" 10#include "parse-events-bison.h"
9#include "parse-events.h" 11#include "parse-events.h"
10 12
11static int __value(char *str, int base, int token) 13char *parse_events_get_text(yyscan_t yyscanner);
14YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
15
16static int __value(YYSTYPE *yylval, char *str, int base, int token)
12{ 17{
13 long num; 18 long num;
14 19
@@ -17,35 +22,48 @@ static int __value(char *str, int base, int token)
17 if (errno) 22 if (errno)
18 return PE_ERROR; 23 return PE_ERROR;
19 24
20 parse_events_lval.num = num; 25 yylval->num = num;
21 return token; 26 return token;
22} 27}
23 28
24static int value(int base) 29static int value(yyscan_t scanner, int base)
25{ 30{
26 return __value(parse_events_text, base, PE_VALUE); 31 YYSTYPE *yylval = parse_events_get_lval(scanner);
32 char *text = parse_events_get_text(scanner);
33
34 return __value(yylval, text, base, PE_VALUE);
27} 35}
28 36
29static int raw(void) 37static int raw(yyscan_t scanner)
30{ 38{
31 return __value(parse_events_text + 1, 16, PE_RAW); 39 YYSTYPE *yylval = parse_events_get_lval(scanner);
40 char *text = parse_events_get_text(scanner);
41
42 return __value(yylval, text + 1, 16, PE_RAW);
32} 43}
33 44
34static int str(int token) 45static int str(yyscan_t scanner, int token)
35{ 46{
36 parse_events_lval.str = strdup(parse_events_text); 47 YYSTYPE *yylval = parse_events_get_lval(scanner);
48 char *text = parse_events_get_text(scanner);
49
50 yylval->str = strdup(text);
37 return token; 51 return token;
38} 52}
39 53
40static int sym(int type, int config) 54static int sym(yyscan_t scanner, int type, int config)
41{ 55{
42 parse_events_lval.num = (type << 16) + config; 56 YYSTYPE *yylval = parse_events_get_lval(scanner);
57
58 yylval->num = (type << 16) + config;
43 return PE_VALUE_SYM; 59 return PE_VALUE_SYM;
44} 60}
45 61
46static int term(int type) 62static int term(yyscan_t scanner, int type)
47{ 63{
48 parse_events_lval.num = type; 64 YYSTYPE *yylval = parse_events_get_lval(scanner);
65
66 yylval->num = type;
49 return PE_TERM; 67 return PE_TERM;
50} 68}
51 69
@@ -61,25 +79,38 @@ modifier_event [ukhpGH]{1,8}
61modifier_bp [rwx] 79modifier_bp [rwx]
62 80
63%% 81%%
64cpu-cycles|cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 82
65stalled-cycles-frontend|idle-cycles-frontend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 83%{
66stalled-cycles-backend|idle-cycles-backend { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 84 {
67instructions { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); } 85 int start_token;
68cache-references { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); } 86
69cache-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); } 87 start_token = (int) parse_events_get_extra(yyscanner);
70branch-instructions|branches { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } 88 if (start_token) {
71branch-misses { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); } 89 parse_events_set_extra(NULL, yyscanner);
72bus-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); } 90 return start_token;
73ref-cycles { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); } 91 }
74cpu-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); } 92 }
75task-clock { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); } 93%}
76page-faults|faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); } 94
77minor-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); } 95cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
78major-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); } 96stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
79context-switches|cs { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); } 97stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
80cpu-migrations|migrations { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); } 98instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
81alignment-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } 99cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
82emulation-faults { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 100cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
101branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
102branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
103bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
104ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
105cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
106task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
107page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
108minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
109major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
110context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
111cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
112alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
113emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
83 114
84L1-dcache|l1-d|l1d|L1-data | 115L1-dcache|l1-d|l1d|L1-data |
85L1-icache|l1-i|l1i|L1-instruction | 116L1-icache|l1-i|l1i|L1-instruction |
@@ -87,14 +118,14 @@ LLC|L2 |
87dTLB|d-tlb|Data-TLB | 118dTLB|d-tlb|Data-TLB |
88iTLB|i-tlb|Instruction-TLB | 119iTLB|i-tlb|Instruction-TLB |
89branch|branches|bpu|btb|bpc | 120branch|branches|bpu|btb|bpc |
90node { return str(PE_NAME_CACHE_TYPE); } 121node { return str(yyscanner, PE_NAME_CACHE_TYPE); }
91 122
92load|loads|read | 123load|loads|read |
93store|stores|write | 124store|stores|write |
94prefetch|prefetches | 125prefetch|prefetches |
95speculative-read|speculative-load | 126speculative-read|speculative-load |
96refs|Reference|ops|access | 127refs|Reference|ops|access |
97misses|miss { return str(PE_NAME_CACHE_OP_RESULT); } 128misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
98 129
99 /* 130 /*
100 * These are event config hardcoded term names to be specified 131 * These are event config hardcoded term names to be specified
@@ -102,20 +133,20 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
102 * so we can put them here directly. In case the we have a conflict 133 * so we can put them here directly. In case the we have a conflict
103 * in future, this needs to go into '//' condition block. 134 * in future, this needs to go into '//' condition block.
104 */ 135 */
105config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); } 136config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
106config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); } 137config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
107config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); } 138config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
108name { return term(PARSE_EVENTS__TERM_TYPE_NAME); } 139name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
109period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } 140period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
110branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 141branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
111 142
112mem: { BEGIN(mem); return PE_PREFIX_MEM; } 143mem: { BEGIN(mem); return PE_PREFIX_MEM; }
113r{num_raw_hex} { return raw(); } 144r{num_raw_hex} { return raw(yyscanner); }
114{num_dec} { return value(10); } 145{num_dec} { return value(yyscanner, 10); }
115{num_hex} { return value(16); } 146{num_hex} { return value(yyscanner, 16); }
116 147
117{modifier_event} { return str(PE_MODIFIER_EVENT); } 148{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
118{name} { return str(PE_NAME); } 149{name} { return str(yyscanner, PE_NAME); }
119"/" { return '/'; } 150"/" { return '/'; }
120- { return '-'; } 151- { return '-'; }
121, { return ','; } 152, { return ','; }
@@ -123,17 +154,17 @@ r{num_raw_hex} { return raw(); }
123= { return '='; } 154= { return '='; }
124 155
125<mem>{ 156<mem>{
126{modifier_bp} { return str(PE_MODIFIER_BP); } 157{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
127: { return ':'; } 158: { return ':'; }
128{num_dec} { return value(10); } 159{num_dec} { return value(yyscanner, 10); }
129{num_hex} { return value(16); } 160{num_hex} { return value(yyscanner, 16); }
130 /* 161 /*
131 * We need to separate 'mem:' scanner part, in order to get specific 162 * We need to separate 'mem:' scanner part, in order to get specific
132 * modifier bits parsed out. Otherwise we would need to handle PE_NAME 163 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
133 * and we'd need to parse it manually. During the escape from <mem> 164 * and we'd need to parse it manually. During the escape from <mem>
134 * state we need to put the escaping char back, so we dont miss it. 165 * state we need to put the escaping char back, so we dont miss it.
135 */ 166 */
136. { unput(*parse_events_text); BEGIN(INITIAL); } 167. { unput(*yytext); BEGIN(INITIAL); }
137 /* 168 /*
138 * We destroy the scanner after reaching EOF, 169 * We destroy the scanner after reaching EOF,
139 * but anyway just to be sure get back to INIT state. 170 * but anyway just to be sure get back to INIT state.
@@ -143,7 +174,7 @@ r{num_raw_hex} { return raw(); }
143 174
144%% 175%%
145 176
146int parse_events_wrap(void) 177int parse_events_wrap(void *scanner __used)
147{ 178{
148 return 1; 179 return 1;
149} 180}
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 362cc59332ae..9525c455d27f 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -1,7 +1,8 @@
1 1%pure-parser
2%name-prefix "parse_events_" 2%name-prefix "parse_events_"
3%parse-param {struct list_head *list_all} 3%parse-param {void *_data}
4%parse-param {int *idx} 4%parse-param {void *scanner}
5%lex-param {void* scanner}
5 6
6%{ 7%{
7 8
@@ -12,8 +13,9 @@
12#include "types.h" 13#include "types.h"
13#include "util.h" 14#include "util.h"
14#include "parse-events.h" 15#include "parse-events.h"
16#include "parse-events-bison.h"
15 17
16extern int parse_events_lex (void); 18extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
17 19
18#define ABORT_ON(val) \ 20#define ABORT_ON(val) \
19do { \ 21do { \
@@ -23,6 +25,7 @@ do { \
23 25
24%} 26%}
25 27
28%token PE_START_EVENTS PE_START_TERMS
26%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM 29%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM
27%token PE_NAME 30%token PE_NAME
28%token PE_MODIFIER_EVENT PE_MODIFIER_BP 31%token PE_MODIFIER_EVENT PE_MODIFIER_BP
@@ -58,24 +61,33 @@ do { \
58} 61}
59%% 62%%
60 63
64start:
65PE_START_EVENTS events
66|
67PE_START_TERMS terms
68
61events: 69events:
62events ',' event | event 70events ',' event | event
63 71
64event: 72event:
65event_def PE_MODIFIER_EVENT 73event_def PE_MODIFIER_EVENT
66{ 74{
75 struct parse_events_data__events *data = _data;
76
67 /* 77 /*
68 * Apply modifier on all events added by single event definition 78 * Apply modifier on all events added by single event definition
69 * (there could be more events added for multiple tracepoint 79 * (there could be more events added for multiple tracepoint
70 * definitions via '*?'. 80 * definitions via '*?'.
71 */ 81 */
72 ABORT_ON(parse_events_modifier($1, $2)); 82 ABORT_ON(parse_events_modifier($1, $2));
73 parse_events_update_lists($1, list_all); 83 parse_events_update_lists($1, &data->list);
74} 84}
75| 85|
76event_def 86event_def
77{ 87{
78 parse_events_update_lists($1, list_all); 88 struct parse_events_data__events *data = _data;
89
90 parse_events_update_lists($1, &data->list);
79} 91}
80 92
81event_def: event_pmu | 93event_def: event_pmu |
@@ -89,9 +101,10 @@ event_def: event_pmu |
89event_pmu: 101event_pmu:
90PE_NAME '/' event_config '/' 102PE_NAME '/' event_config '/'
91{ 103{
104 struct parse_events_data__events *data = _data;
92 struct list_head *list = NULL; 105 struct list_head *list = NULL;
93 106
94 ABORT_ON(parse_events_add_pmu(&list, idx, $1, $3)); 107 ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3));
95 parse_events__free_terms($3); 108 parse_events__free_terms($3);
96 $$ = list; 109 $$ = list;
97} 110}
@@ -99,94 +112,115 @@ PE_NAME '/' event_config '/'
99event_legacy_symbol: 112event_legacy_symbol:
100PE_VALUE_SYM '/' event_config '/' 113PE_VALUE_SYM '/' event_config '/'
101{ 114{
115 struct parse_events_data__events *data = _data;
102 struct list_head *list = NULL; 116 struct list_head *list = NULL;
103 int type = $1 >> 16; 117 int type = $1 >> 16;
104 int config = $1 & 255; 118 int config = $1 & 255;
105 119
106 ABORT_ON(parse_events_add_numeric(&list, idx, type, config, $3)); 120 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
121 type, config, $3));
107 parse_events__free_terms($3); 122 parse_events__free_terms($3);
108 $$ = list; 123 $$ = list;
109} 124}
110| 125|
111PE_VALUE_SYM sep_slash_dc 126PE_VALUE_SYM sep_slash_dc
112{ 127{
128 struct parse_events_data__events *data = _data;
113 struct list_head *list = NULL; 129 struct list_head *list = NULL;
114 int type = $1 >> 16; 130 int type = $1 >> 16;
115 int config = $1 & 255; 131 int config = $1 & 255;
116 132
117 ABORT_ON(parse_events_add_numeric(&list, idx, type, config, NULL)); 133 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
134 type, config, NULL));
118 $$ = list; 135 $$ = list;
119} 136}
120 137
121event_legacy_cache: 138event_legacy_cache:
122PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 139PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
123{ 140{
141 struct parse_events_data__events *data = _data;
124 struct list_head *list = NULL; 142 struct list_head *list = NULL;
125 143
126 ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, $5)); 144 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5));
127 $$ = list; 145 $$ = list;
128} 146}
129| 147|
130PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 148PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
131{ 149{
150 struct parse_events_data__events *data = _data;
132 struct list_head *list = NULL; 151 struct list_head *list = NULL;
133 152
134 ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, NULL)); 153 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL));
135 $$ = list; 154 $$ = list;
136} 155}
137| 156|
138PE_NAME_CACHE_TYPE 157PE_NAME_CACHE_TYPE
139{ 158{
159 struct parse_events_data__events *data = _data;
140 struct list_head *list = NULL; 160 struct list_head *list = NULL;
141 161
142 ABORT_ON(parse_events_add_cache(&list, idx, $1, NULL, NULL)); 162 ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL));
143 $$ = list; 163 $$ = list;
144} 164}
145 165
146event_legacy_mem: 166event_legacy_mem:
147PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 167PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
148{ 168{
169 struct parse_events_data__events *data = _data;
149 struct list_head *list = NULL; 170 struct list_head *list = NULL;
150 171
151 ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, $4)); 172 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
173 (void *) $2, $4));
152 $$ = list; 174 $$ = list;
153} 175}
154| 176|
155PE_PREFIX_MEM PE_VALUE sep_dc 177PE_PREFIX_MEM PE_VALUE sep_dc
156{ 178{
179 struct parse_events_data__events *data = _data;
157 struct list_head *list = NULL; 180 struct list_head *list = NULL;
158 181
159 ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, NULL)); 182 ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
183 (void *) $2, NULL));
160 $$ = list; 184 $$ = list;
161} 185}
162 186
163event_legacy_tracepoint: 187event_legacy_tracepoint:
164PE_NAME ':' PE_NAME 188PE_NAME ':' PE_NAME
165{ 189{
190 struct parse_events_data__events *data = _data;
166 struct list_head *list = NULL; 191 struct list_head *list = NULL;
167 192
168 ABORT_ON(parse_events_add_tracepoint(&list, idx, $1, $3)); 193 ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3));
169 $$ = list; 194 $$ = list;
170} 195}
171 196
172event_legacy_numeric: 197event_legacy_numeric:
173PE_VALUE ':' PE_VALUE 198PE_VALUE ':' PE_VALUE
174{ 199{
200 struct parse_events_data__events *data = _data;
175 struct list_head *list = NULL; 201 struct list_head *list = NULL;
176 202
177 ABORT_ON(parse_events_add_numeric(&list, idx, $1, $3, NULL)); 203 ABORT_ON(parse_events_add_numeric(&list, &data->idx, $1, $3, NULL));
178 $$ = list; 204 $$ = list;
179} 205}
180 206
181event_legacy_raw: 207event_legacy_raw:
182PE_RAW 208PE_RAW
183{ 209{
210 struct parse_events_data__events *data = _data;
184 struct list_head *list = NULL; 211 struct list_head *list = NULL;
185 212
186 ABORT_ON(parse_events_add_numeric(&list, idx, PERF_TYPE_RAW, $1, NULL)); 213 ABORT_ON(parse_events_add_numeric(&list, &data->idx,
214 PERF_TYPE_RAW, $1, NULL));
187 $$ = list; 215 $$ = list;
188} 216}
189 217
218terms: event_config
219{
220 struct parse_events_data__terms *data = _data;
221 data->terms = $1;
222}
223
190event_config: 224event_config:
191event_config ',' event_term 225event_config ',' event_term
192{ 226{
@@ -267,8 +301,7 @@ sep_slash_dc: '/' | ':' |
267 301
268%% 302%%
269 303
270void parse_events_error(struct list_head *list_all __used, 304void parse_events_error(void *data __used, void *scanner __used,
271 int *idx __used,
272 char const *msg __used) 305 char const *msg __used)
273{ 306{
274} 307}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index a119a5371699..74d0948ec368 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -80,6 +80,114 @@ static int pmu_format(char *name, struct list_head *format)
80 return 0; 80 return 0;
81} 81}
82 82
83static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
84{
85 struct perf_pmu__alias *alias;
86 char buf[256];
87 int ret;
88
89 ret = fread(buf, 1, sizeof(buf), file);
90 if (ret == 0)
91 return -EINVAL;
92 buf[ret] = 0;
93
94 alias = malloc(sizeof(*alias));
95 if (!alias)
96 return -ENOMEM;
97
98 INIT_LIST_HEAD(&alias->terms);
99 ret = parse_events_terms(&alias->terms, buf);
100 if (ret) {
101 free(alias);
102 return ret;
103 }
104
105 alias->name = strdup(name);
106 list_add_tail(&alias->list, list);
107 return 0;
108}
109
110/*
111 * Process all the sysfs attributes located under the directory
112 * specified in 'dir' parameter.
113 */
114static int pmu_aliases_parse(char *dir, struct list_head *head)
115{
116 struct dirent *evt_ent;
117 DIR *event_dir;
118 int ret = 0;
119
120 event_dir = opendir(dir);
121 if (!event_dir)
122 return -EINVAL;
123
124 while (!ret && (evt_ent = readdir(event_dir))) {
125 char path[PATH_MAX];
126 char *name = evt_ent->d_name;
127 FILE *file;
128
129 if (!strcmp(name, ".") || !strcmp(name, ".."))
130 continue;
131
132 snprintf(path, PATH_MAX, "%s/%s", dir, name);
133
134 ret = -EINVAL;
135 file = fopen(path, "r");
136 if (!file)
137 break;
138 ret = perf_pmu__new_alias(head, name, file);
139 fclose(file);
140 }
141
142 closedir(event_dir);
143 return ret;
144}
145
146/*
147 * Reading the pmu event aliases definition, which should be located at:
148 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
149 */
150static int pmu_aliases(char *name, struct list_head *head)
151{
152 struct stat st;
153 char path[PATH_MAX];
154 const char *sysfs;
155
156 sysfs = sysfs_find_mountpoint();
157 if (!sysfs)
158 return -1;
159
160 snprintf(path, PATH_MAX,
161 "%s/bus/event_source/devices/%s/events", sysfs, name);
162
163 if (stat(path, &st) < 0)
164 return -1;
165
166 if (pmu_aliases_parse(path, head))
167 return -1;
168
169 return 0;
170}
171
172static int pmu_alias_terms(struct perf_pmu__alias *alias,
173 struct list_head *terms)
174{
175 struct parse_events__term *term, *clone;
176 LIST_HEAD(list);
177 int ret;
178
179 list_for_each_entry(term, &alias->terms, list) {
180 ret = parse_events__term_clone(&clone, term);
181 if (ret) {
182 parse_events__free_terms(&list);
183 return ret;
184 }
185 list_add_tail(&clone->list, &list);
186 }
187 list_splice(&list, terms);
188 return 0;
189}
190
83/* 191/*
84 * Reading/parsing the default pmu type value, which should be 192 * Reading/parsing the default pmu type value, which should be
85 * located at: 193 * located at:
@@ -118,6 +226,7 @@ static struct perf_pmu *pmu_lookup(char *name)
118{ 226{
119 struct perf_pmu *pmu; 227 struct perf_pmu *pmu;
120 LIST_HEAD(format); 228 LIST_HEAD(format);
229 LIST_HEAD(aliases);
121 __u32 type; 230 __u32 type;
122 231
123 /* 232 /*
@@ -135,8 +244,12 @@ static struct perf_pmu *pmu_lookup(char *name)
135 if (!pmu) 244 if (!pmu)
136 return NULL; 245 return NULL;
137 246
247 pmu_aliases(name, &aliases);
248
138 INIT_LIST_HEAD(&pmu->format); 249 INIT_LIST_HEAD(&pmu->format);
250 INIT_LIST_HEAD(&pmu->aliases);
139 list_splice(&format, &pmu->format); 251 list_splice(&format, &pmu->format);
252 list_splice(&aliases, &pmu->aliases);
140 pmu->name = strdup(name); 253 pmu->name = strdup(name);
141 pmu->type = type; 254 pmu->type = type;
142 return pmu; 255 return pmu;
@@ -279,6 +392,59 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
279 return pmu_config(&pmu->format, attr, head_terms); 392 return pmu_config(&pmu->format, attr, head_terms);
280} 393}
281 394
395static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
396 struct parse_events__term *term)
397{
398 struct perf_pmu__alias *alias;
399 char *name;
400
401 if (parse_events__is_hardcoded_term(term))
402 return NULL;
403
404 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
405 if (term->val.num != 1)
406 return NULL;
407 if (pmu_find_format(&pmu->format, term->config))
408 return NULL;
409 name = term->config;
410 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
411 if (strcasecmp(term->config, "event"))
412 return NULL;
413 name = term->val.str;
414 } else {
415 return NULL;
416 }
417
418 list_for_each_entry(alias, &pmu->aliases, list) {
419 if (!strcasecmp(alias->name, name))
420 return alias;
421 }
422 return NULL;
423}
424
425/*
426 * Find alias in the terms list and replace it with the terms
427 * defined for the alias
428 */
429int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
430{
431 struct parse_events__term *term, *h;
432 struct perf_pmu__alias *alias;
433 int ret;
434
435 list_for_each_entry_safe(term, h, head_terms, list) {
436 alias = pmu_find_alias(pmu, term);
437 if (!alias)
438 continue;
439 ret = pmu_alias_terms(alias, &term->list);
440 if (ret)
441 return ret;
442 list_del(&term->list);
443 free(term);
444 }
445 return 0;
446}
447
282int perf_pmu__new_format(struct list_head *list, char *name, 448int perf_pmu__new_format(struct list_head *list, char *name,
283 int config, unsigned long *bits) 449 int config, unsigned long *bits)
284{ 450{
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 68c0db965e1f..535f2c5258ab 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -19,17 +19,26 @@ struct perf_pmu__format {
19 struct list_head list; 19 struct list_head list;
20}; 20};
21 21
22struct perf_pmu__alias {
23 char *name;
24 struct list_head terms;
25 struct list_head list;
26};
27
22struct perf_pmu { 28struct perf_pmu {
23 char *name; 29 char *name;
24 __u32 type; 30 __u32 type;
25 struct list_head format; 31 struct list_head format;
32 struct list_head aliases;
26 struct list_head list; 33 struct list_head list;
27}; 34};
28 35
29struct perf_pmu *perf_pmu__find(char *name); 36struct perf_pmu *perf_pmu__find(char *name);
30int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 37int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
31 struct list_head *head_terms); 38 struct list_head *head_terms);
32 39int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
40struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
41 struct list_head *head_terms);
33int perf_pmu_wrap(void); 42int perf_pmu_wrap(void);
34void perf_pmu_error(struct list_head *list, char *name, char const *msg); 43void perf_pmu_error(struct list_head *list, char *name, char const *msg);
35 44
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index febc0aeb3c66..6b305fbcc986 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -441,6 +441,16 @@ static void perf_tool__fill_defaults(struct perf_tool *tool)
441 tool->finished_round = process_finished_round_stub; 441 tool->finished_round = process_finished_round_stub;
442 } 442 }
443} 443}
444
445void mem_bswap_32(void *src, int byte_size)
446{
447 u32 *m = src;
448 while (byte_size > 0) {
449 *m = bswap_32(*m);
450 byte_size -= sizeof(u32);
451 ++m;
452 }
453}
444 454
445void mem_bswap_64(void *src, int byte_size) 455void mem_bswap_64(void *src, int byte_size)
446{ 456{
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 877d78186f2c..c71a1a7b05ed 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -80,6 +80,7 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
80bool perf_session__has_traces(struct perf_session *self, const char *msg); 80bool perf_session__has_traces(struct perf_session *self, const char *msg);
81 81
82void mem_bswap_64(void *src, int byte_size); 82void mem_bswap_64(void *src, int byte_size);
83void mem_bswap_32(void *src, int byte_size);
83void perf_event__attr_swap(struct perf_event_attr *attr); 84void perf_event__attr_swap(struct perf_event_attr *attr);
84 85
85int perf_session__create_kernel_maps(struct perf_session *self); 86int perf_session__create_kernel_maps(struct perf_session *self);