diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-07-06 04:17:40 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-07-06 04:22:46 -0400 |
commit | 387ef4e24af4ae43a7961ba6eec749488da99535 (patch) | |
tree | bdd6995a544bce7401562afbd70ffd27e2b5a083 /tools | |
parent | 6a67943a18c264d5f3df436da38edb3e59adc905 (diff) | |
parent | 81e9b994bb20716d1f6c47e048e4ae4a43de2f83 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
perf/core improvements and fixes:
- Preparatory patches to use hw events in PMU syntax, from Jiri Olsa
- Remaining backport of trace-cmd's libparseevent, from Namhyung Kim
- Fix libtraceevent 'clean' make target, from Namhyung Kim
- Teach ctags about libtraceevent error codes, from Namhyung Kim
- Fix libtraceevent dependency files usage, from Namhyung Kim
- Support hex number pretty printing in libtraceevent, fixing
kvm output, from Namhyung Kim
- Kill some die() usage in libtraceevent, from Namhyung Kim
- Improve support for hw breakpoints parsing/pretty printing/testing,
from Jiri Olsa
- Clarify perf bench option naming, from Hitoshi Mitake
- Look for ".note" ELF notes too, used in the kernel vdso, from Jiri Olsa
- Fix internal PMU list usage, removing leak, from Robert Richter
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/lib/traceevent/Makefile | 14 | ||||
-rw-r--r-- | tools/lib/traceevent/event-parse.c | 399 | ||||
-rw-r--r-- | tools/lib/traceevent/event-parse.h | 7 | ||||
-rw-r--r-- | tools/lib/traceevent/parse-filter.c | 86 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-bench.txt | 4 | ||||
-rw-r--r-- | tools/perf/bench/mem-memcpy.c | 80 | ||||
-rw-r--r-- | tools/perf/bench/mem-memset.c | 80 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 30 | ||||
-rw-r--r-- | tools/perf/util/include/linux/kernel.h | 10 | ||||
-rw-r--r-- | tools/perf/util/parse-events-test.c | 76 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 194 | ||||
-rw-r--r-- | tools/perf/util/parse-events.l | 5 | ||||
-rw-r--r-- | tools/perf/util/parse-events.y | 15 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 3 | ||||
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-perl.c | 4 | ||||
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 4 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 29 |
17 files changed, 726 insertions, 314 deletions
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 3d69aa9ff51e..46c2f6b7b123 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile | |||
@@ -250,8 +250,12 @@ endef | |||
250 | all_objs := $(sort $(ALL_OBJS)) | 250 | all_objs := $(sort $(ALL_OBJS)) |
251 | all_deps := $(all_objs:%.o=.%.d) | 251 | all_deps := $(all_objs:%.o=.%.d) |
252 | 252 | ||
253 | # let .d file also depends on the source and header files | ||
253 | define check_deps | 254 | define check_deps |
254 | $(CC) -M $(CFLAGS) $< > $@; | 255 | @set -e; $(RM) $@; \ |
256 | $(CC) -M $(CFLAGS) $< > $@.$$$$; \ | ||
257 | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ | ||
258 | $(RM) $@.$$$$ | ||
255 | endef | 259 | endef |
256 | 260 | ||
257 | $(gui_deps): ks_version.h | 261 | $(gui_deps): ks_version.h |
@@ -270,11 +274,13 @@ endif | |||
270 | 274 | ||
271 | tags: force | 275 | tags: force |
272 | $(RM) tags | 276 | $(RM) tags |
273 | find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px | 277 | find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ |
278 | --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' | ||
274 | 279 | ||
275 | TAGS: force | 280 | TAGS: force |
276 | $(RM) TAGS | 281 | $(RM) TAGS |
277 | find . -name '*.[ch]' | xargs etags | 282 | find . -name '*.[ch]' | xargs etags \ |
283 | --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' | ||
278 | 284 | ||
279 | define do_install | 285 | define do_install |
280 | $(print_install) \ | 286 | $(print_install) \ |
@@ -290,7 +296,7 @@ install_lib: all_cmd install_plugins install_python | |||
290 | install: install_lib | 296 | install: install_lib |
291 | 297 | ||
292 | clean: | 298 | clean: |
293 | $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES).*.d | 299 | $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d |
294 | $(RM) tags TAGS | 300 | $(RM) tags TAGS |
295 | 301 | ||
296 | endif # skip-makefile | 302 | endif # skip-makefile |
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 554828219c33..5f34aa371b56 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -467,8 +467,10 @@ int pevent_register_function(struct pevent *pevent, char *func, | |||
467 | item->mod = NULL; | 467 | item->mod = NULL; |
468 | item->addr = addr; | 468 | item->addr = addr; |
469 | 469 | ||
470 | pevent->funclist = item; | 470 | if (!item->func || (mod && !item->mod)) |
471 | die("malloc func"); | ||
471 | 472 | ||
473 | pevent->funclist = item; | ||
472 | pevent->func_count++; | 474 | pevent->func_count++; |
473 | 475 | ||
474 | return 0; | 476 | return 0; |
@@ -511,12 +513,12 @@ struct printk_list { | |||
511 | 513 | ||
512 | static int printk_cmp(const void *a, const void *b) | 514 | static int printk_cmp(const void *a, const void *b) |
513 | { | 515 | { |
514 | const struct func_map *fa = a; | 516 | const struct printk_map *pa = a; |
515 | const struct func_map *fb = b; | 517 | const struct printk_map *pb = b; |
516 | 518 | ||
517 | if (fa->addr < fb->addr) | 519 | if (pa->addr < pb->addr) |
518 | return -1; | 520 | return -1; |
519 | if (fa->addr > fb->addr) | 521 | if (pa->addr > pb->addr) |
520 | return 1; | 522 | return 1; |
521 | 523 | ||
522 | return 0; | 524 | return 0; |
@@ -583,10 +585,13 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt, | |||
583 | item = malloc_or_die(sizeof(*item)); | 585 | item = malloc_or_die(sizeof(*item)); |
584 | 586 | ||
585 | item->next = pevent->printklist; | 587 | item->next = pevent->printklist; |
586 | pevent->printklist = item; | ||
587 | item->printk = strdup(fmt); | 588 | item->printk = strdup(fmt); |
588 | item->addr = addr; | 589 | item->addr = addr; |
589 | 590 | ||
591 | if (!item->printk) | ||
592 | die("malloc fmt"); | ||
593 | |||
594 | pevent->printklist = item; | ||
590 | pevent->printk_count++; | 595 | pevent->printk_count++; |
591 | 596 | ||
592 | return 0; | 597 | return 0; |
@@ -616,7 +621,9 @@ static struct event_format *alloc_event(void) | |||
616 | { | 621 | { |
617 | struct event_format *event; | 622 | struct event_format *event; |
618 | 623 | ||
619 | event = malloc_or_die(sizeof(*event)); | 624 | event = malloc(sizeof(*event)); |
625 | if (!event) | ||
626 | return NULL; | ||
620 | memset(event, 0, sizeof(*event)); | 627 | memset(event, 0, sizeof(*event)); |
621 | 628 | ||
622 | return event; | 629 | return event; |
@@ -626,12 +633,8 @@ static void add_event(struct pevent *pevent, struct event_format *event) | |||
626 | { | 633 | { |
627 | int i; | 634 | int i; |
628 | 635 | ||
629 | if (!pevent->events) | 636 | pevent->events = realloc(pevent->events, sizeof(event) * |
630 | pevent->events = malloc_or_die(sizeof(event)); | 637 | (pevent->nr_events + 1)); |
631 | else | ||
632 | pevent->events = | ||
633 | realloc(pevent->events, sizeof(event) * | ||
634 | (pevent->nr_events + 1)); | ||
635 | if (!pevent->events) | 638 | if (!pevent->events) |
636 | die("Can not allocate events"); | 639 | die("Can not allocate events"); |
637 | 640 | ||
@@ -697,6 +700,10 @@ static void free_arg(struct print_arg *arg) | |||
697 | free_arg(arg->symbol.field); | 700 | free_arg(arg->symbol.field); |
698 | free_flag_sym(arg->symbol.symbols); | 701 | free_flag_sym(arg->symbol.symbols); |
699 | break; | 702 | break; |
703 | case PRINT_HEX: | ||
704 | free_arg(arg->hex.field); | ||
705 | free_arg(arg->hex.size); | ||
706 | break; | ||
700 | case PRINT_TYPE: | 707 | case PRINT_TYPE: |
701 | free(arg->typecast.type); | 708 | free(arg->typecast.type); |
702 | free_arg(arg->typecast.item); | 709 | free_arg(arg->typecast.item); |
@@ -775,6 +782,25 @@ int pevent_peek_char(void) | |||
775 | return __peek_char(); | 782 | return __peek_char(); |
776 | } | 783 | } |
777 | 784 | ||
785 | static int extend_token(char **tok, char *buf, int size) | ||
786 | { | ||
787 | char *newtok = realloc(*tok, size); | ||
788 | |||
789 | if (!newtok) { | ||
790 | free(*tok); | ||
791 | *tok = NULL; | ||
792 | return -1; | ||
793 | } | ||
794 | |||
795 | if (!*tok) | ||
796 | strcpy(newtok, buf); | ||
797 | else | ||
798 | strcat(newtok, buf); | ||
799 | *tok = newtok; | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | |||
778 | static enum event_type force_token(const char *str, char **tok); | 804 | static enum event_type force_token(const char *str, char **tok); |
779 | 805 | ||
780 | static enum event_type __read_token(char **tok) | 806 | static enum event_type __read_token(char **tok) |
@@ -859,17 +885,10 @@ static enum event_type __read_token(char **tok) | |||
859 | do { | 885 | do { |
860 | if (i == (BUFSIZ - 1)) { | 886 | if (i == (BUFSIZ - 1)) { |
861 | buf[i] = 0; | 887 | buf[i] = 0; |
862 | if (*tok) { | 888 | tok_size += BUFSIZ; |
863 | *tok = realloc(*tok, tok_size + BUFSIZ); | ||
864 | if (!*tok) | ||
865 | return EVENT_NONE; | ||
866 | strcat(*tok, buf); | ||
867 | } else | ||
868 | *tok = strdup(buf); | ||
869 | 889 | ||
870 | if (!*tok) | 890 | if (extend_token(tok, buf, tok_size) < 0) |
871 | return EVENT_NONE; | 891 | return EVENT_NONE; |
872 | tok_size += BUFSIZ; | ||
873 | i = 0; | 892 | i = 0; |
874 | } | 893 | } |
875 | last_ch = ch; | 894 | last_ch = ch; |
@@ -908,17 +927,10 @@ static enum event_type __read_token(char **tok) | |||
908 | while (get_type(__peek_char()) == type) { | 927 | while (get_type(__peek_char()) == type) { |
909 | if (i == (BUFSIZ - 1)) { | 928 | if (i == (BUFSIZ - 1)) { |
910 | buf[i] = 0; | 929 | buf[i] = 0; |
911 | if (*tok) { | 930 | tok_size += BUFSIZ; |
912 | *tok = realloc(*tok, tok_size + BUFSIZ); | ||
913 | if (!*tok) | ||
914 | return EVENT_NONE; | ||
915 | strcat(*tok, buf); | ||
916 | } else | ||
917 | *tok = strdup(buf); | ||
918 | 931 | ||
919 | if (!*tok) | 932 | if (extend_token(tok, buf, tok_size) < 0) |
920 | return EVENT_NONE; | 933 | return EVENT_NONE; |
921 | tok_size += BUFSIZ; | ||
922 | i = 0; | 934 | i = 0; |
923 | } | 935 | } |
924 | ch = __read_char(); | 936 | ch = __read_char(); |
@@ -927,14 +939,7 @@ static enum event_type __read_token(char **tok) | |||
927 | 939 | ||
928 | out: | 940 | out: |
929 | buf[i] = 0; | 941 | buf[i] = 0; |
930 | if (*tok) { | 942 | if (extend_token(tok, buf, tok_size + i + 1) < 0) |
931 | *tok = realloc(*tok, tok_size + i); | ||
932 | if (!*tok) | ||
933 | return EVENT_NONE; | ||
934 | strcat(*tok, buf); | ||
935 | } else | ||
936 | *tok = strdup(buf); | ||
937 | if (!*tok) | ||
938 | return EVENT_NONE; | 943 | return EVENT_NONE; |
939 | 944 | ||
940 | if (type == EVENT_ITEM) { | 945 | if (type == EVENT_ITEM) { |
@@ -1255,9 +1260,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1255 | field->flags |= FIELD_IS_POINTER; | 1260 | field->flags |= FIELD_IS_POINTER; |
1256 | 1261 | ||
1257 | if (field->type) { | 1262 | if (field->type) { |
1258 | field->type = realloc(field->type, | 1263 | char *new_type; |
1259 | strlen(field->type) + | 1264 | new_type = realloc(field->type, |
1260 | strlen(last_token) + 2); | 1265 | strlen(field->type) + |
1266 | strlen(last_token) + 2); | ||
1267 | if (!new_type) { | ||
1268 | free(last_token); | ||
1269 | goto fail; | ||
1270 | } | ||
1271 | field->type = new_type; | ||
1261 | strcat(field->type, " "); | 1272 | strcat(field->type, " "); |
1262 | strcat(field->type, last_token); | 1273 | strcat(field->type, last_token); |
1263 | free(last_token); | 1274 | free(last_token); |
@@ -1282,6 +1293,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1282 | if (strcmp(token, "[") == 0) { | 1293 | if (strcmp(token, "[") == 0) { |
1283 | enum event_type last_type = type; | 1294 | enum event_type last_type = type; |
1284 | char *brackets = token; | 1295 | char *brackets = token; |
1296 | char *new_brackets; | ||
1285 | int len; | 1297 | int len; |
1286 | 1298 | ||
1287 | field->flags |= FIELD_IS_ARRAY; | 1299 | field->flags |= FIELD_IS_ARRAY; |
@@ -1301,9 +1313,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1301 | len = 1; | 1313 | len = 1; |
1302 | last_type = type; | 1314 | last_type = type; |
1303 | 1315 | ||
1304 | brackets = realloc(brackets, | 1316 | new_brackets = realloc(brackets, |
1305 | strlen(brackets) + | 1317 | strlen(brackets) + |
1306 | strlen(token) + len); | 1318 | strlen(token) + len); |
1319 | if (!new_brackets) { | ||
1320 | free(brackets); | ||
1321 | goto fail; | ||
1322 | } | ||
1323 | brackets = new_brackets; | ||
1307 | if (len == 2) | 1324 | if (len == 2) |
1308 | strcat(brackets, " "); | 1325 | strcat(brackets, " "); |
1309 | strcat(brackets, token); | 1326 | strcat(brackets, token); |
@@ -1319,7 +1336,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1319 | 1336 | ||
1320 | free_token(token); | 1337 | free_token(token); |
1321 | 1338 | ||
1322 | brackets = realloc(brackets, strlen(brackets) + 2); | 1339 | new_brackets = realloc(brackets, strlen(brackets) + 2); |
1340 | if (!new_brackets) { | ||
1341 | free(brackets); | ||
1342 | goto fail; | ||
1343 | } | ||
1344 | brackets = new_brackets; | ||
1323 | strcat(brackets, "]"); | 1345 | strcat(brackets, "]"); |
1324 | 1346 | ||
1325 | /* add brackets to type */ | 1347 | /* add brackets to type */ |
@@ -1330,10 +1352,16 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1330 | * the format: type [] item; | 1352 | * the format: type [] item; |
1331 | */ | 1353 | */ |
1332 | if (type == EVENT_ITEM) { | 1354 | if (type == EVENT_ITEM) { |
1333 | field->type = realloc(field->type, | 1355 | char *new_type; |
1334 | strlen(field->type) + | 1356 | new_type = realloc(field->type, |
1335 | strlen(field->name) + | 1357 | strlen(field->type) + |
1336 | strlen(brackets) + 2); | 1358 | strlen(field->name) + |
1359 | strlen(brackets) + 2); | ||
1360 | if (!new_type) { | ||
1361 | free(brackets); | ||
1362 | goto fail; | ||
1363 | } | ||
1364 | field->type = new_type; | ||
1337 | strcat(field->type, " "); | 1365 | strcat(field->type, " "); |
1338 | strcat(field->type, field->name); | 1366 | strcat(field->type, field->name); |
1339 | free_token(field->name); | 1367 | free_token(field->name); |
@@ -1341,9 +1369,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f | |||
1341 | field->name = token; | 1369 | field->name = token; |
1342 | type = read_token(&token); | 1370 | type = read_token(&token); |
1343 | } else { | 1371 | } else { |
1344 | field->type = realloc(field->type, | 1372 | char *new_type; |
1345 | strlen(field->type) + | 1373 | new_type = realloc(field->type, |
1346 | strlen(brackets) + 1); | 1374 | strlen(field->type) + |
1375 | strlen(brackets) + 1); | ||
1376 | if (!new_type) { | ||
1377 | free(brackets); | ||
1378 | goto fail; | ||
1379 | } | ||
1380 | field->type = new_type; | ||
1347 | strcat(field->type, brackets); | 1381 | strcat(field->type, brackets); |
1348 | } | 1382 | } |
1349 | free(brackets); | 1383 | free(brackets); |
@@ -1726,10 +1760,16 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) | |||
1726 | /* could just be a type pointer */ | 1760 | /* could just be a type pointer */ |
1727 | if ((strcmp(arg->op.op, "*") == 0) && | 1761 | if ((strcmp(arg->op.op, "*") == 0) && |
1728 | type == EVENT_DELIM && (strcmp(token, ")") == 0)) { | 1762 | type == EVENT_DELIM && (strcmp(token, ")") == 0)) { |
1763 | char *new_atom; | ||
1764 | |||
1729 | if (left->type != PRINT_ATOM) | 1765 | if (left->type != PRINT_ATOM) |
1730 | die("bad pointer type"); | 1766 | die("bad pointer type"); |
1731 | left->atom.atom = realloc(left->atom.atom, | 1767 | new_atom = realloc(left->atom.atom, |
1732 | strlen(left->atom.atom) + 3); | 1768 | strlen(left->atom.atom) + 3); |
1769 | if (!new_atom) | ||
1770 | goto out_free; | ||
1771 | |||
1772 | left->atom.atom = new_atom; | ||
1733 | strcat(left->atom.atom, " *"); | 1773 | strcat(left->atom.atom, " *"); |
1734 | free(arg->op.op); | 1774 | free(arg->op.op); |
1735 | *arg = *left; | 1775 | *arg = *left; |
@@ -2146,6 +2186,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** | |||
2146 | if (value == NULL) | 2186 | if (value == NULL) |
2147 | goto out_free; | 2187 | goto out_free; |
2148 | field->value = strdup(value); | 2188 | field->value = strdup(value); |
2189 | if (field->value == NULL) | ||
2190 | goto out_free; | ||
2149 | 2191 | ||
2150 | free_arg(arg); | 2192 | free_arg(arg); |
2151 | arg = alloc_arg(); | 2193 | arg = alloc_arg(); |
@@ -2159,6 +2201,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** | |||
2159 | if (value == NULL) | 2201 | if (value == NULL) |
2160 | goto out_free; | 2202 | goto out_free; |
2161 | field->str = strdup(value); | 2203 | field->str = strdup(value); |
2204 | if (field->str == NULL) | ||
2205 | goto out_free; | ||
2162 | free_arg(arg); | 2206 | free_arg(arg); |
2163 | arg = NULL; | 2207 | arg = NULL; |
2164 | 2208 | ||
@@ -2260,6 +2304,45 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok) | |||
2260 | } | 2304 | } |
2261 | 2305 | ||
2262 | static enum event_type | 2306 | static enum event_type |
2307 | process_hex(struct event_format *event, struct print_arg *arg, char **tok) | ||
2308 | { | ||
2309 | struct print_arg *field; | ||
2310 | enum event_type type; | ||
2311 | char *token; | ||
2312 | |||
2313 | memset(arg, 0, sizeof(*arg)); | ||
2314 | arg->type = PRINT_HEX; | ||
2315 | |||
2316 | field = alloc_arg(); | ||
2317 | type = process_arg(event, field, &token); | ||
2318 | |||
2319 | if (test_type_token(type, token, EVENT_DELIM, ",")) | ||
2320 | goto out_free; | ||
2321 | |||
2322 | arg->hex.field = field; | ||
2323 | |||
2324 | free_token(token); | ||
2325 | |||
2326 | field = alloc_arg(); | ||
2327 | type = process_arg(event, field, &token); | ||
2328 | |||
2329 | if (test_type_token(type, token, EVENT_DELIM, ")")) | ||
2330 | goto out_free; | ||
2331 | |||
2332 | arg->hex.size = field; | ||
2333 | |||
2334 | free_token(token); | ||
2335 | type = read_token_item(tok); | ||
2336 | return type; | ||
2337 | |||
2338 | out_free: | ||
2339 | free_arg(field); | ||
2340 | free_token(token); | ||
2341 | *tok = NULL; | ||
2342 | return EVENT_ERROR; | ||
2343 | } | ||
2344 | |||
2345 | static enum event_type | ||
2263 | process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok) | 2346 | process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok) |
2264 | { | 2347 | { |
2265 | struct format_field *field; | 2348 | struct format_field *field; |
@@ -2488,6 +2571,10 @@ process_function(struct event_format *event, struct print_arg *arg, | |||
2488 | is_symbolic_field = 1; | 2571 | is_symbolic_field = 1; |
2489 | return process_symbols(event, arg, tok); | 2572 | return process_symbols(event, arg, tok); |
2490 | } | 2573 | } |
2574 | if (strcmp(token, "__print_hex") == 0) { | ||
2575 | free_token(token); | ||
2576 | return process_hex(event, arg, tok); | ||
2577 | } | ||
2491 | if (strcmp(token, "__get_str") == 0) { | 2578 | if (strcmp(token, "__get_str") == 0) { |
2492 | free_token(token); | 2579 | free_token(token); |
2493 | return process_str(event, arg, tok); | 2580 | return process_str(event, arg, tok); |
@@ -2541,7 +2628,16 @@ process_arg_token(struct event_format *event, struct print_arg *arg, | |||
2541 | } | 2628 | } |
2542 | /* atoms can be more than one token long */ | 2629 | /* atoms can be more than one token long */ |
2543 | while (type == EVENT_ITEM) { | 2630 | while (type == EVENT_ITEM) { |
2544 | atom = realloc(atom, strlen(atom) + strlen(token) + 2); | 2631 | char *new_atom; |
2632 | new_atom = realloc(atom, | ||
2633 | strlen(atom) + strlen(token) + 2); | ||
2634 | if (!new_atom) { | ||
2635 | free(atom); | ||
2636 | *tok = NULL; | ||
2637 | free_token(token); | ||
2638 | return EVENT_ERROR; | ||
2639 | } | ||
2640 | atom = new_atom; | ||
2545 | strcat(atom, " "); | 2641 | strcat(atom, " "); |
2546 | strcat(atom, token); | 2642 | strcat(atom, token); |
2547 | free_token(token); | 2643 | free_token(token); |
@@ -2835,7 +2931,7 @@ static int get_common_info(struct pevent *pevent, | |||
2835 | event = pevent->events[0]; | 2931 | event = pevent->events[0]; |
2836 | field = pevent_find_common_field(event, type); | 2932 | field = pevent_find_common_field(event, type); |
2837 | if (!field) | 2933 | if (!field) |
2838 | die("field '%s' not found", type); | 2934 | return -1; |
2839 | 2935 | ||
2840 | *offset = field->offset; | 2936 | *offset = field->offset; |
2841 | *size = field->size; | 2937 | *size = field->size; |
@@ -2886,15 +2982,16 @@ static int parse_common_flags(struct pevent *pevent, void *data) | |||
2886 | 2982 | ||
2887 | static int parse_common_lock_depth(struct pevent *pevent, void *data) | 2983 | static int parse_common_lock_depth(struct pevent *pevent, void *data) |
2888 | { | 2984 | { |
2889 | int ret; | 2985 | return __parse_common(pevent, data, |
2890 | 2986 | &pevent->ld_size, &pevent->ld_offset, | |
2891 | ret = __parse_common(pevent, data, | 2987 | "common_lock_depth"); |
2892 | &pevent->ld_size, &pevent->ld_offset, | 2988 | } |
2893 | "common_lock_depth"); | ||
2894 | if (ret < 0) | ||
2895 | return -1; | ||
2896 | 2989 | ||
2897 | return ret; | 2990 | static int parse_common_migrate_disable(struct pevent *pevent, void *data) |
2991 | { | ||
2992 | return __parse_common(pevent, data, | ||
2993 | &pevent->ld_size, &pevent->ld_offset, | ||
2994 | "common_migrate_disable"); | ||
2898 | } | 2995 | } |
2899 | 2996 | ||
2900 | static int events_id_cmp(const void *a, const void *b); | 2997 | static int events_id_cmp(const void *a, const void *b); |
@@ -2995,6 +3092,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg | |||
2995 | break; | 3092 | break; |
2996 | case PRINT_FLAGS: | 3093 | case PRINT_FLAGS: |
2997 | case PRINT_SYMBOL: | 3094 | case PRINT_SYMBOL: |
3095 | case PRINT_HEX: | ||
2998 | break; | 3096 | break; |
2999 | case PRINT_TYPE: | 3097 | case PRINT_TYPE: |
3000 | val = eval_num_arg(data, size, event, arg->typecast.item); | 3098 | val = eval_num_arg(data, size, event, arg->typecast.item); |
@@ -3214,11 +3312,13 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3214 | { | 3312 | { |
3215 | struct pevent *pevent = event->pevent; | 3313 | struct pevent *pevent = event->pevent; |
3216 | struct print_flag_sym *flag; | 3314 | struct print_flag_sym *flag; |
3315 | struct format_field *field; | ||
3217 | unsigned long long val, fval; | 3316 | unsigned long long val, fval; |
3218 | unsigned long addr; | 3317 | unsigned long addr; |
3219 | char *str; | 3318 | char *str; |
3319 | unsigned char *hex; | ||
3220 | int print; | 3320 | int print; |
3221 | int len; | 3321 | int i, len; |
3222 | 3322 | ||
3223 | switch (arg->type) { | 3323 | switch (arg->type) { |
3224 | case PRINT_NULL: | 3324 | case PRINT_NULL: |
@@ -3228,27 +3328,29 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3228 | print_str_to_seq(s, format, len_arg, arg->atom.atom); | 3328 | print_str_to_seq(s, format, len_arg, arg->atom.atom); |
3229 | return; | 3329 | return; |
3230 | case PRINT_FIELD: | 3330 | case PRINT_FIELD: |
3231 | if (!arg->field.field) { | 3331 | field = arg->field.field; |
3232 | arg->field.field = pevent_find_any_field(event, arg->field.name); | 3332 | if (!field) { |
3233 | if (!arg->field.field) | 3333 | field = pevent_find_any_field(event, arg->field.name); |
3334 | if (!field) | ||
3234 | die("field %s not found", arg->field.name); | 3335 | die("field %s not found", arg->field.name); |
3336 | arg->field.field = field; | ||
3235 | } | 3337 | } |
3236 | /* Zero sized fields, mean the rest of the data */ | 3338 | /* Zero sized fields, mean the rest of the data */ |
3237 | len = arg->field.field->size ? : size - arg->field.field->offset; | 3339 | len = field->size ? : size - field->offset; |
3238 | 3340 | ||
3239 | /* | 3341 | /* |
3240 | * Some events pass in pointers. If this is not an array | 3342 | * Some events pass in pointers. If this is not an array |
3241 | * and the size is the same as long_size, assume that it | 3343 | * and the size is the same as long_size, assume that it |
3242 | * is a pointer. | 3344 | * is a pointer. |
3243 | */ | 3345 | */ |
3244 | if (!(arg->field.field->flags & FIELD_IS_ARRAY) && | 3346 | if (!(field->flags & FIELD_IS_ARRAY) && |
3245 | arg->field.field->size == pevent->long_size) { | 3347 | field->size == pevent->long_size) { |
3246 | addr = *(unsigned long *)(data + arg->field.field->offset); | 3348 | addr = *(unsigned long *)(data + field->offset); |
3247 | trace_seq_printf(s, "%lx", addr); | 3349 | trace_seq_printf(s, "%lx", addr); |
3248 | break; | 3350 | break; |
3249 | } | 3351 | } |
3250 | str = malloc_or_die(len + 1); | 3352 | str = malloc_or_die(len + 1); |
3251 | memcpy(str, data + arg->field.field->offset, len); | 3353 | memcpy(str, data + field->offset, len); |
3252 | str[len] = 0; | 3354 | str[len] = 0; |
3253 | print_str_to_seq(s, format, len_arg, str); | 3355 | print_str_to_seq(s, format, len_arg, str); |
3254 | free(str); | 3356 | free(str); |
@@ -3281,6 +3383,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3281 | } | 3383 | } |
3282 | } | 3384 | } |
3283 | break; | 3385 | break; |
3386 | case PRINT_HEX: | ||
3387 | field = arg->hex.field->field.field; | ||
3388 | if (!field) { | ||
3389 | str = arg->hex.field->field.name; | ||
3390 | field = pevent_find_any_field(event, str); | ||
3391 | if (!field) | ||
3392 | die("field %s not found", str); | ||
3393 | arg->hex.field->field.field = field; | ||
3394 | } | ||
3395 | hex = data + field->offset; | ||
3396 | len = eval_num_arg(data, size, event, arg->hex.size); | ||
3397 | for (i = 0; i < len; i++) { | ||
3398 | if (i) | ||
3399 | trace_seq_putc(s, ' '); | ||
3400 | trace_seq_printf(s, "%02x", hex[i]); | ||
3401 | } | ||
3402 | break; | ||
3284 | 3403 | ||
3285 | case PRINT_TYPE: | 3404 | case PRINT_TYPE: |
3286 | break; | 3405 | break; |
@@ -3299,7 +3418,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3299 | break; | 3418 | break; |
3300 | } | 3419 | } |
3301 | case PRINT_BSTRING: | 3420 | case PRINT_BSTRING: |
3302 | trace_seq_printf(s, format, arg->string.string); | 3421 | print_str_to_seq(s, format, len_arg, arg->string.string); |
3303 | break; | 3422 | break; |
3304 | case PRINT_OP: | 3423 | case PRINT_OP: |
3305 | /* | 3424 | /* |
@@ -3363,6 +3482,10 @@ process_defined_func(struct trace_seq *s, void *data, int size, | |||
3363 | string = malloc_or_die(sizeof(*string)); | 3482 | string = malloc_or_die(sizeof(*string)); |
3364 | string->next = strings; | 3483 | string->next = strings; |
3365 | string->str = strdup(str.buffer); | 3484 | string->str = strdup(str.buffer); |
3485 | if (!string->str) | ||
3486 | die("malloc str"); | ||
3487 | |||
3488 | args[i] = (unsigned long long)string->str; | ||
3366 | strings = string; | 3489 | strings = string; |
3367 | trace_seq_destroy(&str); | 3490 | trace_seq_destroy(&str); |
3368 | break; | 3491 | break; |
@@ -3400,6 +3523,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc | |||
3400 | unsigned long long ip, val; | 3523 | unsigned long long ip, val; |
3401 | char *ptr; | 3524 | char *ptr; |
3402 | void *bptr; | 3525 | void *bptr; |
3526 | int vsize; | ||
3403 | 3527 | ||
3404 | field = pevent->bprint_buf_field; | 3528 | field = pevent->bprint_buf_field; |
3405 | ip_field = pevent->bprint_ip_field; | 3529 | ip_field = pevent->bprint_ip_field; |
@@ -3448,6 +3572,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc | |||
3448 | goto process_again; | 3572 | goto process_again; |
3449 | case '0' ... '9': | 3573 | case '0' ... '9': |
3450 | goto process_again; | 3574 | goto process_again; |
3575 | case '.': | ||
3576 | goto process_again; | ||
3451 | case 'p': | 3577 | case 'p': |
3452 | ls = 1; | 3578 | ls = 1; |
3453 | /* fall through */ | 3579 | /* fall through */ |
@@ -3455,23 +3581,30 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc | |||
3455 | case 'u': | 3581 | case 'u': |
3456 | case 'x': | 3582 | case 'x': |
3457 | case 'i': | 3583 | case 'i': |
3458 | /* the pointers are always 4 bytes aligned */ | ||
3459 | bptr = (void *)(((unsigned long)bptr + 3) & | ||
3460 | ~3); | ||
3461 | switch (ls) { | 3584 | switch (ls) { |
3462 | case 0: | 3585 | case 0: |
3463 | ls = 4; | 3586 | vsize = 4; |
3464 | break; | 3587 | break; |
3465 | case 1: | 3588 | case 1: |
3466 | ls = pevent->long_size; | 3589 | vsize = pevent->long_size; |
3467 | break; | 3590 | break; |
3468 | case 2: | 3591 | case 2: |
3469 | ls = 8; | 3592 | vsize = 8; |
3593 | break; | ||
3470 | default: | 3594 | default: |
3595 | vsize = ls; /* ? */ | ||
3471 | break; | 3596 | break; |
3472 | } | 3597 | } |
3473 | val = pevent_read_number(pevent, bptr, ls); | 3598 | /* fall through */ |
3474 | bptr += ls; | 3599 | case '*': |
3600 | if (*ptr == '*') | ||
3601 | vsize = 4; | ||
3602 | |||
3603 | /* the pointers are always 4 bytes aligned */ | ||
3604 | bptr = (void *)(((unsigned long)bptr + 3) & | ||
3605 | ~3); | ||
3606 | val = pevent_read_number(pevent, bptr, vsize); | ||
3607 | bptr += vsize; | ||
3475 | arg = alloc_arg(); | 3608 | arg = alloc_arg(); |
3476 | arg->next = NULL; | 3609 | arg->next = NULL; |
3477 | arg->type = PRINT_ATOM; | 3610 | arg->type = PRINT_ATOM; |
@@ -3479,12 +3612,21 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc | |||
3479 | sprintf(arg->atom.atom, "%lld", val); | 3612 | sprintf(arg->atom.atom, "%lld", val); |
3480 | *next = arg; | 3613 | *next = arg; |
3481 | next = &arg->next; | 3614 | next = &arg->next; |
3615 | /* | ||
3616 | * The '*' case means that an arg is used as the length. | ||
3617 | * We need to continue to figure out for what. | ||
3618 | */ | ||
3619 | if (*ptr == '*') | ||
3620 | goto process_again; | ||
3621 | |||
3482 | break; | 3622 | break; |
3483 | case 's': | 3623 | case 's': |
3484 | arg = alloc_arg(); | 3624 | arg = alloc_arg(); |
3485 | arg->next = NULL; | 3625 | arg->next = NULL; |
3486 | arg->type = PRINT_BSTRING; | 3626 | arg->type = PRINT_BSTRING; |
3487 | arg->string.string = strdup(bptr); | 3627 | arg->string.string = strdup(bptr); |
3628 | if (!arg->string.string) | ||
3629 | break; | ||
3488 | bptr += strlen(bptr) + 1; | 3630 | bptr += strlen(bptr) + 1; |
3489 | *next = arg; | 3631 | *next = arg; |
3490 | next = &arg->next; | 3632 | next = &arg->next; |
@@ -3589,6 +3731,16 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, | |||
3589 | trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); | 3731 | trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); |
3590 | } | 3732 | } |
3591 | 3733 | ||
3734 | static int is_printable_array(char *p, unsigned int len) | ||
3735 | { | ||
3736 | unsigned int i; | ||
3737 | |||
3738 | for (i = 0; i < len && p[i]; i++) | ||
3739 | if (!isprint(p[i])) | ||
3740 | return 0; | ||
3741 | return 1; | ||
3742 | } | ||
3743 | |||
3592 | static void print_event_fields(struct trace_seq *s, void *data, int size, | 3744 | static void print_event_fields(struct trace_seq *s, void *data, int size, |
3593 | struct event_format *event) | 3745 | struct event_format *event) |
3594 | { | 3746 | { |
@@ -3608,7 +3760,8 @@ static void print_event_fields(struct trace_seq *s, void *data, int size, | |||
3608 | len = offset >> 16; | 3760 | len = offset >> 16; |
3609 | offset &= 0xffff; | 3761 | offset &= 0xffff; |
3610 | } | 3762 | } |
3611 | if (field->flags & FIELD_IS_STRING) { | 3763 | if (field->flags & FIELD_IS_STRING && |
3764 | is_printable_array(data + offset, len)) { | ||
3612 | trace_seq_printf(s, "%s", (char *)data + offset); | 3765 | trace_seq_printf(s, "%s", (char *)data + offset); |
3613 | } else { | 3766 | } else { |
3614 | trace_seq_puts(s, "ARRAY["); | 3767 | trace_seq_puts(s, "ARRAY["); |
@@ -3619,6 +3772,7 @@ static void print_event_fields(struct trace_seq *s, void *data, int size, | |||
3619 | *((unsigned char *)data + offset + i)); | 3772 | *((unsigned char *)data + offset + i)); |
3620 | } | 3773 | } |
3621 | trace_seq_putc(s, ']'); | 3774 | trace_seq_putc(s, ']'); |
3775 | field->flags &= ~FIELD_IS_STRING; | ||
3622 | } | 3776 | } |
3623 | } else { | 3777 | } else { |
3624 | val = pevent_read_number(event->pevent, data + field->offset, | 3778 | val = pevent_read_number(event->pevent, data + field->offset, |
@@ -3758,6 +3912,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
3758 | } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') { | 3912 | } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') { |
3759 | print_mac_arg(s, *(ptr+1), data, size, event, arg); | 3913 | print_mac_arg(s, *(ptr+1), data, size, event, arg); |
3760 | ptr++; | 3914 | ptr++; |
3915 | arg = arg->next; | ||
3761 | break; | 3916 | break; |
3762 | } | 3917 | } |
3763 | 3918 | ||
@@ -3794,14 +3949,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
3794 | break; | 3949 | break; |
3795 | } | 3950 | } |
3796 | } | 3951 | } |
3797 | if (pevent->long_size == 8 && ls) { | 3952 | if (pevent->long_size == 8 && ls && |
3953 | sizeof(long) != 8) { | ||
3798 | char *p; | 3954 | char *p; |
3799 | 3955 | ||
3800 | ls = 2; | 3956 | ls = 2; |
3801 | /* make %l into %ll */ | 3957 | /* make %l into %ll */ |
3802 | p = strchr(format, 'l'); | 3958 | p = strchr(format, 'l'); |
3803 | if (p) | 3959 | if (p) |
3804 | memmove(p, p+1, strlen(p)+1); | 3960 | memmove(p+1, p, strlen(p)+1); |
3805 | else if (strcmp(format, "%p") == 0) | 3961 | else if (strcmp(format, "%p") == 0) |
3806 | strcpy(format, "0x%llx"); | 3962 | strcpy(format, "0x%llx"); |
3807 | } | 3963 | } |
@@ -3878,8 +4034,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
3878 | * pevent_data_lat_fmt - parse the data for the latency format | 4034 | * pevent_data_lat_fmt - parse the data for the latency format |
3879 | * @pevent: a handle to the pevent | 4035 | * @pevent: a handle to the pevent |
3880 | * @s: the trace_seq to write to | 4036 | * @s: the trace_seq to write to |
3881 | * @data: the raw data to read from | 4037 | * @record: the record to read from |
3882 | * @size: currently unused. | ||
3883 | * | 4038 | * |
3884 | * This parses out the Latency format (interrupts disabled, | 4039 | * This parses out the Latency format (interrupts disabled, |
3885 | * need rescheduling, in hard/soft interrupt, preempt count | 4040 | * need rescheduling, in hard/soft interrupt, preempt count |
@@ -3889,10 +4044,13 @@ void pevent_data_lat_fmt(struct pevent *pevent, | |||
3889 | struct trace_seq *s, struct pevent_record *record) | 4044 | struct trace_seq *s, struct pevent_record *record) |
3890 | { | 4045 | { |
3891 | static int check_lock_depth = 1; | 4046 | static int check_lock_depth = 1; |
4047 | static int check_migrate_disable = 1; | ||
3892 | static int lock_depth_exists; | 4048 | static int lock_depth_exists; |
4049 | static int migrate_disable_exists; | ||
3893 | unsigned int lat_flags; | 4050 | unsigned int lat_flags; |
3894 | unsigned int pc; | 4051 | unsigned int pc; |
3895 | int lock_depth; | 4052 | int lock_depth; |
4053 | int migrate_disable; | ||
3896 | int hardirq; | 4054 | int hardirq; |
3897 | int softirq; | 4055 | int softirq; |
3898 | void *data = record->data; | 4056 | void *data = record->data; |
@@ -3900,18 +4058,26 @@ void pevent_data_lat_fmt(struct pevent *pevent, | |||
3900 | lat_flags = parse_common_flags(pevent, data); | 4058 | lat_flags = parse_common_flags(pevent, data); |
3901 | pc = parse_common_pc(pevent, data); | 4059 | pc = parse_common_pc(pevent, data); |
3902 | /* lock_depth may not always exist */ | 4060 | /* lock_depth may not always exist */ |
3903 | if (check_lock_depth) { | ||
3904 | struct format_field *field; | ||
3905 | struct event_format *event; | ||
3906 | |||
3907 | check_lock_depth = 0; | ||
3908 | event = pevent->events[0]; | ||
3909 | field = pevent_find_common_field(event, "common_lock_depth"); | ||
3910 | if (field) | ||
3911 | lock_depth_exists = 1; | ||
3912 | } | ||
3913 | if (lock_depth_exists) | 4061 | if (lock_depth_exists) |
3914 | lock_depth = parse_common_lock_depth(pevent, data); | 4062 | lock_depth = parse_common_lock_depth(pevent, data); |
4063 | else if (check_lock_depth) { | ||
4064 | lock_depth = parse_common_lock_depth(pevent, data); | ||
4065 | if (lock_depth < 0) | ||
4066 | check_lock_depth = 0; | ||
4067 | else | ||
4068 | lock_depth_exists = 1; | ||
4069 | } | ||
4070 | |||
4071 | /* migrate_disable may not always exist */ | ||
4072 | if (migrate_disable_exists) | ||
4073 | migrate_disable = parse_common_migrate_disable(pevent, data); | ||
4074 | else if (check_migrate_disable) { | ||
4075 | migrate_disable = parse_common_migrate_disable(pevent, data); | ||
4076 | if (migrate_disable < 0) | ||
4077 | check_migrate_disable = 0; | ||
4078 | else | ||
4079 | migrate_disable_exists = 1; | ||
4080 | } | ||
3915 | 4081 | ||
3916 | hardirq = lat_flags & TRACE_FLAG_HARDIRQ; | 4082 | hardirq = lat_flags & TRACE_FLAG_HARDIRQ; |
3917 | softirq = lat_flags & TRACE_FLAG_SOFTIRQ; | 4083 | softirq = lat_flags & TRACE_FLAG_SOFTIRQ; |
@@ -3930,6 +4096,13 @@ void pevent_data_lat_fmt(struct pevent *pevent, | |||
3930 | else | 4096 | else |
3931 | trace_seq_putc(s, '.'); | 4097 | trace_seq_putc(s, '.'); |
3932 | 4098 | ||
4099 | if (migrate_disable_exists) { | ||
4100 | if (migrate_disable < 0) | ||
4101 | trace_seq_putc(s, '.'); | ||
4102 | else | ||
4103 | trace_seq_printf(s, "%d", migrate_disable); | ||
4104 | } | ||
4105 | |||
3933 | if (lock_depth_exists) { | 4106 | if (lock_depth_exists) { |
3934 | if (lock_depth < 0) | 4107 | if (lock_depth < 0) |
3935 | trace_seq_putc(s, '.'); | 4108 | trace_seq_putc(s, '.'); |
@@ -3996,10 +4169,7 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid) | |||
3996 | * pevent_data_comm_from_pid - parse the data into the print format | 4169 | * pevent_data_comm_from_pid - parse the data into the print format |
3997 | * @s: the trace_seq to write to | 4170 | * @s: the trace_seq to write to |
3998 | * @event: the handle to the event | 4171 | * @event: the handle to the event |
3999 | * @cpu: the cpu the event was recorded on | 4172 | * @record: the record to read from |
4000 | * @data: the raw data | ||
4001 | * @size: the size of the raw data | ||
4002 | * @nsecs: the timestamp of the event | ||
4003 | * | 4173 | * |
4004 | * This parses the raw @data using the given @event information and | 4174 | * This parses the raw @data using the given @event information and |
4005 | * writes the print format into the trace_seq. | 4175 | * writes the print format into the trace_seq. |
@@ -4279,6 +4449,13 @@ static void print_args(struct print_arg *args) | |||
4279 | trace_seq_destroy(&s); | 4449 | trace_seq_destroy(&s); |
4280 | printf(")"); | 4450 | printf(")"); |
4281 | break; | 4451 | break; |
4452 | case PRINT_HEX: | ||
4453 | printf("__print_hex("); | ||
4454 | print_args(args->hex.field); | ||
4455 | printf(", "); | ||
4456 | print_args(args->hex.size); | ||
4457 | printf(")"); | ||
4458 | break; | ||
4282 | case PRINT_STRING: | 4459 | case PRINT_STRING: |
4283 | case PRINT_BSTRING: | 4460 | case PRINT_BSTRING: |
4284 | printf("__get_str(%s)", args->string.string); | 4461 | printf("__get_str(%s)", args->string.string); |
@@ -4541,6 +4718,8 @@ int pevent_parse_event(struct pevent *pevent, | |||
4541 | die("failed to read event id"); | 4718 | die("failed to read event id"); |
4542 | 4719 | ||
4543 | event->system = strdup(sys); | 4720 | event->system = strdup(sys); |
4721 | if (!event->system) | ||
4722 | die("failed to allocate system"); | ||
4544 | 4723 | ||
4545 | /* Add pevent to event so that it can be referenced */ | 4724 | /* Add pevent to event so that it can be referenced */ |
4546 | event->pevent = pevent; | 4725 | event->pevent = pevent; |
@@ -4582,6 +4761,11 @@ int pevent_parse_event(struct pevent *pevent, | |||
4582 | list = &arg->next; | 4761 | list = &arg->next; |
4583 | arg->type = PRINT_FIELD; | 4762 | arg->type = PRINT_FIELD; |
4584 | arg->field.name = strdup(field->name); | 4763 | arg->field.name = strdup(field->name); |
4764 | if (!arg->field.name) { | ||
4765 | do_warning("failed to allocate field name"); | ||
4766 | event->flags |= EVENT_FL_FAILED; | ||
4767 | return -1; | ||
4768 | } | ||
4585 | arg->field.field = field; | 4769 | arg->field.field = field; |
4586 | } | 4770 | } |
4587 | return 0; | 4771 | return 0; |
@@ -4753,7 +4937,7 @@ int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event, | |||
4753 | * @record: The record with the field name. | 4937 | * @record: The record with the field name. |
4754 | * @err: print default error if failed. | 4938 | * @err: print default error if failed. |
4755 | * | 4939 | * |
4756 | * Returns: 0 on success, -1 field not fould, or 1 if buffer is full. | 4940 | * Returns: 0 on success, -1 field not found, or 1 if buffer is full. |
4757 | */ | 4941 | */ |
4758 | int pevent_print_num_field(struct trace_seq *s, const char *fmt, | 4942 | int pevent_print_num_field(struct trace_seq *s, const char *fmt, |
4759 | struct event_format *event, const char *name, | 4943 | struct event_format *event, const char *name, |
@@ -4795,11 +4979,12 @@ static void free_func_handle(struct pevent_function_handler *func) | |||
4795 | * pevent_register_print_function - register a helper function | 4979 | * pevent_register_print_function - register a helper function |
4796 | * @pevent: the handle to the pevent | 4980 | * @pevent: the handle to the pevent |
4797 | * @func: the function to process the helper function | 4981 | * @func: the function to process the helper function |
4982 | * @ret_type: the return type of the helper function | ||
4798 | * @name: the name of the helper function | 4983 | * @name: the name of the helper function |
4799 | * @parameters: A list of enum pevent_func_arg_type | 4984 | * @parameters: A list of enum pevent_func_arg_type |
4800 | * | 4985 | * |
4801 | * Some events may have helper functions in the print format arguments. | 4986 | * Some events may have helper functions in the print format arguments. |
4802 | * This allows a plugin to dynmically create a way to process one | 4987 | * This allows a plugin to dynamically create a way to process one |
4803 | * of these functions. | 4988 | * of these functions. |
4804 | * | 4989 | * |
4805 | * The @parameters is a variable list of pevent_func_arg_type enums that | 4990 | * The @parameters is a variable list of pevent_func_arg_type enums that |
@@ -4870,12 +5055,13 @@ int pevent_register_print_function(struct pevent *pevent, | |||
4870 | } | 5055 | } |
4871 | 5056 | ||
4872 | /** | 5057 | /** |
4873 | * pevent_register_event_handle - register a way to parse an event | 5058 | * pevent_register_event_handler - register a way to parse an event |
4874 | * @pevent: the handle to the pevent | 5059 | * @pevent: the handle to the pevent |
4875 | * @id: the id of the event to register | 5060 | * @id: the id of the event to register |
4876 | * @sys_name: the system name the event belongs to | 5061 | * @sys_name: the system name the event belongs to |
4877 | * @event_name: the name of the event | 5062 | * @event_name: the name of the event |
4878 | * @func: the function to call to parse the event information | 5063 | * @func: the function to call to parse the event information |
5064 | * @context: the data to be passed to @func | ||
4879 | * | 5065 | * |
4880 | * This function allows a developer to override the parsing of | 5066 | * This function allows a developer to override the parsing of |
4881 | * a given event. If for some reason the default print format | 5067 | * a given event. If for some reason the default print format |
@@ -4925,6 +5111,11 @@ int pevent_register_event_handler(struct pevent *pevent, | |||
4925 | if (sys_name) | 5111 | if (sys_name) |
4926 | handle->sys_name = strdup(sys_name); | 5112 | handle->sys_name = strdup(sys_name); |
4927 | 5113 | ||
5114 | if ((event_name && !handle->event_name) || | ||
5115 | (sys_name && !handle->sys_name)) { | ||
5116 | die("Failed to allocate event/sys name"); | ||
5117 | } | ||
5118 | |||
4928 | handle->func = func; | 5119 | handle->func = func; |
4929 | handle->next = pevent->handlers; | 5120 | handle->next = pevent->handlers; |
4930 | pevent->handlers = handle; | 5121 | pevent->handlers = handle; |
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index ac997bc7b592..5772ad8cb386 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h | |||
@@ -226,6 +226,11 @@ struct print_arg_symbol { | |||
226 | struct print_flag_sym *symbols; | 226 | struct print_flag_sym *symbols; |
227 | }; | 227 | }; |
228 | 228 | ||
229 | struct print_arg_hex { | ||
230 | struct print_arg *field; | ||
231 | struct print_arg *size; | ||
232 | }; | ||
233 | |||
229 | struct print_arg_dynarray { | 234 | struct print_arg_dynarray { |
230 | struct format_field *field; | 235 | struct format_field *field; |
231 | struct print_arg *index; | 236 | struct print_arg *index; |
@@ -253,6 +258,7 @@ enum print_arg_type { | |||
253 | PRINT_FIELD, | 258 | PRINT_FIELD, |
254 | PRINT_FLAGS, | 259 | PRINT_FLAGS, |
255 | PRINT_SYMBOL, | 260 | PRINT_SYMBOL, |
261 | PRINT_HEX, | ||
256 | PRINT_TYPE, | 262 | PRINT_TYPE, |
257 | PRINT_STRING, | 263 | PRINT_STRING, |
258 | PRINT_BSTRING, | 264 | PRINT_BSTRING, |
@@ -270,6 +276,7 @@ struct print_arg { | |||
270 | struct print_arg_typecast typecast; | 276 | struct print_arg_typecast typecast; |
271 | struct print_arg_flags flags; | 277 | struct print_arg_flags flags; |
272 | struct print_arg_symbol symbol; | 278 | struct print_arg_symbol symbol; |
279 | struct print_arg_hex hex; | ||
273 | struct print_arg_func func; | 280 | struct print_arg_func func; |
274 | struct print_arg_string string; | 281 | struct print_arg_string string; |
275 | struct print_arg_op op; | 282 | struct print_arg_op op; |
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index dfcfe2c131de..ad17855528f9 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c | |||
@@ -96,7 +96,7 @@ static enum event_type read_token(char **tok) | |||
96 | (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && | 96 | (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && |
97 | pevent_peek_char() == '~') { | 97 | pevent_peek_char() == '~') { |
98 | /* append it */ | 98 | /* append it */ |
99 | *tok = malloc(3); | 99 | *tok = malloc_or_die(3); |
100 | sprintf(*tok, "%c%c", *token, '~'); | 100 | sprintf(*tok, "%c%c", *token, '~'); |
101 | free_token(token); | 101 | free_token(token); |
102 | /* Now remove the '~' from the buffer */ | 102 | /* Now remove the '~' from the buffer */ |
@@ -148,17 +148,11 @@ add_filter_type(struct event_filter *filter, int id) | |||
148 | if (filter_type) | 148 | if (filter_type) |
149 | return filter_type; | 149 | return filter_type; |
150 | 150 | ||
151 | if (!filter->filters) | 151 | filter->event_filters = realloc(filter->event_filters, |
152 | filter->event_filters = | 152 | sizeof(*filter->event_filters) * |
153 | malloc_or_die(sizeof(*filter->event_filters)); | 153 | (filter->filters + 1)); |
154 | else { | 154 | if (!filter->event_filters) |
155 | filter->event_filters = | 155 | die("Could not allocate filter"); |
156 | realloc(filter->event_filters, | ||
157 | sizeof(*filter->event_filters) * | ||
158 | (filter->filters + 1)); | ||
159 | if (!filter->event_filters) | ||
160 | die("Could not allocate filter"); | ||
161 | } | ||
162 | 156 | ||
163 | for (i = 0; i < filter->filters; i++) { | 157 | for (i = 0; i < filter->filters; i++) { |
164 | if (filter->event_filters[i].event_id > id) | 158 | if (filter->event_filters[i].event_id > id) |
@@ -1480,7 +1474,7 @@ void pevent_filter_clear_trivial(struct event_filter *filter, | |||
1480 | { | 1474 | { |
1481 | struct filter_type *filter_type; | 1475 | struct filter_type *filter_type; |
1482 | int count = 0; | 1476 | int count = 0; |
1483 | int *ids; | 1477 | int *ids = NULL; |
1484 | int i; | 1478 | int i; |
1485 | 1479 | ||
1486 | if (!filter->filters) | 1480 | if (!filter->filters) |
@@ -1504,10 +1498,8 @@ void pevent_filter_clear_trivial(struct event_filter *filter, | |||
1504 | default: | 1498 | default: |
1505 | break; | 1499 | break; |
1506 | } | 1500 | } |
1507 | if (count) | 1501 | |
1508 | ids = realloc(ids, sizeof(*ids) * (count + 1)); | 1502 | ids = realloc(ids, sizeof(*ids) * (count + 1)); |
1509 | else | ||
1510 | ids = malloc(sizeof(*ids)); | ||
1511 | if (!ids) | 1503 | if (!ids) |
1512 | die("Can't allocate ids"); | 1504 | die("Can't allocate ids"); |
1513 | ids[count++] = filter_type->event_id; | 1505 | ids[count++] = filter_type->event_id; |
@@ -1710,18 +1702,43 @@ static int test_num(struct event_format *event, | |||
1710 | 1702 | ||
1711 | static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record) | 1703 | static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record) |
1712 | { | 1704 | { |
1713 | const char *val = record->data + arg->str.field->offset; | 1705 | struct event_format *event; |
1706 | struct pevent *pevent; | ||
1707 | unsigned long long addr; | ||
1708 | const char *val = NULL; | ||
1709 | char hex[64]; | ||
1714 | 1710 | ||
1715 | /* | 1711 | /* If the field is not a string convert it */ |
1716 | * We need to copy the data since we can't be sure the field | 1712 | if (arg->str.field->flags & FIELD_IS_STRING) { |
1717 | * is null terminated. | 1713 | val = record->data + arg->str.field->offset; |
1718 | */ | 1714 | |
1719 | if (*(val + arg->str.field->size - 1)) { | 1715 | /* |
1720 | /* copy it */ | 1716 | * We need to copy the data since we can't be sure the field |
1721 | memcpy(arg->str.buffer, val, arg->str.field->size); | 1717 | * is null terminated. |
1722 | /* the buffer is already NULL terminated */ | 1718 | */ |
1723 | val = arg->str.buffer; | 1719 | if (*(val + arg->str.field->size - 1)) { |
1720 | /* copy it */ | ||
1721 | memcpy(arg->str.buffer, val, arg->str.field->size); | ||
1722 | /* the buffer is already NULL terminated */ | ||
1723 | val = arg->str.buffer; | ||
1724 | } | ||
1725 | |||
1726 | } else { | ||
1727 | event = arg->str.field->event; | ||
1728 | pevent = event->pevent; | ||
1729 | addr = get_value(event, arg->str.field, record); | ||
1730 | |||
1731 | if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG)) | ||
1732 | /* convert to a kernel symbol */ | ||
1733 | val = pevent_find_function(pevent, addr); | ||
1734 | |||
1735 | if (val == NULL) { | ||
1736 | /* just use the hex of the string name */ | ||
1737 | snprintf(hex, 64, "0x%llx", addr); | ||
1738 | val = hex; | ||
1739 | } | ||
1724 | } | 1740 | } |
1741 | |||
1725 | return val; | 1742 | return val; |
1726 | } | 1743 | } |
1727 | 1744 | ||
@@ -2001,11 +2018,13 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2001 | char *lstr; | 2018 | char *lstr; |
2002 | char *rstr; | 2019 | char *rstr; |
2003 | char *op; | 2020 | char *op; |
2004 | char *str; | 2021 | char *str = NULL; |
2005 | int len; | 2022 | int len; |
2006 | 2023 | ||
2007 | lstr = arg_to_str(filter, arg->exp.left); | 2024 | lstr = arg_to_str(filter, arg->exp.left); |
2008 | rstr = arg_to_str(filter, arg->exp.right); | 2025 | rstr = arg_to_str(filter, arg->exp.right); |
2026 | if (!lstr || !rstr) | ||
2027 | goto out; | ||
2009 | 2028 | ||
2010 | switch (arg->exp.type) { | 2029 | switch (arg->exp.type) { |
2011 | case FILTER_EXP_ADD: | 2030 | case FILTER_EXP_ADD: |
@@ -2045,6 +2064,7 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2045 | len = strlen(op) + strlen(lstr) + strlen(rstr) + 4; | 2064 | len = strlen(op) + strlen(lstr) + strlen(rstr) + 4; |
2046 | str = malloc_or_die(len); | 2065 | str = malloc_or_die(len); |
2047 | snprintf(str, len, "%s %s %s", lstr, op, rstr); | 2066 | snprintf(str, len, "%s %s %s", lstr, op, rstr); |
2067 | out: | ||
2048 | free(lstr); | 2068 | free(lstr); |
2049 | free(rstr); | 2069 | free(rstr); |
2050 | 2070 | ||
@@ -2061,6 +2081,8 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2061 | 2081 | ||
2062 | lstr = arg_to_str(filter, arg->num.left); | 2082 | lstr = arg_to_str(filter, arg->num.left); |
2063 | rstr = arg_to_str(filter, arg->num.right); | 2083 | rstr = arg_to_str(filter, arg->num.right); |
2084 | if (!lstr || !rstr) | ||
2085 | goto out; | ||
2064 | 2086 | ||
2065 | switch (arg->num.type) { | 2087 | switch (arg->num.type) { |
2066 | case FILTER_CMP_EQ: | 2088 | case FILTER_CMP_EQ: |
@@ -2097,6 +2119,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) | |||
2097 | break; | 2119 | break; |
2098 | } | 2120 | } |
2099 | 2121 | ||
2122 | out: | ||
2100 | free(lstr); | 2123 | free(lstr); |
2101 | free(rstr); | 2124 | free(rstr); |
2102 | return str; | 2125 | return str; |
@@ -2247,7 +2270,12 @@ int pevent_filter_compare(struct event_filter *filter1, struct event_filter *fil | |||
2247 | /* The best way to compare complex filters is with strings */ | 2270 | /* The best way to compare complex filters is with strings */ |
2248 | str1 = arg_to_str(filter1, filter_type1->filter); | 2271 | str1 = arg_to_str(filter1, filter_type1->filter); |
2249 | str2 = arg_to_str(filter2, filter_type2->filter); | 2272 | str2 = arg_to_str(filter2, filter_type2->filter); |
2250 | result = strcmp(str1, str2) != 0; | 2273 | if (str1 && str2) |
2274 | result = strcmp(str1, str2) != 0; | ||
2275 | else | ||
2276 | /* bail out if allocation fails */ | ||
2277 | result = 1; | ||
2278 | |||
2251 | free(str1); | 2279 | free(str1); |
2252 | free(str2); | 2280 | free(str2); |
2253 | if (result) | 2281 | if (result) |
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt index f3c716a4cad3..7065cd6fbdfc 100644 --- a/tools/perf/Documentation/perf-bench.txt +++ b/tools/perf/Documentation/perf-bench.txt | |||
@@ -144,7 +144,7 @@ On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported. | |||
144 | Repeat memcpy invocation this number of times. | 144 | Repeat memcpy invocation this number of times. |
145 | 145 | ||
146 | -c:: | 146 | -c:: |
147 | --clock:: | 147 | --cycle:: |
148 | Use perf's cpu-cycles event instead of gettimeofday syscall. | 148 | Use perf's cpu-cycles event instead of gettimeofday syscall. |
149 | 149 | ||
150 | -o:: | 150 | -o:: |
@@ -176,7 +176,7 @@ On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported. | |||
176 | Repeat memset invocation this number of times. | 176 | Repeat memset invocation this number of times. |
177 | 177 | ||
178 | -c:: | 178 | -c:: |
179 | --clock:: | 179 | --cycle:: |
180 | Use perf's cpu-cycles event instead of gettimeofday syscall. | 180 | Use perf's cpu-cycles event instead of gettimeofday syscall. |
181 | 181 | ||
182 | -o:: | 182 | -o:: |
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index d990365cafa0..02dad5d3359b 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c | |||
@@ -24,8 +24,8 @@ | |||
24 | static const char *length_str = "1MB"; | 24 | static const char *length_str = "1MB"; |
25 | static const char *routine = "default"; | 25 | static const char *routine = "default"; |
26 | static int iterations = 1; | 26 | static int iterations = 1; |
27 | static bool use_clock; | 27 | static bool use_cycle; |
28 | static int clock_fd; | 28 | static int cycle_fd; |
29 | static bool only_prefault; | 29 | static bool only_prefault; |
30 | static bool no_prefault; | 30 | static bool no_prefault; |
31 | 31 | ||
@@ -37,7 +37,7 @@ static const struct option options[] = { | |||
37 | "Specify routine to copy"), | 37 | "Specify routine to copy"), |
38 | OPT_INTEGER('i', "iterations", &iterations, | 38 | OPT_INTEGER('i', "iterations", &iterations, |
39 | "repeat memcpy() invocation this number of times"), | 39 | "repeat memcpy() invocation this number of times"), |
40 | OPT_BOOLEAN('c', "clock", &use_clock, | 40 | OPT_BOOLEAN('c', "cycle", &use_cycle, |
41 | "Use cycles event instead of gettimeofday() for measuring"), | 41 | "Use cycles event instead of gettimeofday() for measuring"), |
42 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, | 42 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, |
43 | "Show only the result with page faults before memcpy()"), | 43 | "Show only the result with page faults before memcpy()"), |
@@ -76,27 +76,27 @@ static const char * const bench_mem_memcpy_usage[] = { | |||
76 | NULL | 76 | NULL |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct perf_event_attr clock_attr = { | 79 | static struct perf_event_attr cycle_attr = { |
80 | .type = PERF_TYPE_HARDWARE, | 80 | .type = PERF_TYPE_HARDWARE, |
81 | .config = PERF_COUNT_HW_CPU_CYCLES | 81 | .config = PERF_COUNT_HW_CPU_CYCLES |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static void init_clock(void) | 84 | static void init_cycle(void) |
85 | { | 85 | { |
86 | clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); | 86 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0); |
87 | 87 | ||
88 | if (clock_fd < 0 && errno == ENOSYS) | 88 | if (cycle_fd < 0 && errno == ENOSYS) |
89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | 89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); |
90 | else | 90 | else |
91 | BUG_ON(clock_fd < 0); | 91 | BUG_ON(cycle_fd < 0); |
92 | } | 92 | } |
93 | 93 | ||
94 | static u64 get_clock(void) | 94 | static u64 get_cycle(void) |
95 | { | 95 | { |
96 | int ret; | 96 | int ret; |
97 | u64 clk; | 97 | u64 clk; |
98 | 98 | ||
99 | ret = read(clock_fd, &clk, sizeof(u64)); | 99 | ret = read(cycle_fd, &clk, sizeof(u64)); |
100 | BUG_ON(ret != sizeof(u64)); | 100 | BUG_ON(ret != sizeof(u64)); |
101 | 101 | ||
102 | return clk; | 102 | return clk; |
@@ -119,9 +119,9 @@ static void alloc_mem(void **dst, void **src, size_t length) | |||
119 | die("memory allocation failed - maybe length is too large?\n"); | 119 | die("memory allocation failed - maybe length is too large?\n"); |
120 | } | 120 | } |
121 | 121 | ||
122 | static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault) | 122 | static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault) |
123 | { | 123 | { |
124 | u64 clock_start = 0ULL, clock_end = 0ULL; | 124 | u64 cycle_start = 0ULL, cycle_end = 0ULL; |
125 | void *src = NULL, *dst = NULL; | 125 | void *src = NULL, *dst = NULL; |
126 | int i; | 126 | int i; |
127 | 127 | ||
@@ -130,14 +130,14 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault) | |||
130 | if (prefault) | 130 | if (prefault) |
131 | fn(dst, src, len); | 131 | fn(dst, src, len); |
132 | 132 | ||
133 | clock_start = get_clock(); | 133 | cycle_start = get_cycle(); |
134 | for (i = 0; i < iterations; ++i) | 134 | for (i = 0; i < iterations; ++i) |
135 | fn(dst, src, len); | 135 | fn(dst, src, len); |
136 | clock_end = get_clock(); | 136 | cycle_end = get_cycle(); |
137 | 137 | ||
138 | free(src); | 138 | free(src); |
139 | free(dst); | 139 | free(dst); |
140 | return clock_end - clock_start; | 140 | return cycle_end - cycle_start; |
141 | } | 141 | } |
142 | 142 | ||
143 | static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) | 143 | static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault) |
@@ -182,17 +182,17 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
182 | int i; | 182 | int i; |
183 | size_t len; | 183 | size_t len; |
184 | double result_bps[2]; | 184 | double result_bps[2]; |
185 | u64 result_clock[2]; | 185 | u64 result_cycle[2]; |
186 | 186 | ||
187 | argc = parse_options(argc, argv, options, | 187 | argc = parse_options(argc, argv, options, |
188 | bench_mem_memcpy_usage, 0); | 188 | bench_mem_memcpy_usage, 0); |
189 | 189 | ||
190 | if (use_clock) | 190 | if (use_cycle) |
191 | init_clock(); | 191 | init_cycle(); |
192 | 192 | ||
193 | len = (size_t)perf_atoll((char *)length_str); | 193 | len = (size_t)perf_atoll((char *)length_str); |
194 | 194 | ||
195 | result_clock[0] = result_clock[1] = 0ULL; | 195 | result_cycle[0] = result_cycle[1] = 0ULL; |
196 | result_bps[0] = result_bps[1] = 0.0; | 196 | result_bps[0] = result_bps[1] = 0.0; |
197 | 197 | ||
198 | if ((s64)len <= 0) { | 198 | if ((s64)len <= 0) { |
@@ -223,11 +223,11 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
223 | 223 | ||
224 | if (!only_prefault && !no_prefault) { | 224 | if (!only_prefault && !no_prefault) { |
225 | /* show both of results */ | 225 | /* show both of results */ |
226 | if (use_clock) { | 226 | if (use_cycle) { |
227 | result_clock[0] = | 227 | result_cycle[0] = |
228 | do_memcpy_clock(routines[i].fn, len, false); | 228 | do_memcpy_cycle(routines[i].fn, len, false); |
229 | result_clock[1] = | 229 | result_cycle[1] = |
230 | do_memcpy_clock(routines[i].fn, len, true); | 230 | do_memcpy_cycle(routines[i].fn, len, true); |
231 | } else { | 231 | } else { |
232 | result_bps[0] = | 232 | result_bps[0] = |
233 | do_memcpy_gettimeofday(routines[i].fn, | 233 | do_memcpy_gettimeofday(routines[i].fn, |
@@ -237,9 +237,9 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
237 | len, true); | 237 | len, true); |
238 | } | 238 | } |
239 | } else { | 239 | } else { |
240 | if (use_clock) { | 240 | if (use_cycle) { |
241 | result_clock[pf] = | 241 | result_cycle[pf] = |
242 | do_memcpy_clock(routines[i].fn, | 242 | do_memcpy_cycle(routines[i].fn, |
243 | len, only_prefault); | 243 | len, only_prefault); |
244 | } else { | 244 | } else { |
245 | result_bps[pf] = | 245 | result_bps[pf] = |
@@ -251,12 +251,12 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
251 | switch (bench_format) { | 251 | switch (bench_format) { |
252 | case BENCH_FORMAT_DEFAULT: | 252 | case BENCH_FORMAT_DEFAULT: |
253 | if (!only_prefault && !no_prefault) { | 253 | if (!only_prefault && !no_prefault) { |
254 | if (use_clock) { | 254 | if (use_cycle) { |
255 | printf(" %14lf Clock/Byte\n", | 255 | printf(" %14lf Cycle/Byte\n", |
256 | (double)result_clock[0] | 256 | (double)result_cycle[0] |
257 | / (double)len); | 257 | / (double)len); |
258 | printf(" %14lf Clock/Byte (with prefault)\n", | 258 | printf(" %14lf Cycle/Byte (with prefault)\n", |
259 | (double)result_clock[1] | 259 | (double)result_cycle[1] |
260 | / (double)len); | 260 | / (double)len); |
261 | } else { | 261 | } else { |
262 | print_bps(result_bps[0]); | 262 | print_bps(result_bps[0]); |
@@ -265,9 +265,9 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
265 | printf(" (with prefault)\n"); | 265 | printf(" (with prefault)\n"); |
266 | } | 266 | } |
267 | } else { | 267 | } else { |
268 | if (use_clock) { | 268 | if (use_cycle) { |
269 | printf(" %14lf Clock/Byte", | 269 | printf(" %14lf Cycle/Byte", |
270 | (double)result_clock[pf] | 270 | (double)result_cycle[pf] |
271 | / (double)len); | 271 | / (double)len); |
272 | } else | 272 | } else |
273 | print_bps(result_bps[pf]); | 273 | print_bps(result_bps[pf]); |
@@ -277,17 +277,17 @@ int bench_mem_memcpy(int argc, const char **argv, | |||
277 | break; | 277 | break; |
278 | case BENCH_FORMAT_SIMPLE: | 278 | case BENCH_FORMAT_SIMPLE: |
279 | if (!only_prefault && !no_prefault) { | 279 | if (!only_prefault && !no_prefault) { |
280 | if (use_clock) { | 280 | if (use_cycle) { |
281 | printf("%lf %lf\n", | 281 | printf("%lf %lf\n", |
282 | (double)result_clock[0] / (double)len, | 282 | (double)result_cycle[0] / (double)len, |
283 | (double)result_clock[1] / (double)len); | 283 | (double)result_cycle[1] / (double)len); |
284 | } else { | 284 | } else { |
285 | printf("%lf %lf\n", | 285 | printf("%lf %lf\n", |
286 | result_bps[0], result_bps[1]); | 286 | result_bps[0], result_bps[1]); |
287 | } | 287 | } |
288 | } else { | 288 | } else { |
289 | if (use_clock) { | 289 | if (use_cycle) { |
290 | printf("%lf\n", (double)result_clock[pf] | 290 | printf("%lf\n", (double)result_cycle[pf] |
291 | / (double)len); | 291 | / (double)len); |
292 | } else | 292 | } else |
293 | printf("%lf\n", result_bps[pf]); | 293 | printf("%lf\n", result_bps[pf]); |
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c index bf0d5f552017..350cc9557265 100644 --- a/tools/perf/bench/mem-memset.c +++ b/tools/perf/bench/mem-memset.c | |||
@@ -24,8 +24,8 @@ | |||
24 | static const char *length_str = "1MB"; | 24 | static const char *length_str = "1MB"; |
25 | static const char *routine = "default"; | 25 | static const char *routine = "default"; |
26 | static int iterations = 1; | 26 | static int iterations = 1; |
27 | static bool use_clock; | 27 | static bool use_cycle; |
28 | static int clock_fd; | 28 | static int cycle_fd; |
29 | static bool only_prefault; | 29 | static bool only_prefault; |
30 | static bool no_prefault; | 30 | static bool no_prefault; |
31 | 31 | ||
@@ -37,7 +37,7 @@ static const struct option options[] = { | |||
37 | "Specify routine to set"), | 37 | "Specify routine to set"), |
38 | OPT_INTEGER('i', "iterations", &iterations, | 38 | OPT_INTEGER('i', "iterations", &iterations, |
39 | "repeat memset() invocation this number of times"), | 39 | "repeat memset() invocation this number of times"), |
40 | OPT_BOOLEAN('c', "clock", &use_clock, | 40 | OPT_BOOLEAN('c', "cycle", &use_cycle, |
41 | "Use cycles event instead of gettimeofday() for measuring"), | 41 | "Use cycles event instead of gettimeofday() for measuring"), |
42 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, | 42 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, |
43 | "Show only the result with page faults before memset()"), | 43 | "Show only the result with page faults before memset()"), |
@@ -76,27 +76,27 @@ static const char * const bench_mem_memset_usage[] = { | |||
76 | NULL | 76 | NULL |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct perf_event_attr clock_attr = { | 79 | static struct perf_event_attr cycle_attr = { |
80 | .type = PERF_TYPE_HARDWARE, | 80 | .type = PERF_TYPE_HARDWARE, |
81 | .config = PERF_COUNT_HW_CPU_CYCLES | 81 | .config = PERF_COUNT_HW_CPU_CYCLES |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static void init_clock(void) | 84 | static void init_cycle(void) |
85 | { | 85 | { |
86 | clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0); | 86 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0); |
87 | 87 | ||
88 | if (clock_fd < 0 && errno == ENOSYS) | 88 | if (cycle_fd < 0 && errno == ENOSYS) |
89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | 89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); |
90 | else | 90 | else |
91 | BUG_ON(clock_fd < 0); | 91 | BUG_ON(cycle_fd < 0); |
92 | } | 92 | } |
93 | 93 | ||
94 | static u64 get_clock(void) | 94 | static u64 get_cycle(void) |
95 | { | 95 | { |
96 | int ret; | 96 | int ret; |
97 | u64 clk; | 97 | u64 clk; |
98 | 98 | ||
99 | ret = read(clock_fd, &clk, sizeof(u64)); | 99 | ret = read(cycle_fd, &clk, sizeof(u64)); |
100 | BUG_ON(ret != sizeof(u64)); | 100 | BUG_ON(ret != sizeof(u64)); |
101 | 101 | ||
102 | return clk; | 102 | return clk; |
@@ -115,9 +115,9 @@ static void alloc_mem(void **dst, size_t length) | |||
115 | die("memory allocation failed - maybe length is too large?\n"); | 115 | die("memory allocation failed - maybe length is too large?\n"); |
116 | } | 116 | } |
117 | 117 | ||
118 | static u64 do_memset_clock(memset_t fn, size_t len, bool prefault) | 118 | static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault) |
119 | { | 119 | { |
120 | u64 clock_start = 0ULL, clock_end = 0ULL; | 120 | u64 cycle_start = 0ULL, cycle_end = 0ULL; |
121 | void *dst = NULL; | 121 | void *dst = NULL; |
122 | int i; | 122 | int i; |
123 | 123 | ||
@@ -126,13 +126,13 @@ static u64 do_memset_clock(memset_t fn, size_t len, bool prefault) | |||
126 | if (prefault) | 126 | if (prefault) |
127 | fn(dst, -1, len); | 127 | fn(dst, -1, len); |
128 | 128 | ||
129 | clock_start = get_clock(); | 129 | cycle_start = get_cycle(); |
130 | for (i = 0; i < iterations; ++i) | 130 | for (i = 0; i < iterations; ++i) |
131 | fn(dst, i, len); | 131 | fn(dst, i, len); |
132 | clock_end = get_clock(); | 132 | cycle_end = get_cycle(); |
133 | 133 | ||
134 | free(dst); | 134 | free(dst); |
135 | return clock_end - clock_start; | 135 | return cycle_end - cycle_start; |
136 | } | 136 | } |
137 | 137 | ||
138 | static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) | 138 | static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault) |
@@ -176,17 +176,17 @@ int bench_mem_memset(int argc, const char **argv, | |||
176 | int i; | 176 | int i; |
177 | size_t len; | 177 | size_t len; |
178 | double result_bps[2]; | 178 | double result_bps[2]; |
179 | u64 result_clock[2]; | 179 | u64 result_cycle[2]; |
180 | 180 | ||
181 | argc = parse_options(argc, argv, options, | 181 | argc = parse_options(argc, argv, options, |
182 | bench_mem_memset_usage, 0); | 182 | bench_mem_memset_usage, 0); |
183 | 183 | ||
184 | if (use_clock) | 184 | if (use_cycle) |
185 | init_clock(); | 185 | init_cycle(); |
186 | 186 | ||
187 | len = (size_t)perf_atoll((char *)length_str); | 187 | len = (size_t)perf_atoll((char *)length_str); |
188 | 188 | ||
189 | result_clock[0] = result_clock[1] = 0ULL; | 189 | result_cycle[0] = result_cycle[1] = 0ULL; |
190 | result_bps[0] = result_bps[1] = 0.0; | 190 | result_bps[0] = result_bps[1] = 0.0; |
191 | 191 | ||
192 | if ((s64)len <= 0) { | 192 | if ((s64)len <= 0) { |
@@ -217,11 +217,11 @@ int bench_mem_memset(int argc, const char **argv, | |||
217 | 217 | ||
218 | if (!only_prefault && !no_prefault) { | 218 | if (!only_prefault && !no_prefault) { |
219 | /* show both of results */ | 219 | /* show both of results */ |
220 | if (use_clock) { | 220 | if (use_cycle) { |
221 | result_clock[0] = | 221 | result_cycle[0] = |
222 | do_memset_clock(routines[i].fn, len, false); | 222 | do_memset_cycle(routines[i].fn, len, false); |
223 | result_clock[1] = | 223 | result_cycle[1] = |
224 | do_memset_clock(routines[i].fn, len, true); | 224 | do_memset_cycle(routines[i].fn, len, true); |
225 | } else { | 225 | } else { |
226 | result_bps[0] = | 226 | result_bps[0] = |
227 | do_memset_gettimeofday(routines[i].fn, | 227 | do_memset_gettimeofday(routines[i].fn, |
@@ -231,9 +231,9 @@ int bench_mem_memset(int argc, const char **argv, | |||
231 | len, true); | 231 | len, true); |
232 | } | 232 | } |
233 | } else { | 233 | } else { |
234 | if (use_clock) { | 234 | if (use_cycle) { |
235 | result_clock[pf] = | 235 | result_cycle[pf] = |
236 | do_memset_clock(routines[i].fn, | 236 | do_memset_cycle(routines[i].fn, |
237 | len, only_prefault); | 237 | len, only_prefault); |
238 | } else { | 238 | } else { |
239 | result_bps[pf] = | 239 | result_bps[pf] = |
@@ -245,12 +245,12 @@ int bench_mem_memset(int argc, const char **argv, | |||
245 | switch (bench_format) { | 245 | switch (bench_format) { |
246 | case BENCH_FORMAT_DEFAULT: | 246 | case BENCH_FORMAT_DEFAULT: |
247 | if (!only_prefault && !no_prefault) { | 247 | if (!only_prefault && !no_prefault) { |
248 | if (use_clock) { | 248 | if (use_cycle) { |
249 | printf(" %14lf Clock/Byte\n", | 249 | printf(" %14lf Cycle/Byte\n", |
250 | (double)result_clock[0] | 250 | (double)result_cycle[0] |
251 | / (double)len); | 251 | / (double)len); |
252 | printf(" %14lf Clock/Byte (with prefault)\n ", | 252 | printf(" %14lf Cycle/Byte (with prefault)\n ", |
253 | (double)result_clock[1] | 253 | (double)result_cycle[1] |
254 | / (double)len); | 254 | / (double)len); |
255 | } else { | 255 | } else { |
256 | print_bps(result_bps[0]); | 256 | print_bps(result_bps[0]); |
@@ -259,9 +259,9 @@ int bench_mem_memset(int argc, const char **argv, | |||
259 | printf(" (with prefault)\n"); | 259 | printf(" (with prefault)\n"); |
260 | } | 260 | } |
261 | } else { | 261 | } else { |
262 | if (use_clock) { | 262 | if (use_cycle) { |
263 | printf(" %14lf Clock/Byte", | 263 | printf(" %14lf Cycle/Byte", |
264 | (double)result_clock[pf] | 264 | (double)result_cycle[pf] |
265 | / (double)len); | 265 | / (double)len); |
266 | } else | 266 | } else |
267 | print_bps(result_bps[pf]); | 267 | print_bps(result_bps[pf]); |
@@ -271,17 +271,17 @@ int bench_mem_memset(int argc, const char **argv, | |||
271 | break; | 271 | break; |
272 | case BENCH_FORMAT_SIMPLE: | 272 | case BENCH_FORMAT_SIMPLE: |
273 | if (!only_prefault && !no_prefault) { | 273 | if (!only_prefault && !no_prefault) { |
274 | if (use_clock) { | 274 | if (use_cycle) { |
275 | printf("%lf %lf\n", | 275 | printf("%lf %lf\n", |
276 | (double)result_clock[0] / (double)len, | 276 | (double)result_cycle[0] / (double)len, |
277 | (double)result_clock[1] / (double)len); | 277 | (double)result_cycle[1] / (double)len); |
278 | } else { | 278 | } else { |
279 | printf("%lf %lf\n", | 279 | printf("%lf %lf\n", |
280 | result_bps[0], result_bps[1]); | 280 | result_bps[0], result_bps[1]); |
281 | } | 281 | } |
282 | } else { | 282 | } else { |
283 | if (use_clock) { | 283 | if (use_cycle) { |
284 | printf("%lf\n", (double)result_clock[pf] | 284 | printf("%lf\n", (double)result_cycle[pf] |
285 | / (double)len); | 285 | / (double)len); |
286 | } else | 286 | } else |
287 | printf("%lf\n", result_bps[pf]); | 287 | printf("%lf\n", result_bps[pf]); |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3d1f6968f175..e81771364867 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "cpumap.h" | 15 | #include "cpumap.h" |
16 | #include "thread_map.h" | 16 | #include "thread_map.h" |
17 | #include "target.h" | 17 | #include "target.h" |
18 | #include "../../../include/linux/hw_breakpoint.h" | ||
18 | 19 | ||
19 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 20 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
20 | #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) | 21 | #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) |
@@ -152,6 +153,31 @@ static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size) | |||
152 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); | 153 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); |
153 | } | 154 | } |
154 | 155 | ||
156 | static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) | ||
157 | { | ||
158 | int r; | ||
159 | |||
160 | r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr); | ||
161 | |||
162 | if (type & HW_BREAKPOINT_R) | ||
163 | r += scnprintf(bf + r, size - r, "r"); | ||
164 | |||
165 | if (type & HW_BREAKPOINT_W) | ||
166 | r += scnprintf(bf + r, size - r, "w"); | ||
167 | |||
168 | if (type & HW_BREAKPOINT_X) | ||
169 | r += scnprintf(bf + r, size - r, "x"); | ||
170 | |||
171 | return r; | ||
172 | } | ||
173 | |||
174 | static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size) | ||
175 | { | ||
176 | struct perf_event_attr *attr = &evsel->attr; | ||
177 | int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type); | ||
178 | return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); | ||
179 | } | ||
180 | |||
155 | const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] | 181 | const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] |
156 | [PERF_EVSEL__MAX_ALIASES] = { | 182 | [PERF_EVSEL__MAX_ALIASES] = { |
157 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, | 183 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, |
@@ -285,6 +311,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel) | |||
285 | scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint"); | 311 | scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint"); |
286 | break; | 312 | break; |
287 | 313 | ||
314 | case PERF_TYPE_BREAKPOINT: | ||
315 | perf_evsel__bp_name(evsel, bf, sizeof(bf)); | ||
316 | break; | ||
317 | |||
288 | default: | 318 | default: |
289 | scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); | 319 | scnprintf(bf, sizeof(bf), "%s", "unknown attr type"); |
290 | break; | 320 | break; |
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index 1eb804fd3fbf..b6842c1d02a8 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h | |||
@@ -108,4 +108,14 @@ int eprintf(int level, | |||
108 | #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) | 108 | #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) |
109 | #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) | 109 | #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) |
110 | 110 | ||
111 | /* | ||
112 | * This looks more complex than it should be. But we need to | ||
113 | * get the type for the ~ right in round_down (it needs to be | ||
114 | * as wide as the result!), and we want to evaluate the macro | ||
115 | * arguments just once each. | ||
116 | */ | ||
117 | #define __round_mask(x, y) ((__typeof__(x))((y)-1)) | ||
118 | #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) | ||
119 | #define round_down(x, y) ((x) & ~__round_mask(x, y)) | ||
120 | |||
111 | #endif | 121 | #endif |
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index a0f61a2a6835..1b997d2b89ce 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c | |||
@@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) | |||
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | 183 | ||
184 | static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist) | ||
185 | { | ||
186 | struct perf_evsel *evsel = list_entry(evlist->entries.next, | ||
187 | struct perf_evsel, node); | ||
188 | |||
189 | TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); | ||
190 | TEST_ASSERT_VAL("wrong type", | ||
191 | PERF_TYPE_BREAKPOINT == evsel->attr.type); | ||
192 | TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); | ||
193 | TEST_ASSERT_VAL("wrong bp_type", | ||
194 | (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type); | ||
195 | TEST_ASSERT_VAL("wrong bp_len", | ||
196 | HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
184 | static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) | 200 | static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist) |
185 | { | 201 | { |
186 | struct perf_evsel *evsel = list_entry(evlist->entries.next, | 202 | struct perf_evsel *evsel = list_entry(evlist->entries.next, |
@@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) | |||
309 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | 325 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); |
310 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | 326 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); |
311 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | 327 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); |
328 | TEST_ASSERT_VAL("wrong name", | ||
329 | !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u")); | ||
312 | 330 | ||
313 | return test__checkevent_breakpoint(evlist); | 331 | return test__checkevent_breakpoint(evlist); |
314 | } | 332 | } |
@@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist) | |||
322 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | 340 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); |
323 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | 341 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); |
324 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); | 342 | TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); |
343 | TEST_ASSERT_VAL("wrong name", | ||
344 | !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k")); | ||
325 | 345 | ||
326 | return test__checkevent_breakpoint_x(evlist); | 346 | return test__checkevent_breakpoint_x(evlist); |
327 | } | 347 | } |
@@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist) | |||
335 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | 355 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); |
336 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); | 356 | TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv); |
337 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | 357 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); |
358 | TEST_ASSERT_VAL("wrong name", | ||
359 | !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp")); | ||
338 | 360 | ||
339 | return test__checkevent_breakpoint_r(evlist); | 361 | return test__checkevent_breakpoint_r(evlist); |
340 | } | 362 | } |
@@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist) | |||
348 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); | 370 | TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); |
349 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | 371 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); |
350 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | 372 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); |
373 | TEST_ASSERT_VAL("wrong name", | ||
374 | !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up")); | ||
351 | 375 | ||
352 | return test__checkevent_breakpoint_w(evlist); | 376 | return test__checkevent_breakpoint_w(evlist); |
353 | } | 377 | } |
354 | 378 | ||
379 | static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist) | ||
380 | { | ||
381 | struct perf_evsel *evsel = list_entry(evlist->entries.next, | ||
382 | struct perf_evsel, node); | ||
383 | |||
384 | TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); | ||
385 | TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); | ||
386 | TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); | ||
387 | TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip); | ||
388 | TEST_ASSERT_VAL("wrong name", | ||
389 | !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp")); | ||
390 | |||
391 | return test__checkevent_breakpoint_rw(evlist); | ||
392 | } | ||
393 | |||
355 | static int test__checkevent_pmu(struct perf_evlist *evlist) | 394 | static int test__checkevent_pmu(struct perf_evlist *evlist) |
356 | { | 395 | { |
357 | 396 | ||
@@ -585,10 +624,16 @@ static struct test__event_st test__events[] = { | |||
585 | .name = "instructions:H", | 624 | .name = "instructions:H", |
586 | .check = test__checkevent_exclude_guest_modifier, | 625 | .check = test__checkevent_exclude_guest_modifier, |
587 | }, | 626 | }, |
627 | [26] = { | ||
628 | .name = "mem:0:rw", | ||
629 | .check = test__checkevent_breakpoint_rw, | ||
630 | }, | ||
631 | [27] = { | ||
632 | .name = "mem:0:rw:kp", | ||
633 | .check = test__checkevent_breakpoint_rw_modifier, | ||
634 | }, | ||
588 | }; | 635 | }; |
589 | 636 | ||
590 | #define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) | ||
591 | |||
592 | static struct test__event_st test__events_pmu[] = { | 637 | static struct test__event_st test__events_pmu[] = { |
593 | [0] = { | 638 | [0] = { |
594 | .name = "cpu/config=10,config1,config2=3,period=1000/u", | 639 | .name = "cpu/config=10,config1,config2=3,period=1000/u", |
@@ -600,9 +645,6 @@ static struct test__event_st test__events_pmu[] = { | |||
600 | }, | 645 | }, |
601 | }; | 646 | }; |
602 | 647 | ||
603 | #define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \ | ||
604 | sizeof(struct test__event_st)) | ||
605 | |||
606 | struct test__term { | 648 | struct test__term { |
607 | const char *str; | 649 | const char *str; |
608 | __u32 type; | 650 | __u32 type; |
@@ -718,21 +760,17 @@ int parse_events__test(void) | |||
718 | { | 760 | { |
719 | int ret; | 761 | int ret; |
720 | 762 | ||
721 | do { | 763 | #define TEST_EVENTS(tests) \ |
722 | ret = test_events(test__events, TEST__EVENTS_CNT); | 764 | do { \ |
723 | if (ret) | 765 | ret = test_events(tests, ARRAY_SIZE(tests)); \ |
724 | break; | 766 | if (ret) \ |
725 | 767 | return ret; \ | |
726 | if (test_pmu()) { | 768 | } while (0) |
727 | ret = test_events(test__events_pmu, | ||
728 | TEST__EVENTS_PMU_CNT); | ||
729 | if (ret) | ||
730 | break; | ||
731 | } | ||
732 | 769 | ||
733 | ret = test_terms(test__terms, TEST__TERMS_CNT); | 770 | TEST_EVENTS(test__events); |
734 | 771 | ||
735 | } while (0); | 772 | if (test_pmu()) |
773 | TEST_EVENTS(test__events_pmu); | ||
736 | 774 | ||
737 | return ret; | 775 | return test_terms(test__terms, ARRAY_SIZE(test__terms)); |
738 | } | 776 | } |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 0cc27da30ddb..1aa721d7c10f 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -19,8 +19,6 @@ | |||
19 | #define MAX_NAME_LEN 100 | 19 | #define MAX_NAME_LEN 100 |
20 | 20 | ||
21 | struct event_symbol { | 21 | struct event_symbol { |
22 | u8 type; | ||
23 | u64 config; | ||
24 | const char *symbol; | 22 | const char *symbol; |
25 | const char *alias; | 23 | const char *alias; |
26 | }; | 24 | }; |
@@ -30,30 +28,86 @@ extern int parse_events_debug; | |||
30 | #endif | 28 | #endif |
31 | int parse_events_parse(void *data, void *scanner); | 29 | int parse_events_parse(void *data, void *scanner); |
32 | 30 | ||
33 | #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x | 31 | static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { |
34 | #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x | 32 | [PERF_COUNT_HW_CPU_CYCLES] = { |
35 | 33 | .symbol = "cpu-cycles", | |
36 | static struct event_symbol event_symbols[] = { | 34 | .alias = "cycles", |
37 | { CHW(CPU_CYCLES), "cpu-cycles", "cycles" }, | 35 | }, |
38 | { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" }, | 36 | [PERF_COUNT_HW_INSTRUCTIONS] = { |
39 | { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" }, | 37 | .symbol = "instructions", |
40 | { CHW(INSTRUCTIONS), "instructions", "" }, | 38 | .alias = "", |
41 | { CHW(CACHE_REFERENCES), "cache-references", "" }, | 39 | }, |
42 | { CHW(CACHE_MISSES), "cache-misses", "" }, | 40 | [PERF_COUNT_HW_CACHE_REFERENCES] = { |
43 | { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" }, | 41 | .symbol = "cache-references", |
44 | { CHW(BRANCH_MISSES), "branch-misses", "" }, | 42 | .alias = "", |
45 | { CHW(BUS_CYCLES), "bus-cycles", "" }, | 43 | }, |
46 | { CHW(REF_CPU_CYCLES), "ref-cycles", "" }, | 44 | [PERF_COUNT_HW_CACHE_MISSES] = { |
47 | 45 | .symbol = "cache-misses", | |
48 | { CSW(CPU_CLOCK), "cpu-clock", "" }, | 46 | .alias = "", |
49 | { CSW(TASK_CLOCK), "task-clock", "" }, | 47 | }, |
50 | { CSW(PAGE_FAULTS), "page-faults", "faults" }, | 48 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { |
51 | { CSW(PAGE_FAULTS_MIN), "minor-faults", "" }, | 49 | .symbol = "branch-instructions", |
52 | { CSW(PAGE_FAULTS_MAJ), "major-faults", "" }, | 50 | .alias = "branches", |
53 | { CSW(CONTEXT_SWITCHES), "context-switches", "cs" }, | 51 | }, |
54 | { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" }, | 52 | [PERF_COUNT_HW_BRANCH_MISSES] = { |
55 | { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" }, | 53 | .symbol = "branch-misses", |
56 | { CSW(EMULATION_FAULTS), "emulation-faults", "" }, | 54 | .alias = "", |
55 | }, | ||
56 | [PERF_COUNT_HW_BUS_CYCLES] = { | ||
57 | .symbol = "bus-cycles", | ||
58 | .alias = "", | ||
59 | }, | ||
60 | [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { | ||
61 | .symbol = "stalled-cycles-frontend", | ||
62 | .alias = "idle-cycles-frontend", | ||
63 | }, | ||
64 | [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { | ||
65 | .symbol = "stalled-cycles-backend", | ||
66 | .alias = "idle-cycles-backend", | ||
67 | }, | ||
68 | [PERF_COUNT_HW_REF_CPU_CYCLES] = { | ||
69 | .symbol = "ref-cycles", | ||
70 | .alias = "", | ||
71 | }, | ||
72 | }; | ||
73 | |||
74 | static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { | ||
75 | [PERF_COUNT_SW_CPU_CLOCK] = { | ||
76 | .symbol = "cpu-clock", | ||
77 | .alias = "", | ||
78 | }, | ||
79 | [PERF_COUNT_SW_TASK_CLOCK] = { | ||
80 | .symbol = "task-clock", | ||
81 | .alias = "", | ||
82 | }, | ||
83 | [PERF_COUNT_SW_PAGE_FAULTS] = { | ||
84 | .symbol = "page-faults", | ||
85 | .alias = "faults", | ||
86 | }, | ||
87 | [PERF_COUNT_SW_CONTEXT_SWITCHES] = { | ||
88 | .symbol = "context-switches", | ||
89 | .alias = "cs", | ||
90 | }, | ||
91 | [PERF_COUNT_SW_CPU_MIGRATIONS] = { | ||
92 | .symbol = "cpu-migrations", | ||
93 | .alias = "migrations", | ||
94 | }, | ||
95 | [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { | ||
96 | .symbol = "minor-faults", | ||
97 | .alias = "", | ||
98 | }, | ||
99 | [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { | ||
100 | .symbol = "major-faults", | ||
101 | .alias = "", | ||
102 | }, | ||
103 | [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { | ||
104 | .symbol = "alignment-faults", | ||
105 | .alias = "", | ||
106 | }, | ||
107 | [PERF_COUNT_SW_EMULATION_FAULTS] = { | ||
108 | .symbol = "emulation-faults", | ||
109 | .alias = "", | ||
110 | }, | ||
57 | }; | 111 | }; |
58 | 112 | ||
59 | #define __PERF_EVENT_FIELD(config, name) \ | 113 | #define __PERF_EVENT_FIELD(config, name) \ |
@@ -383,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr) | |||
383 | if (!type || !type[i]) | 437 | if (!type || !type[i]) |
384 | break; | 438 | break; |
385 | 439 | ||
440 | #define CHECK_SET_TYPE(bit) \ | ||
441 | do { \ | ||
442 | if (attr->bp_type & bit) \ | ||
443 | return -EINVAL; \ | ||
444 | else \ | ||
445 | attr->bp_type |= bit; \ | ||
446 | } while (0) | ||
447 | |||
386 | switch (type[i]) { | 448 | switch (type[i]) { |
387 | case 'r': | 449 | case 'r': |
388 | attr->bp_type |= HW_BREAKPOINT_R; | 450 | CHECK_SET_TYPE(HW_BREAKPOINT_R); |
389 | break; | 451 | break; |
390 | case 'w': | 452 | case 'w': |
391 | attr->bp_type |= HW_BREAKPOINT_W; | 453 | CHECK_SET_TYPE(HW_BREAKPOINT_W); |
392 | break; | 454 | break; |
393 | case 'x': | 455 | case 'x': |
394 | attr->bp_type |= HW_BREAKPOINT_X; | 456 | CHECK_SET_TYPE(HW_BREAKPOINT_X); |
395 | break; | 457 | break; |
396 | default: | 458 | default: |
397 | return -EINVAL; | 459 | return -EINVAL; |
398 | } | 460 | } |
399 | } | 461 | } |
400 | 462 | ||
463 | #undef CHECK_SET_TYPE | ||
464 | |||
401 | if (!attr->bp_type) /* Default */ | 465 | if (!attr->bp_type) /* Default */ |
402 | attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; | 466 | attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; |
403 | 467 | ||
@@ -408,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx, | |||
408 | void *ptr, char *type) | 472 | void *ptr, char *type) |
409 | { | 473 | { |
410 | struct perf_event_attr attr; | 474 | struct perf_event_attr attr; |
411 | char name[MAX_NAME_LEN]; | ||
412 | 475 | ||
413 | memset(&attr, 0, sizeof(attr)); | 476 | memset(&attr, 0, sizeof(attr)); |
414 | attr.bp_addr = (unsigned long) ptr; | 477 | attr.bp_addr = (unsigned long) ptr; |
@@ -427,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx, | |||
427 | 490 | ||
428 | attr.type = PERF_TYPE_BREAKPOINT; | 491 | attr.type = PERF_TYPE_BREAKPOINT; |
429 | 492 | ||
430 | snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw"); | 493 | return add_event(list, idx, &attr, NULL); |
431 | return add_event(list, idx, &attr, name); | ||
432 | } | 494 | } |
433 | 495 | ||
434 | static int config_term(struct perf_event_attr *attr, | 496 | static int config_term(struct perf_event_attr *attr, |
@@ -816,16 +878,13 @@ int is_valid_tracepoint(const char *event_string) | |||
816 | return 0; | 878 | return 0; |
817 | } | 879 | } |
818 | 880 | ||
819 | void print_events_type(u8 type) | 881 | static void __print_events_type(u8 type, struct event_symbol *syms, |
882 | unsigned max) | ||
820 | { | 883 | { |
821 | struct event_symbol *syms = event_symbols; | ||
822 | unsigned int i; | ||
823 | char name[64]; | 884 | char name[64]; |
885 | unsigned i; | ||
824 | 886 | ||
825 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { | 887 | for (i = 0; i < max ; i++, syms++) { |
826 | if (type != syms->type) | ||
827 | continue; | ||
828 | |||
829 | if (strlen(syms->alias)) | 888 | if (strlen(syms->alias)) |
830 | snprintf(name, sizeof(name), "%s OR %s", | 889 | snprintf(name, sizeof(name), "%s OR %s", |
831 | syms->symbol, syms->alias); | 890 | syms->symbol, syms->alias); |
@@ -837,6 +896,14 @@ void print_events_type(u8 type) | |||
837 | } | 896 | } |
838 | } | 897 | } |
839 | 898 | ||
899 | void print_events_type(u8 type) | ||
900 | { | ||
901 | if (type == PERF_TYPE_SOFTWARE) | ||
902 | __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX); | ||
903 | else | ||
904 | __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX); | ||
905 | } | ||
906 | |||
840 | int print_hwcache_events(const char *event_glob) | 907 | int print_hwcache_events(const char *event_glob) |
841 | { | 908 | { |
842 | unsigned int type, op, i, printed = 0; | 909 | unsigned int type, op, i, printed = 0; |
@@ -864,26 +931,13 @@ int print_hwcache_events(const char *event_glob) | |||
864 | return printed; | 931 | return printed; |
865 | } | 932 | } |
866 | 933 | ||
867 | /* | 934 | static void print_symbol_events(const char *event_glob, unsigned type, |
868 | * Print the help text for the event symbols: | 935 | struct event_symbol *syms, unsigned max) |
869 | */ | ||
870 | void print_events(const char *event_glob) | ||
871 | { | 936 | { |
872 | unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0; | 937 | unsigned i, printed = 0; |
873 | struct event_symbol *syms = event_symbols; | ||
874 | char name[MAX_NAME_LEN]; | 938 | char name[MAX_NAME_LEN]; |
875 | 939 | ||
876 | printf("\n"); | 940 | for (i = 0; i < max; i++, syms++) { |
877 | printf("List of pre-defined events (to be used in -e):\n"); | ||
878 | |||
879 | for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { | ||
880 | type = syms->type; | ||
881 | |||
882 | if (type != prev_type && printed) { | ||
883 | printf("\n"); | ||
884 | printed = 0; | ||
885 | ntypes_printed++; | ||
886 | } | ||
887 | 941 | ||
888 | if (event_glob != NULL && | 942 | if (event_glob != NULL && |
889 | !(strglobmatch(syms->symbol, event_glob) || | 943 | !(strglobmatch(syms->symbol, event_glob) || |
@@ -894,17 +948,31 @@ void print_events(const char *event_glob) | |||
894 | snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); | 948 | snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); |
895 | else | 949 | else |
896 | strncpy(name, syms->symbol, MAX_NAME_LEN); | 950 | strncpy(name, syms->symbol, MAX_NAME_LEN); |
897 | printf(" %-50s [%s]\n", name, | ||
898 | event_type_descriptors[type]); | ||
899 | 951 | ||
900 | prev_type = type; | 952 | printf(" %-50s [%s]\n", name, event_type_descriptors[type]); |
901 | ++printed; | 953 | |
954 | printed++; | ||
902 | } | 955 | } |
903 | 956 | ||
904 | if (ntypes_printed) { | 957 | if (printed) |
905 | printed = 0; | ||
906 | printf("\n"); | 958 | printf("\n"); |
907 | } | 959 | } |
960 | |||
961 | /* | ||
962 | * Print the help text for the event symbols: | ||
963 | */ | ||
964 | void print_events(const char *event_glob) | ||
965 | { | ||
966 | |||
967 | printf("\n"); | ||
968 | printf("List of pre-defined events (to be used in -e):\n"); | ||
969 | |||
970 | print_symbol_events(event_glob, PERF_TYPE_HARDWARE, | ||
971 | event_symbols_hw, PERF_COUNT_HW_MAX); | ||
972 | |||
973 | print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, | ||
974 | event_symbols_sw, PERF_COUNT_SW_MAX); | ||
975 | |||
908 | print_hwcache_events(event_glob); | 976 | print_hwcache_events(event_glob); |
909 | 977 | ||
910 | if (event_glob != NULL) | 978 | if (event_glob != NULL) |
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 488362e14133..384ca74c6b22 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
@@ -56,7 +56,7 @@ static int sym(yyscan_t scanner, int type, int config) | |||
56 | YYSTYPE *yylval = parse_events_get_lval(scanner); | 56 | YYSTYPE *yylval = parse_events_get_lval(scanner); |
57 | 57 | ||
58 | yylval->num = (type << 16) + config; | 58 | yylval->num = (type << 16) + config; |
59 | return PE_VALUE_SYM; | 59 | return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW; |
60 | } | 60 | } |
61 | 61 | ||
62 | static int term(yyscan_t scanner, int type) | 62 | static int term(yyscan_t scanner, int type) |
@@ -76,7 +76,7 @@ num_hex 0x[a-fA-F0-9]+ | |||
76 | num_raw_hex [a-fA-F0-9]+ | 76 | num_raw_hex [a-fA-F0-9]+ |
77 | name [a-zA-Z_*?][a-zA-Z0-9_*?]* | 77 | name [a-zA-Z_*?][a-zA-Z0-9_*?]* |
78 | modifier_event [ukhpGH]{1,8} | 78 | modifier_event [ukhpGH]{1,8} |
79 | modifier_bp [rwx] | 79 | modifier_bp [rwx]{1,3} |
80 | 80 | ||
81 | %% | 81 | %% |
82 | 82 | ||
@@ -152,6 +152,7 @@ r{num_raw_hex} { return raw(yyscanner); } | |||
152 | , { return ','; } | 152 | , { return ','; } |
153 | : { return ':'; } | 153 | : { return ':'; } |
154 | = { return '='; } | 154 | = { return '='; } |
155 | \n { } | ||
155 | 156 | ||
156 | <mem>{ | 157 | <mem>{ |
157 | {modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } | 158 | {modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } |
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 9525c455d27f..2bc5fbff2b5d 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y | |||
@@ -26,14 +26,15 @@ do { \ | |||
26 | %} | 26 | %} |
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 PE_RAW PE_TERM | 29 | %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM |
30 | %token PE_NAME | 30 | %token PE_NAME |
31 | %token PE_MODIFIER_EVENT PE_MODIFIER_BP | 31 | %token PE_MODIFIER_EVENT PE_MODIFIER_BP |
32 | %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT | 32 | %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT |
33 | %token PE_PREFIX_MEM PE_PREFIX_RAW | 33 | %token PE_PREFIX_MEM PE_PREFIX_RAW |
34 | %token PE_ERROR | 34 | %token PE_ERROR |
35 | %type <num> PE_VALUE | 35 | %type <num> PE_VALUE |
36 | %type <num> PE_VALUE_SYM | 36 | %type <num> PE_VALUE_SYM_HW |
37 | %type <num> PE_VALUE_SYM_SW | ||
37 | %type <num> PE_RAW | 38 | %type <num> PE_RAW |
38 | %type <num> PE_TERM | 39 | %type <num> PE_TERM |
39 | %type <str> PE_NAME | 40 | %type <str> PE_NAME |
@@ -41,6 +42,7 @@ do { \ | |||
41 | %type <str> PE_NAME_CACHE_OP_RESULT | 42 | %type <str> PE_NAME_CACHE_OP_RESULT |
42 | %type <str> PE_MODIFIER_EVENT | 43 | %type <str> PE_MODIFIER_EVENT |
43 | %type <str> PE_MODIFIER_BP | 44 | %type <str> PE_MODIFIER_BP |
45 | %type <num> value_sym | ||
44 | %type <head> event_config | 46 | %type <head> event_config |
45 | %type <term> event_term | 47 | %type <term> event_term |
46 | %type <head> event_pmu | 48 | %type <head> event_pmu |
@@ -109,8 +111,13 @@ PE_NAME '/' event_config '/' | |||
109 | $$ = list; | 111 | $$ = list; |
110 | } | 112 | } |
111 | 113 | ||
114 | value_sym: | ||
115 | PE_VALUE_SYM_HW | ||
116 | | | ||
117 | PE_VALUE_SYM_SW | ||
118 | |||
112 | event_legacy_symbol: | 119 | event_legacy_symbol: |
113 | PE_VALUE_SYM '/' event_config '/' | 120 | value_sym '/' event_config '/' |
114 | { | 121 | { |
115 | struct parse_events_data__events *data = _data; | 122 | struct parse_events_data__events *data = _data; |
116 | struct list_head *list = NULL; | 123 | struct list_head *list = NULL; |
@@ -123,7 +130,7 @@ PE_VALUE_SYM '/' event_config '/' | |||
123 | $$ = list; | 130 | $$ = list; |
124 | } | 131 | } |
125 | | | 132 | | |
126 | PE_VALUE_SYM sep_slash_dc | 133 | value_sym sep_slash_dc |
127 | { | 134 | { |
128 | struct parse_events_data__events *data = _data; | 135 | struct parse_events_data__events *data = _data; |
129 | struct list_head *list = NULL; | 136 | struct list_head *list = NULL; |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 74d0948ec368..67715a42cd6d 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format) | |||
72 | "%s/bus/event_source/devices/%s/format", sysfs, name); | 72 | "%s/bus/event_source/devices/%s/format", sysfs, name); |
73 | 73 | ||
74 | if (stat(path, &st) < 0) | 74 | if (stat(path, &st) < 0) |
75 | return -1; | 75 | return 0; /* no error if format does not exist */ |
76 | 76 | ||
77 | if (pmu_format_parse(path, format)) | 77 | if (pmu_format_parse(path, format)) |
78 | return -1; | 78 | return -1; |
@@ -252,6 +252,7 @@ static struct perf_pmu *pmu_lookup(char *name) | |||
252 | list_splice(&aliases, &pmu->aliases); | 252 | list_splice(&aliases, &pmu->aliases); |
253 | pmu->name = strdup(name); | 253 | pmu->name = strdup(name); |
254 | pmu->type = type; | 254 | pmu->type = type; |
255 | list_add_tail(&pmu->list, &pmus); | ||
255 | return pmu; | 256 | return pmu; |
256 | } | 257 | } |
257 | 258 | ||
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index b3620fe12763..02dfa19a467f 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
@@ -209,6 +209,10 @@ static void define_event_symbols(struct event_format *event, | |||
209 | define_symbolic_values(args->symbol.symbols, ev_name, | 209 | define_symbolic_values(args->symbol.symbols, ev_name, |
210 | cur_field_name); | 210 | cur_field_name); |
211 | break; | 211 | break; |
212 | case PRINT_HEX: | ||
213 | define_event_symbols(event, ev_name, args->hex.field); | ||
214 | define_event_symbols(event, ev_name, args->hex.size); | ||
215 | break; | ||
212 | case PRINT_BSTRING: | 216 | case PRINT_BSTRING: |
213 | case PRINT_DYNAMIC_ARRAY: | 217 | case PRINT_DYNAMIC_ARRAY: |
214 | case PRINT_STRING: | 218 | case PRINT_STRING: |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index a8ca2f8179a9..ce4d1b0c3862 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -166,6 +166,10 @@ static void define_event_symbols(struct event_format *event, | |||
166 | define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, | 166 | define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, |
167 | cur_field_name); | 167 | cur_field_name); |
168 | break; | 168 | break; |
169 | case PRINT_HEX: | ||
170 | define_event_symbols(event, ev_name, args->hex.field); | ||
171 | define_event_symbols(event, ev_name, args->hex.size); | ||
172 | break; | ||
169 | case PRINT_STRING: | 173 | case PRINT_STRING: |
170 | break; | 174 | break; |
171 | case PRINT_TYPE: | 175 | case PRINT_TYPE: |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 994f4ffdcd05..50958bbeb26a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1478,14 +1478,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size) | |||
1478 | goto out; | 1478 | goto out; |
1479 | } | 1479 | } |
1480 | 1480 | ||
1481 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 1481 | /* |
1482 | ".note.gnu.build-id", NULL); | 1482 | * Check following sections for notes: |
1483 | if (sec == NULL) { | 1483 | * '.note.gnu.build-id' |
1484 | * '.notes' | ||
1485 | * '.note' (VDSO specific) | ||
1486 | */ | ||
1487 | do { | ||
1488 | sec = elf_section_by_name(elf, &ehdr, &shdr, | ||
1489 | ".note.gnu.build-id", NULL); | ||
1490 | if (sec) | ||
1491 | break; | ||
1492 | |||
1484 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 1493 | sec = elf_section_by_name(elf, &ehdr, &shdr, |
1485 | ".notes", NULL); | 1494 | ".notes", NULL); |
1486 | if (sec == NULL) | 1495 | if (sec) |
1487 | goto out; | 1496 | break; |
1488 | } | 1497 | |
1498 | sec = elf_section_by_name(elf, &ehdr, &shdr, | ||
1499 | ".note", NULL); | ||
1500 | if (sec) | ||
1501 | break; | ||
1502 | |||
1503 | return err; | ||
1504 | |||
1505 | } while (0); | ||
1489 | 1506 | ||
1490 | data = elf_getdata(sec, NULL); | 1507 | data = elf_getdata(sec, NULL); |
1491 | if (data == NULL) | 1508 | if (data == NULL) |