aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-08-24 06:01:02 -0400
committerIngo Molnar <mingo@kernel.org>2012-08-24 06:01:02 -0400
commit734e9a26d612f64e1c9cfd92256969b773954ae2 (patch)
treed6fd23e9cf7ea37d36060e877e856001d83e6c6c
parentd57c5d51a30152f3175d2344cb6395f08bf8ee0c (diff)
parentf63fe79fa0b1362e8ea1c1e4996cf70d14917b02 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: * Improve warning message when libunwind devel packages not present, from Jiri Olsa * Remove perf_event_attr needless version inflation, from Jiri Olsa * Introduce libtraceevent strerror like error reporting facility, from Namhyung Kim * Add pmu mappings to perf.data header and use event names from cmd line, from Robert Richter Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--include/linux/perf_event.h4
-rw-r--r--tools/lib/traceevent/event-parse.c104
-rw-r--r--tools/lib/traceevent/event-parse.h34
-rw-r--r--tools/lib/traceevent/event-utils.h6
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/util/header.c265
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/parse-events-test.c37
-rw-r--r--tools/perf/util/parse-events.c12
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/parse-events.l50
-rw-r--r--tools/perf/util/parse-events.y20
-rw-r--r--tools/perf/util/pmu.c50
-rw-r--r--tools/perf/util/pmu.h2
14 files changed, 487 insertions, 101 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 297ca3db6b4a..28f9cee3fbc3 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -205,8 +205,8 @@ enum perf_event_read_format {
205#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ 205#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
206#define PERF_ATTR_SIZE_VER1 72 /* add: config2 */ 206#define PERF_ATTR_SIZE_VER1 72 /* add: config2 */
207#define PERF_ATTR_SIZE_VER2 80 /* add: branch_sample_type */ 207#define PERF_ATTR_SIZE_VER2 80 /* add: branch_sample_type */
208#define PERF_ATTR_SIZE_VER3 88 /* add: sample_regs_user */ 208#define PERF_ATTR_SIZE_VER3 96 /* add: sample_regs_user */
209#define PERF_ATTR_SIZE_VER4 96 /* add: sample_stack_user */ 209 /* add: sample_stack_user */
210 210
211/* 211/*
212 * Hardware event_id to monitor via a performance monitoring event: 212 * Hardware event_id to monitor via a performance monitoring event:
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index b7c2c491f61e..b5b4d806ffa2 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -4686,9 +4686,8 @@ static int find_event_handle(struct pevent *pevent, struct event_format *event)
4686 * 4686 *
4687 * /sys/kernel/debug/tracing/events/.../.../format 4687 * /sys/kernel/debug/tracing/events/.../.../format
4688 */ 4688 */
4689int pevent_parse_event(struct pevent *pevent, 4689enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
4690 const char *buf, unsigned long size, 4690 unsigned long size, const char *sys)
4691 const char *sys)
4692{ 4691{
4693 struct event_format *event; 4692 struct event_format *event;
4694 int ret; 4693 int ret;
@@ -4697,17 +4696,16 @@ int pevent_parse_event(struct pevent *pevent,
4697 4696
4698 event = alloc_event(); 4697 event = alloc_event();
4699 if (!event) 4698 if (!event)
4700 return -ENOMEM; 4699 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
4701 4700
4702 event->name = event_read_name(); 4701 event->name = event_read_name();
4703 if (!event->name) { 4702 if (!event->name) {
4704 /* Bad event? */ 4703 /* Bad event? */
4705 free(event); 4704 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
4706 return -1; 4705 goto event_alloc_failed;
4707 } 4706 }
4708 4707
4709 if (strcmp(sys, "ftrace") == 0) { 4708 if (strcmp(sys, "ftrace") == 0) {
4710
4711 event->flags |= EVENT_FL_ISFTRACE; 4709 event->flags |= EVENT_FL_ISFTRACE;
4712 4710
4713 if (strcmp(event->name, "bprint") == 0) 4711 if (strcmp(event->name, "bprint") == 0)
@@ -4715,20 +4713,28 @@ int pevent_parse_event(struct pevent *pevent,
4715 } 4713 }
4716 4714
4717 event->id = event_read_id(); 4715 event->id = event_read_id();
4718 if (event->id < 0) 4716 if (event->id < 0) {
4719 die("failed to read event id"); 4717 ret = PEVENT_ERRNO__READ_ID_FAILED;
4718 /*
4719 * This isn't an allocation error actually.
4720 * But as the ID is critical, just bail out.
4721 */
4722 goto event_alloc_failed;
4723 }
4720 4724
4721 event->system = strdup(sys); 4725 event->system = strdup(sys);
4722 if (!event->system) 4726 if (!event->system) {
4723 die("failed to allocate system"); 4727 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
4728 goto event_alloc_failed;
4729 }
4724 4730
4725 /* Add pevent to event so that it can be referenced */ 4731 /* Add pevent to event so that it can be referenced */
4726 event->pevent = pevent; 4732 event->pevent = pevent;
4727 4733
4728 ret = event_read_format(event); 4734 ret = event_read_format(event);
4729 if (ret < 0) { 4735 if (ret < 0) {
4730 do_warning("failed to read event format for %s", event->name); 4736 ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
4731 goto event_failed; 4737 goto event_parse_failed;
4732 } 4738 }
4733 4739
4734 /* 4740 /*
@@ -4740,10 +4746,9 @@ int pevent_parse_event(struct pevent *pevent,
4740 4746
4741 ret = event_read_print(event); 4747 ret = event_read_print(event);
4742 if (ret < 0) { 4748 if (ret < 0) {
4743 do_warning("failed to read event print fmt for %s",
4744 event->name);
4745 show_warning = 1; 4749 show_warning = 1;
4746 goto event_failed; 4750 ret = PEVENT_ERRNO__READ_PRINT_FAILED;
4751 goto event_parse_failed;
4747 } 4752 }
4748 show_warning = 1; 4753 show_warning = 1;
4749 4754
@@ -4754,20 +4759,19 @@ int pevent_parse_event(struct pevent *pevent,
4754 struct print_arg *arg, **list; 4759 struct print_arg *arg, **list;
4755 4760
4756 /* old ftrace had no args */ 4761 /* old ftrace had no args */
4757
4758 list = &event->print_fmt.args; 4762 list = &event->print_fmt.args;
4759 for (field = event->format.fields; field; field = field->next) { 4763 for (field = event->format.fields; field; field = field->next) {
4760 arg = alloc_arg(); 4764 arg = alloc_arg();
4761 *list = arg;
4762 list = &arg->next;
4763 arg->type = PRINT_FIELD; 4765 arg->type = PRINT_FIELD;
4764 arg->field.name = strdup(field->name); 4766 arg->field.name = strdup(field->name);
4765 if (!arg->field.name) { 4767 if (!arg->field.name) {
4766 do_warning("failed to allocate field name");
4767 event->flags |= EVENT_FL_FAILED; 4768 event->flags |= EVENT_FL_FAILED;
4768 return -1; 4769 free_arg(arg);
4770 return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
4769 } 4771 }
4770 arg->field.field = field; 4772 arg->field.field = field;
4773 *list = arg;
4774 list = &arg->next;
4771 } 4775 }
4772 return 0; 4776 return 0;
4773 } 4777 }
@@ -4778,11 +4782,65 @@ int pevent_parse_event(struct pevent *pevent,
4778 4782
4779 return 0; 4783 return 0;
4780 4784
4781 event_failed: 4785 event_parse_failed:
4782 event->flags |= EVENT_FL_FAILED; 4786 event->flags |= EVENT_FL_FAILED;
4783 /* still add it even if it failed */ 4787 /* still add it even if it failed */
4784 add_event(pevent, event); 4788 add_event(pevent, event);
4785 return -1; 4789 return ret;
4790
4791 event_alloc_failed:
4792 free(event->system);
4793 free(event->name);
4794 free(event);
4795 return ret;
4796}
4797
4798#undef _PE
4799#define _PE(code, str) str
4800static const char * const pevent_error_str[] = {
4801 PEVENT_ERRORS
4802};
4803#undef _PE
4804
4805int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
4806 char *buf, size_t buflen)
4807{
4808 int idx;
4809 const char *msg;
4810
4811 if (errnum >= 0) {
4812 msg = strerror_r(errnum, buf, buflen);
4813 if (msg != buf) {
4814 size_t len = strlen(msg);
4815 char *c = mempcpy(buf, msg, min(buflen-1, len));
4816 *c = '\0';
4817 }
4818 return 0;
4819 }
4820
4821 if (errnum <= __PEVENT_ERRNO__START ||
4822 errnum >= __PEVENT_ERRNO__END)
4823 return -1;
4824
4825 idx = errnum - __PEVENT_ERRNO__START - 1;
4826 msg = pevent_error_str[idx];
4827
4828 switch (errnum) {
4829 case PEVENT_ERRNO__MEM_ALLOC_FAILED:
4830 case PEVENT_ERRNO__PARSE_EVENT_FAILED:
4831 case PEVENT_ERRNO__READ_ID_FAILED:
4832 case PEVENT_ERRNO__READ_FORMAT_FAILED:
4833 case PEVENT_ERRNO__READ_PRINT_FAILED:
4834 case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED:
4835 snprintf(buf, buflen, "%s", msg);
4836 break;
4837
4838 default:
4839 /* cannot reach here */
4840 break;
4841 }
4842
4843 return 0;
4786} 4844}
4787 4845
4788int get_field_val(struct trace_seq *s, struct format_field *field, 4846int get_field_val(struct trace_seq *s, struct format_field *field,
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 5772ad8cb386..527df038a25f 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -345,6 +345,34 @@ enum pevent_flag {
345 PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */ 345 PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */
346}; 346};
347 347
348#define PEVENT_ERRORS \
349 _PE(MEM_ALLOC_FAILED, "failed to allocate memory"), \
350 _PE(PARSE_EVENT_FAILED, "failed to parse event"), \
351 _PE(READ_ID_FAILED, "failed to read event id"), \
352 _PE(READ_FORMAT_FAILED, "failed to read event format"), \
353 _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \
354 _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace")
355
356#undef _PE
357#define _PE(__code, __str) PEVENT_ERRNO__ ## __code
358enum pevent_errno {
359 PEVENT_ERRNO__SUCCESS = 0,
360
361 /*
362 * Choose an arbitrary negative big number not to clash with standard
363 * errno since SUS requires the errno has distinct positive values.
364 * See 'Issue 6' in the link below.
365 *
366 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
367 */
368 __PEVENT_ERRNO__START = -100000,
369
370 PEVENT_ERRORS,
371
372 __PEVENT_ERRNO__END,
373};
374#undef _PE
375
348struct cmdline; 376struct cmdline;
349struct cmdline_list; 377struct cmdline_list;
350struct func_map; 378struct func_map;
@@ -509,8 +537,8 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
509int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size, 537int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
510 int long_size); 538 int long_size);
511 539
512int pevent_parse_event(struct pevent *pevent, const char *buf, 540enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
513 unsigned long size, const char *sys); 541 unsigned long size, const char *sys);
514 542
515void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event, 543void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
516 const char *name, struct pevent_record *record, 544 const char *name, struct pevent_record *record,
@@ -561,6 +589,8 @@ int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
561const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid); 589const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
562void pevent_event_info(struct trace_seq *s, struct event_format *event, 590void pevent_event_info(struct trace_seq *s, struct event_format *event,
563 struct pevent_record *record); 591 struct pevent_record *record);
592int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
593 char *buf, size_t buflen);
564 594
565struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type); 595struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type);
566struct format_field **pevent_event_common_fields(struct event_format *event); 596struct format_field **pevent_event_common_fields(struct event_format *event);
diff --git a/tools/lib/traceevent/event-utils.h b/tools/lib/traceevent/event-utils.h
index 08296383d1e6..bc075006966e 100644
--- a/tools/lib/traceevent/event-utils.h
+++ b/tools/lib/traceevent/event-utils.h
@@ -39,6 +39,12 @@ void __vdie(const char *fmt, ...);
39void __vwarning(const char *fmt, ...); 39void __vwarning(const char *fmt, ...);
40void __vpr_stat(const char *fmt, ...); 40void __vpr_stat(const char *fmt, ...);
41 41
42#define min(x, y) ({ \
43 typeof(x) _min1 = (x); \
44 typeof(y) _min2 = (y); \
45 (void) (&_min1 == &_min2); \
46 _min1 < _min2 ? _min1 : _min2; })
47
42static inline char *strim(char *string) 48static inline char *strim(char *string)
43{ 49{
44 char *ret; 50 char *ret;
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 6bd888d04b6e..722ddee61f9f 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -493,7 +493,7 @@ endif
493 493
494FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) 494FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
495ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y) 495ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y)
496 msg := $(warning No libunwind found. Please install libunwind >= 0.99); 496 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
497 NO_LIBUNWIND := 1 497 NO_LIBUNWIND := 1
498endif # Libunwind support 498endif # Libunwind support
499endif # NO_LIBUNWIND 499endif # NO_LIBUNWIND
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1e5b6aa60523..9696e64c9dbd 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -20,6 +20,7 @@
20#include "symbol.h" 20#include "symbol.h"
21#include "debug.h" 21#include "debug.h"
22#include "cpumap.h" 22#include "cpumap.h"
23#include "pmu.h"
23 24
24static bool no_buildid_cache = false; 25static bool no_buildid_cache = false;
25 26
@@ -1004,6 +1005,45 @@ done:
1004} 1005}
1005 1006
1006/* 1007/*
1008 * File format:
1009 *
1010 * struct pmu_mappings {
1011 * u32 pmu_num;
1012 * struct pmu_map {
1013 * u32 type;
1014 * char name[];
1015 * }[pmu_num];
1016 * };
1017 */
1018
1019static int write_pmu_mappings(int fd, struct perf_header *h __used,
1020 struct perf_evlist *evlist __used)
1021{
1022 struct perf_pmu *pmu = NULL;
1023 off_t offset = lseek(fd, 0, SEEK_CUR);
1024 __u32 pmu_num = 0;
1025
1026 /* write real pmu_num later */
1027 do_write(fd, &pmu_num, sizeof(pmu_num));
1028
1029 while ((pmu = perf_pmu__scan(pmu))) {
1030 if (!pmu->name)
1031 continue;
1032 pmu_num++;
1033 do_write(fd, &pmu->type, sizeof(pmu->type));
1034 do_write_string(fd, pmu->name);
1035 }
1036
1037 if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
1038 /* discard all */
1039 lseek(fd, offset, SEEK_SET);
1040 return -1;
1041 }
1042
1043 return 0;
1044}
1045
1046/*
1007 * default get_cpuid(): nothing gets recorded 1047 * default get_cpuid(): nothing gets recorded
1008 * actual implementation must be in arch/$(ARCH)/util/header.c 1048 * actual implementation must be in arch/$(ARCH)/util/header.c
1009 */ 1049 */
@@ -1148,12 +1188,29 @@ static void print_cpu_topology(struct perf_header *ph, int fd, FILE *fp)
1148 } 1188 }
1149} 1189}
1150 1190
1151static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) 1191static void free_event_desc(struct perf_evsel *events)
1192{
1193 struct perf_evsel *evsel;
1194
1195 if (!events)
1196 return;
1197
1198 for (evsel = events; evsel->attr.size; evsel++) {
1199 if (evsel->name)
1200 free(evsel->name);
1201 if (evsel->id)
1202 free(evsel->id);
1203 }
1204
1205 free(events);
1206}
1207
1208static struct perf_evsel *
1209read_event_desc(struct perf_header *ph, int fd)
1152{ 1210{
1153 struct perf_event_attr attr; 1211 struct perf_evsel *evsel, *events = NULL;
1154 uint64_t id; 1212 u64 *id;
1155 void *buf = NULL; 1213 void *buf = NULL;
1156 char *str;
1157 u32 nre, sz, nr, i, j; 1214 u32 nre, sz, nr, i, j;
1158 ssize_t ret; 1215 ssize_t ret;
1159 size_t msz; 1216 size_t msz;
@@ -1173,18 +1230,22 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1173 if (ph->needs_swap) 1230 if (ph->needs_swap)
1174 sz = bswap_32(sz); 1231 sz = bswap_32(sz);
1175 1232
1176 memset(&attr, 0, sizeof(attr));
1177
1178 /* buffer to hold on file attr struct */ 1233 /* buffer to hold on file attr struct */
1179 buf = malloc(sz); 1234 buf = malloc(sz);
1180 if (!buf) 1235 if (!buf)
1181 goto error; 1236 goto error;
1182 1237
1183 msz = sizeof(attr); 1238 /* the last event terminates with evsel->attr.size == 0: */
1239 events = calloc(nre + 1, sizeof(*events));
1240 if (!events)
1241 goto error;
1242
1243 msz = sizeof(evsel->attr);
1184 if (sz < msz) 1244 if (sz < msz)
1185 msz = sz; 1245 msz = sz;
1186 1246
1187 for (i = 0 ; i < nre; i++) { 1247 for (i = 0, evsel = events; i < nre; evsel++, i++) {
1248 evsel->idx = i;
1188 1249
1189 /* 1250 /*
1190 * must read entire on-file attr struct to 1251 * must read entire on-file attr struct to
@@ -1197,7 +1258,7 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1197 if (ph->needs_swap) 1258 if (ph->needs_swap)
1198 perf_event__attr_swap(buf); 1259 perf_event__attr_swap(buf);
1199 1260
1200 memcpy(&attr, buf, msz); 1261 memcpy(&evsel->attr, buf, msz);
1201 1262
1202 ret = read(fd, &nr, sizeof(nr)); 1263 ret = read(fd, &nr, sizeof(nr));
1203 if (ret != (ssize_t)sizeof(nr)) 1264 if (ret != (ssize_t)sizeof(nr))
@@ -1206,51 +1267,82 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1206 if (ph->needs_swap) 1267 if (ph->needs_swap)
1207 nr = bswap_32(nr); 1268 nr = bswap_32(nr);
1208 1269
1209 str = do_read_string(fd, ph); 1270 evsel->name = do_read_string(fd, ph);
1210 fprintf(fp, "# event : name = %s, ", str); 1271
1211 free(str); 1272 if (!nr)
1273 continue;
1274
1275 id = calloc(nr, sizeof(*id));
1276 if (!id)
1277 goto error;
1278 evsel->ids = nr;
1279 evsel->id = id;
1280
1281 for (j = 0 ; j < nr; j++) {
1282 ret = read(fd, id, sizeof(*id));
1283 if (ret != (ssize_t)sizeof(*id))
1284 goto error;
1285 if (ph->needs_swap)
1286 *id = bswap_64(*id);
1287 id++;
1288 }
1289 }
1290out:
1291 if (buf)
1292 free(buf);
1293 return events;
1294error:
1295 if (events)
1296 free_event_desc(events);
1297 events = NULL;
1298 goto out;
1299}
1300
1301static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1302{
1303 struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
1304 u32 j;
1305 u64 *id;
1306
1307 if (!events) {
1308 fprintf(fp, "# event desc: not available or unable to read\n");
1309 return;
1310 }
1311
1312 for (evsel = events; evsel->attr.size; evsel++) {
1313 fprintf(fp, "# event : name = %s, ", evsel->name);
1212 1314
1213 fprintf(fp, "type = %d, config = 0x%"PRIx64 1315 fprintf(fp, "type = %d, config = 0x%"PRIx64
1214 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64, 1316 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
1215 attr.type, 1317 evsel->attr.type,
1216 (u64)attr.config, 1318 (u64)evsel->attr.config,
1217 (u64)attr.config1, 1319 (u64)evsel->attr.config1,
1218 (u64)attr.config2); 1320 (u64)evsel->attr.config2);
1219 1321
1220 fprintf(fp, ", excl_usr = %d, excl_kern = %d", 1322 fprintf(fp, ", excl_usr = %d, excl_kern = %d",
1221 attr.exclude_user, 1323 evsel->attr.exclude_user,
1222 attr.exclude_kernel); 1324 evsel->attr.exclude_kernel);
1223 1325
1224 fprintf(fp, ", excl_host = %d, excl_guest = %d", 1326 fprintf(fp, ", excl_host = %d, excl_guest = %d",
1225 attr.exclude_host, 1327 evsel->attr.exclude_host,
1226 attr.exclude_guest); 1328 evsel->attr.exclude_guest);
1227 1329
1228 fprintf(fp, ", precise_ip = %d", attr.precise_ip); 1330 fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
1229 1331
1230 if (nr) 1332 if (evsel->ids) {
1231 fprintf(fp, ", id = {"); 1333 fprintf(fp, ", id = {");
1232 1334 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
1233 for (j = 0 ; j < nr; j++) { 1335 if (j)
1234 ret = read(fd, &id, sizeof(id)); 1336 fputc(',', fp);
1235 if (ret != (ssize_t)sizeof(id)) 1337 fprintf(fp, " %"PRIu64, *id);
1236 goto error; 1338 }
1237
1238 if (ph->needs_swap)
1239 id = bswap_64(id);
1240
1241 if (j)
1242 fputc(',', fp);
1243
1244 fprintf(fp, " %"PRIu64, id);
1245 }
1246 if (nr && j == nr)
1247 fprintf(fp, " }"); 1339 fprintf(fp, " }");
1340 }
1341
1248 fputc('\n', fp); 1342 fputc('\n', fp);
1249 } 1343 }
1250 free(buf); 1344
1251 return; 1345 free_event_desc(events);
1252error:
1253 fprintf(fp, "# event desc: not available or unable to read\n");
1254} 1346}
1255 1347
1256static void print_total_mem(struct perf_header *h __used, int fd, FILE *fp) 1348static void print_total_mem(struct perf_header *h __used, int fd, FILE *fp)
@@ -1337,6 +1429,43 @@ static void print_branch_stack(struct perf_header *ph __used, int fd __used,
1337 fprintf(fp, "# contains samples with branch stack\n"); 1429 fprintf(fp, "# contains samples with branch stack\n");
1338} 1430}
1339 1431
1432static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp)
1433{
1434 const char *delimiter = "# pmu mappings: ";
1435 char *name;
1436 int ret;
1437 u32 pmu_num;
1438 u32 type;
1439
1440 ret = read(fd, &pmu_num, sizeof(pmu_num));
1441 if (ret != sizeof(pmu_num))
1442 goto error;
1443
1444 if (!pmu_num) {
1445 fprintf(fp, "# pmu mappings: not available\n");
1446 return;
1447 }
1448
1449 while (pmu_num) {
1450 if (read(fd, &type, sizeof(type)) != sizeof(type))
1451 break;
1452 name = do_read_string(fd, ph);
1453 if (!name)
1454 break;
1455 pmu_num--;
1456 fprintf(fp, "%s%s = %" PRIu32, delimiter, name, type);
1457 free(name);
1458 delimiter = ", ";
1459 }
1460
1461 fprintf(fp, "\n");
1462
1463 if (!pmu_num)
1464 return;
1465error:
1466 fprintf(fp, "# pmu mappings: unable to read\n");
1467}
1468
1340static int __event_process_build_id(struct build_id_event *bev, 1469static int __event_process_build_id(struct build_id_event *bev,
1341 char *filename, 1470 char *filename,
1342 struct perf_session *session) 1471 struct perf_session *session)
@@ -1504,6 +1633,56 @@ static int process_build_id(struct perf_file_section *section,
1504 return 0; 1633 return 0;
1505} 1634}
1506 1635
1636static struct perf_evsel *
1637perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
1638{
1639 struct perf_evsel *evsel;
1640
1641 list_for_each_entry(evsel, &evlist->entries, node) {
1642 if (evsel->idx == idx)
1643 return evsel;
1644 }
1645
1646 return NULL;
1647}
1648
1649static void
1650perf_evlist__set_event_name(struct perf_evlist *evlist, struct perf_evsel *event)
1651{
1652 struct perf_evsel *evsel;
1653
1654 if (!event->name)
1655 return;
1656
1657 evsel = perf_evlist__find_by_index(evlist, event->idx);
1658 if (!evsel)
1659 return;
1660
1661 if (evsel->name)
1662 return;
1663
1664 evsel->name = strdup(event->name);
1665}
1666
1667static int
1668process_event_desc(struct perf_file_section *section __unused,
1669 struct perf_header *header, int feat __unused, int fd,
1670 void *data __used)
1671{
1672 struct perf_session *session = container_of(header, struct perf_session, header);
1673 struct perf_evsel *evsel, *events = read_event_desc(header, fd);
1674
1675 if (!events)
1676 return 0;
1677
1678 for (evsel = events; evsel->attr.size; evsel++)
1679 perf_evlist__set_event_name(session->evlist, evsel);
1680
1681 free_event_desc(events);
1682
1683 return 0;
1684}
1685
1507struct feature_ops { 1686struct feature_ops {
1508 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1687 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1509 void (*print)(struct perf_header *h, int fd, FILE *fp); 1688 void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1537,11 +1716,12 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1537 FEAT_OPA(HEADER_CPUDESC, cpudesc), 1716 FEAT_OPA(HEADER_CPUDESC, cpudesc),
1538 FEAT_OPA(HEADER_CPUID, cpuid), 1717 FEAT_OPA(HEADER_CPUID, cpuid),
1539 FEAT_OPA(HEADER_TOTAL_MEM, total_mem), 1718 FEAT_OPA(HEADER_TOTAL_MEM, total_mem),
1540 FEAT_OPA(HEADER_EVENT_DESC, event_desc), 1719 FEAT_OPP(HEADER_EVENT_DESC, event_desc),
1541 FEAT_OPA(HEADER_CMDLINE, cmdline), 1720 FEAT_OPA(HEADER_CMDLINE, cmdline),
1542 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology), 1721 FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
1543 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology), 1722 FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
1544 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack), 1723 FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
1724 FEAT_OPA(HEADER_PMU_MAPPINGS, pmu_mappings),
1545}; 1725};
1546 1726
1547struct header_print_data { 1727struct header_print_data {
@@ -1831,7 +2011,6 @@ static const int attr_file_abi_sizes[] = {
1831 [1] = PERF_ATTR_SIZE_VER1, 2011 [1] = PERF_ATTR_SIZE_VER1,
1832 [2] = PERF_ATTR_SIZE_VER2, 2012 [2] = PERF_ATTR_SIZE_VER2,
1833 [3] = PERF_ATTR_SIZE_VER3, 2013 [3] = PERF_ATTR_SIZE_VER3,
1834 [4] = PERF_ATTR_SIZE_VER4,
1835 0, 2014 0,
1836}; 2015};
1837 2016
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 24962e707e5b..9d5eedceda72 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -28,6 +28,7 @@ enum {
28 HEADER_CPU_TOPOLOGY, 28 HEADER_CPU_TOPOLOGY,
29 HEADER_NUMA_TOPOLOGY, 29 HEADER_NUMA_TOPOLOGY,
30 HEADER_BRANCH_STACK, 30 HEADER_BRANCH_STACK,
31 HEADER_PMU_MAPPINGS,
31 HEADER_LAST_FEATURE, 32 HEADER_LAST_FEATURE,
32 HEADER_FEAT_BITS = 256, 33 HEADER_FEAT_BITS = 256,
33}; 34};
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c
index bf055ce1916e..bc8b65130ae0 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -301,12 +301,13 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
301{ 301{
302 struct perf_evsel *evsel = perf_evlist__first(evlist); 302 struct perf_evsel *evsel = perf_evlist__first(evlist);
303 303
304
304 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); 305 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
305 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 306 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
306 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 307 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
307 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 308 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
308 TEST_ASSERT_VAL("wrong name", 309 TEST_ASSERT_VAL("wrong name",
309 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u")); 310 !strcmp(perf_evsel__name(evsel), "mem:0:u"));
310 311
311 return test__checkevent_breakpoint(evlist); 312 return test__checkevent_breakpoint(evlist);
312} 313}
@@ -320,7 +321,7 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
320 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 321 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
321 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 322 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
322 TEST_ASSERT_VAL("wrong name", 323 TEST_ASSERT_VAL("wrong name",
323 !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k")); 324 !strcmp(perf_evsel__name(evsel), "mem:0:x:k"));
324 325
325 return test__checkevent_breakpoint_x(evlist); 326 return test__checkevent_breakpoint_x(evlist);
326} 327}
@@ -334,7 +335,7 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
334 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); 335 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
335 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 336 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
336 TEST_ASSERT_VAL("wrong name", 337 TEST_ASSERT_VAL("wrong name",
337 !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp")); 338 !strcmp(perf_evsel__name(evsel), "mem:0:r:hp"));
338 339
339 return test__checkevent_breakpoint_r(evlist); 340 return test__checkevent_breakpoint_r(evlist);
340} 341}
@@ -348,7 +349,7 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
348 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 349 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
349 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 350 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
350 TEST_ASSERT_VAL("wrong name", 351 TEST_ASSERT_VAL("wrong name",
351 !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up")); 352 !strcmp(perf_evsel__name(evsel), "mem:0:w:up"));
352 353
353 return test__checkevent_breakpoint_w(evlist); 354 return test__checkevent_breakpoint_w(evlist);
354} 355}
@@ -362,7 +363,7 @@ static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
362 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 363 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
363 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); 364 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
364 TEST_ASSERT_VAL("wrong name", 365 TEST_ASSERT_VAL("wrong name",
365 !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp")); 366 !strcmp(perf_evsel__name(evsel), "mem:0:rw:kp"));
366 367
367 return test__checkevent_breakpoint_rw(evlist); 368 return test__checkevent_breakpoint_rw(evlist);
368} 369}
@@ -437,7 +438,7 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
437 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); 438 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
438 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config); 439 TEST_ASSERT_VAL("wrong config", 2 == evsel->attr.config);
439 TEST_ASSERT_VAL("wrong name", 440 TEST_ASSERT_VAL("wrong name",
440 !strcmp(perf_evsel__name(evsel), "raw 0x2:u")); 441 !strcmp(perf_evsel__name(evsel), "cpu/config=2/u"));
441 442
442 return 0; 443 return 0;
443} 444}
@@ -948,19 +949,19 @@ static int test_event(struct test__event_st *e)
948 949
949static int test_events(struct test__event_st *events, unsigned cnt) 950static int test_events(struct test__event_st *events, unsigned cnt)
950{ 951{
951 int ret = 0; 952 int ret1, ret2 = 0;
952 unsigned i; 953 unsigned i;
953 954
954 for (i = 0; i < cnt; i++) { 955 for (i = 0; i < cnt; i++) {
955 struct test__event_st *e = &events[i]; 956 struct test__event_st *e = &events[i];
956 957
957 pr_debug("running test %d '%s'\n", i, e->name); 958 pr_debug("running test %d '%s'\n", i, e->name);
958 ret = test_event(e); 959 ret1 = test_event(e);
959 if (ret) 960 if (ret1)
960 break; 961 ret2 = ret1;
961 } 962 }
962 963
963 return ret; 964 return ret2;
964} 965}
965 966
966static int test_term(struct test__term *t) 967static int test_term(struct test__term *t)
@@ -1021,13 +1022,13 @@ static int test_pmu(void)
1021 1022
1022int parse_events__test(void) 1023int parse_events__test(void)
1023{ 1024{
1024 int ret; 1025 int ret1, ret2 = 0;
1025 1026
1026#define TEST_EVENTS(tests) \ 1027#define TEST_EVENTS(tests) \
1027do { \ 1028do { \
1028 ret = test_events(tests, ARRAY_SIZE(tests)); \ 1029 ret1 = test_events(tests, ARRAY_SIZE(tests)); \
1029 if (ret) \ 1030 if (!ret2) \
1030 return ret; \ 1031 ret2 = ret1; \
1031} while (0) 1032} while (0)
1032 1033
1033 TEST_EVENTS(test__events); 1034 TEST_EVENTS(test__events);
@@ -1035,5 +1036,9 @@ do { \
1035 if (test_pmu()) 1036 if (test_pmu())
1036 TEST_EVENTS(test__events_pmu); 1037 TEST_EVENTS(test__events_pmu);
1037 1038
1038 return test_terms(test__terms, ARRAY_SIZE(test__terms)); 1039 ret1 = test_terms(test__terms, ARRAY_SIZE(test__terms));
1040 if (!ret2)
1041 ret2 = ret1;
1042
1043 return ret2;
1039} 1044}
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 925784a930a8..b24630398b92 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -751,6 +751,18 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
751 return 0; 751 return 0;
752} 752}
753 753
754int parse_events_name(struct list_head *list, char *name)
755{
756 struct perf_evsel *evsel;
757
758 list_for_each_entry(evsel, list, node) {
759 if (!evsel->name)
760 evsel->name = strdup(name);
761 }
762
763 return 0;
764}
765
754static int parse_events__scanner(const char *str, void *data, int start_token) 766static int parse_events__scanner(const char *str, void *data, int start_token)
755{ 767{
756 YY_BUFFER_STATE buffer; 768 YY_BUFFER_STATE buffer;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 0b9782dc3da2..c356e443448d 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -81,6 +81,7 @@ int parse_events__term_clone(struct parse_events__term **new,
81void parse_events__free_terms(struct list_head *terms); 81void parse_events__free_terms(struct list_head *terms);
82int parse_events__modifier_event(struct list_head *list, char *str, bool add); 82int parse_events__modifier_event(struct list_head *list, char *str, bool add);
83int parse_events__modifier_group(struct list_head *list, char *event_mod); 83int parse_events__modifier_group(struct list_head *list, char *event_mod);
84int parse_events_name(struct list_head *list, char *name);
84int parse_events_add_tracepoint(struct list_head **list, int *idx, 85int parse_events_add_tracepoint(struct list_head **list, int *idx,
85 char *sys, char *event); 86 char *sys, char *event);
86int parse_events_add_numeric(struct list_head **list, int *idx, 87int parse_events_add_numeric(struct list_head **list, int *idx,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 2c0d006d43db..f5e28dc68270 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -70,6 +70,12 @@ static int term(yyscan_t scanner, int type)
70%} 70%}
71 71
72%x mem 72%x mem
73%s config
74%x event
75
76group [^,{}/]*[{][^}]*[}][^,{}/]*
77event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
78event [^,{}/]+
73 79
74num_dec [0-9]+ 80num_dec [0-9]+
75num_hex 0x[a-fA-F0-9]+ 81num_hex 0x[a-fA-F0-9]+
@@ -84,7 +90,13 @@ modifier_bp [rwx]{1,3}
84 { 90 {
85 int start_token; 91 int start_token;
86 92
87 start_token = (int) parse_events_get_extra(yyscanner); 93 start_token = parse_events_get_extra(yyscanner);
94
95 if (start_token == PE_START_TERMS)
96 BEGIN(config);
97 else if (start_token == PE_START_EVENTS)
98 BEGIN(event);
99
88 if (start_token) { 100 if (start_token) {
89 parse_events_set_extra(NULL, yyscanner); 101 parse_events_set_extra(NULL, yyscanner);
90 return start_token; 102 return start_token;
@@ -92,6 +104,26 @@ modifier_bp [rwx]{1,3}
92 } 104 }
93%} 105%}
94 106
107<event>{
108
109{group} {
110 BEGIN(INITIAL); yyless(0);
111 }
112
113{event_pmu} |
114{event} {
115 str(yyscanner, PE_EVENT_NAME);
116 BEGIN(INITIAL); yyless(0);
117 return PE_EVENT_NAME;
118 }
119
120. |
121<<EOF>> {
122 BEGIN(INITIAL); yyless(0);
123 }
124
125}
126
95cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 127cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
96stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 128stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
97stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 129stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
@@ -127,18 +159,16 @@ speculative-read|speculative-load |
127refs|Reference|ops|access | 159refs|Reference|ops|access |
128misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); } 160misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
129 161
130 /* 162<config>{
131 * These are event config hardcoded term names to be specified
132 * within xxx/.../ syntax. So far we dont clash with other names,
133 * so we can put them here directly. In case the we have a conflict
134 * in future, this needs to go into '//' condition block.
135 */
136config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } 163config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
137config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); } 164config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
138config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } 165config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
139name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } 166name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
140period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } 167period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
141branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 168branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
169, { return ','; }
170"/" { BEGIN(INITIAL); return '/'; }
171}
142 172
143mem: { BEGIN(mem); return PE_PREFIX_MEM; } 173mem: { BEGIN(mem); return PE_PREFIX_MEM; }
144r{num_raw_hex} { return raw(yyscanner); } 174r{num_raw_hex} { return raw(yyscanner); }
@@ -147,11 +177,11 @@ r{num_raw_hex} { return raw(yyscanner); }
147 177
148{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 178{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
149{name} { return str(yyscanner, PE_NAME); } 179{name} { return str(yyscanner, PE_NAME); }
150"/" { return '/'; } 180"/" { BEGIN(config); return '/'; }
151- { return '-'; } 181- { return '-'; }
152, { return ','; } 182, { BEGIN(event); return ','; }
153: { return ':'; } 183: { return ':'; }
154"{" { return '{'; } 184"{" { BEGIN(event); return '{'; }
155"}" { return '}'; } 185"}" { return '}'; }
156= { return '='; } 186= { return '='; }
157\n { } 187\n { }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 66850f820df9..42d9a17b83b1 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -27,6 +27,7 @@ do { \
27 27
28%token PE_START_EVENTS PE_START_TERMS 28%token PE_START_EVENTS PE_START_TERMS
29%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 29%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
30%token PE_EVENT_NAME
30%token PE_NAME 31%token PE_NAME
31%token PE_MODIFIER_EVENT PE_MODIFIER_BP 32%token PE_MODIFIER_EVENT PE_MODIFIER_BP
32%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 33%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
@@ -42,6 +43,7 @@ do { \
42%type <str> PE_NAME_CACHE_OP_RESULT 43%type <str> PE_NAME_CACHE_OP_RESULT
43%type <str> PE_MODIFIER_EVENT 44%type <str> PE_MODIFIER_EVENT
44%type <str> PE_MODIFIER_BP 45%type <str> PE_MODIFIER_BP
46%type <str> PE_EVENT_NAME
45%type <num> value_sym 47%type <num> value_sym
46%type <head> event_config 48%type <head> event_config
47%type <term> event_term 49%type <term> event_term
@@ -53,6 +55,8 @@ do { \
53%type <head> event_legacy_numeric 55%type <head> event_legacy_numeric
54%type <head> event_legacy_raw 56%type <head> event_legacy_raw
55%type <head> event_def 57%type <head> event_def
58%type <head> event_mod
59%type <head> event_name
56%type <head> event 60%type <head> event
57%type <head> events 61%type <head> events
58%type <head> group_def 62%type <head> group_def
@@ -143,8 +147,10 @@ events ',' event
143| 147|
144event 148event
145 149
146event: 150event: event_mod
147event_def PE_MODIFIER_EVENT 151
152event_mod:
153event_name PE_MODIFIER_EVENT
148{ 154{
149 struct list_head *list = $1; 155 struct list_head *list = $1;
150 156
@@ -157,6 +163,16 @@ event_def PE_MODIFIER_EVENT
157 $$ = list; 163 $$ = list;
158} 164}
159| 165|
166event_name
167
168event_name:
169PE_EVENT_NAME event_def
170{
171 ABORT_ON(parse_events_name($2, $1));
172 free($1);
173 $$ = $2;
174}
175|
160event_def 176event_def
161 177
162event_def: event_pmu | 178event_def: event_pmu |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 67715a42cd6d..6631d828db3d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -10,6 +10,8 @@
10#include "pmu.h" 10#include "pmu.h"
11#include "parse-events.h" 11#include "parse-events.h"
12 12
13#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
14
13int perf_pmu_parse(struct list_head *list, char *name); 15int perf_pmu_parse(struct list_head *list, char *name);
14extern FILE *perf_pmu_in; 16extern FILE *perf_pmu_in;
15 17
@@ -69,7 +71,7 @@ static int pmu_format(char *name, struct list_head *format)
69 return -1; 71 return -1;
70 72
71 snprintf(path, PATH_MAX, 73 snprintf(path, PATH_MAX,
72 "%s/bus/event_source/devices/%s/format", sysfs, name); 74 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
73 75
74 if (stat(path, &st) < 0) 76 if (stat(path, &st) < 0)
75 return 0; /* no error if format does not exist */ 77 return 0; /* no error if format does not exist */
@@ -206,7 +208,7 @@ static int pmu_type(char *name, __u32 *type)
206 return -1; 208 return -1;
207 209
208 snprintf(path, PATH_MAX, 210 snprintf(path, PATH_MAX,
209 "%s/bus/event_source/devices/%s/type", sysfs, name); 211 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
210 212
211 if (stat(path, &st) < 0) 213 if (stat(path, &st) < 0)
212 return -1; 214 return -1;
@@ -222,6 +224,35 @@ static int pmu_type(char *name, __u32 *type)
222 return ret; 224 return ret;
223} 225}
224 226
227/* Add all pmus in sysfs to pmu list: */
228static void pmu_read_sysfs(void)
229{
230 char path[PATH_MAX];
231 const char *sysfs;
232 DIR *dir;
233 struct dirent *dent;
234
235 sysfs = sysfs_find_mountpoint();
236 if (!sysfs)
237 return;
238
239 snprintf(path, PATH_MAX,
240 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
241
242 dir = opendir(path);
243 if (!dir)
244 return;
245
246 while ((dent = readdir(dir))) {
247 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
248 continue;
249 /* add to static LIST_HEAD(pmus): */
250 perf_pmu__find(dent->d_name);
251 }
252
253 closedir(dir);
254}
255
225static struct perf_pmu *pmu_lookup(char *name) 256static struct perf_pmu *pmu_lookup(char *name)
226{ 257{
227 struct perf_pmu *pmu; 258 struct perf_pmu *pmu;
@@ -267,6 +298,21 @@ static struct perf_pmu *pmu_find(char *name)
267 return NULL; 298 return NULL;
268} 299}
269 300
301struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
302{
303 /*
304 * pmu iterator: If pmu is NULL, we start at the begin,
305 * otherwise return the next pmu. Returns NULL on end.
306 */
307 if (!pmu) {
308 pmu_read_sysfs();
309 pmu = list_prepare_entry(pmu, &pmus, list);
310 }
311 list_for_each_entry_continue(pmu, &pmus, list)
312 return pmu;
313 return NULL;
314}
315
270struct perf_pmu *perf_pmu__find(char *name) 316struct perf_pmu *perf_pmu__find(char *name)
271{ 317{
272 struct perf_pmu *pmu; 318 struct perf_pmu *pmu;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 535f2c5258ab..47f68d3cc5d1 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -46,5 +46,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
46 int config, unsigned long *bits); 46 int config, unsigned long *bits);
47void perf_pmu__set_format(unsigned long *bits, long from, long to); 47void perf_pmu__set_format(unsigned long *bits, long from, long to);
48 48
49struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
50
49int perf_pmu__test(void); 51int perf_pmu__test(void);
50#endif /* __PMU_H */ 52#endif /* __PMU_H */