diff options
| -rw-r--r-- | tools/perf/Documentation/perf-record.txt | 3 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 62 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 4 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 12 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.l | 2 | ||||
| -rw-r--r-- | tools/perf/util/pmu.c | 4 |
7 files changed, 86 insertions, 3 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index afbe45ef7e3e..7f82dec2b541 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
| @@ -53,6 +53,9 @@ OPTIONS | |||
| 53 | - 'time': Disable/enable time stamping. Acceptable values are 1 for | 53 | - 'time': Disable/enable time stamping. Acceptable values are 1 for |
| 54 | enabling time stamping. 0 for disabling time stamping. | 54 | enabling time stamping. 0 for disabling time stamping. |
| 55 | The default is 1. | 55 | The default is 1. |
| 56 | - 'call-graph': Disable/enable callgraph. Acceptable str are "fp" for | ||
| 57 | FP mode, "dwarf" for DWARF mode, "lbr" for LBR mode. | ||
| 58 | - 'stack-size': user stack size for dwarf mode | ||
| 56 | Note: If user explicitly sets options which conflict with the params, | 59 | Note: If user explicitly sets options which conflict with the params, |
| 57 | the value set by the params will be overridden. | 60 | the value set by the params will be overridden. |
| 58 | 61 | ||
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 04fddddc6b6f..6647925d5f28 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -588,11 +588,36 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel, | |||
| 588 | } | 588 | } |
| 589 | } | 589 | } |
| 590 | 590 | ||
| 591 | static void apply_config_terms(struct perf_evsel *evsel) | 591 | static void |
| 592 | perf_evsel__reset_callgraph(struct perf_evsel *evsel, | ||
| 593 | struct callchain_param *param) | ||
| 594 | { | ||
| 595 | struct perf_event_attr *attr = &evsel->attr; | ||
| 596 | |||
| 597 | perf_evsel__reset_sample_bit(evsel, CALLCHAIN); | ||
| 598 | if (param->record_mode == CALLCHAIN_LBR) { | ||
| 599 | perf_evsel__reset_sample_bit(evsel, BRANCH_STACK); | ||
| 600 | attr->branch_sample_type &= ~(PERF_SAMPLE_BRANCH_USER | | ||
| 601 | PERF_SAMPLE_BRANCH_CALL_STACK); | ||
| 602 | } | ||
| 603 | if (param->record_mode == CALLCHAIN_DWARF) { | ||
| 604 | perf_evsel__reset_sample_bit(evsel, REGS_USER); | ||
| 605 | perf_evsel__reset_sample_bit(evsel, STACK_USER); | ||
| 606 | } | ||
| 607 | } | ||
| 608 | |||
| 609 | static void apply_config_terms(struct perf_evsel *evsel, | ||
| 610 | struct record_opts *opts) | ||
| 592 | { | 611 | { |
| 593 | struct perf_evsel_config_term *term; | 612 | struct perf_evsel_config_term *term; |
| 594 | struct list_head *config_terms = &evsel->config_terms; | 613 | struct list_head *config_terms = &evsel->config_terms; |
| 595 | struct perf_event_attr *attr = &evsel->attr; | 614 | struct perf_event_attr *attr = &evsel->attr; |
| 615 | struct callchain_param param; | ||
| 616 | u32 dump_size = 0; | ||
| 617 | char *callgraph_buf = NULL; | ||
| 618 | |||
| 619 | /* callgraph default */ | ||
| 620 | param.record_mode = callchain_param.record_mode; | ||
| 596 | 621 | ||
| 597 | list_for_each_entry(term, config_terms, list) { | 622 | list_for_each_entry(term, config_terms, list) { |
| 598 | switch (term->type) { | 623 | switch (term->type) { |
| @@ -610,10 +635,43 @@ static void apply_config_terms(struct perf_evsel *evsel) | |||
| 610 | else | 635 | else |
| 611 | perf_evsel__reset_sample_bit(evsel, TIME); | 636 | perf_evsel__reset_sample_bit(evsel, TIME); |
| 612 | break; | 637 | break; |
| 638 | case PERF_EVSEL__CONFIG_TERM_CALLGRAPH: | ||
| 639 | callgraph_buf = term->val.callgraph; | ||
| 640 | break; | ||
| 641 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: | ||
| 642 | dump_size = term->val.stack_user; | ||
| 643 | break; | ||
| 613 | default: | 644 | default: |
| 614 | break; | 645 | break; |
| 615 | } | 646 | } |
| 616 | } | 647 | } |
| 648 | |||
| 649 | /* User explicitly set per-event callgraph, clear the old setting and reset. */ | ||
| 650 | if ((callgraph_buf != NULL) || (dump_size > 0)) { | ||
| 651 | |||
| 652 | /* parse callgraph parameters */ | ||
| 653 | if (callgraph_buf != NULL) { | ||
| 654 | param.enabled = true; | ||
| 655 | if (parse_callchain_record(callgraph_buf, ¶m)) { | ||
| 656 | pr_err("per-event callgraph setting for %s failed. " | ||
| 657 | "Apply callgraph global setting for it\n", | ||
| 658 | evsel->name); | ||
| 659 | return; | ||
| 660 | } | ||
| 661 | } | ||
| 662 | if (dump_size > 0) { | ||
| 663 | dump_size = round_up(dump_size, sizeof(u64)); | ||
| 664 | param.dump_size = dump_size; | ||
| 665 | } | ||
| 666 | |||
| 667 | /* If global callgraph set, clear it */ | ||
| 668 | if (callchain_param.enabled) | ||
| 669 | perf_evsel__reset_callgraph(evsel, &callchain_param); | ||
| 670 | |||
| 671 | /* set perf-event callgraph */ | ||
| 672 | if (param.enabled) | ||
| 673 | perf_evsel__config_callgraph(evsel, opts, ¶m); | ||
| 674 | } | ||
| 617 | } | 675 | } |
| 618 | 676 | ||
| 619 | /* | 677 | /* |
| @@ -812,7 +870,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
| 812 | * Apply event specific term settings, | 870 | * Apply event specific term settings, |
| 813 | * it overloads any global configuration. | 871 | * it overloads any global configuration. |
| 814 | */ | 872 | */ |
| 815 | apply_config_terms(evsel); | 873 | apply_config_terms(evsel, opts); |
| 816 | } | 874 | } |
| 817 | 875 | ||
| 818 | static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 876 | static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index fdf2674ab339..93ac6b128149 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -41,6 +41,8 @@ enum { | |||
| 41 | PERF_EVSEL__CONFIG_TERM_PERIOD, | 41 | PERF_EVSEL__CONFIG_TERM_PERIOD, |
| 42 | PERF_EVSEL__CONFIG_TERM_FREQ, | 42 | PERF_EVSEL__CONFIG_TERM_FREQ, |
| 43 | PERF_EVSEL__CONFIG_TERM_TIME, | 43 | PERF_EVSEL__CONFIG_TERM_TIME, |
| 44 | PERF_EVSEL__CONFIG_TERM_CALLGRAPH, | ||
| 45 | PERF_EVSEL__CONFIG_TERM_STACK_USER, | ||
| 44 | PERF_EVSEL__CONFIG_TERM_MAX, | 46 | PERF_EVSEL__CONFIG_TERM_MAX, |
| 45 | }; | 47 | }; |
| 46 | 48 | ||
| @@ -51,6 +53,8 @@ struct perf_evsel_config_term { | |||
| 51 | u64 period; | 53 | u64 period; |
| 52 | u64 freq; | 54 | u64 freq; |
| 53 | bool time; | 55 | bool time; |
| 56 | char *callgraph; | ||
| 57 | u64 stack_user; | ||
| 54 | } val; | 58 | } val; |
| 55 | }; | 59 | }; |
| 56 | 60 | ||
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index dbf315df4220..d826e6f515db 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
| @@ -614,6 +614,12 @@ do { \ | |||
| 614 | return -EINVAL; | 614 | return -EINVAL; |
| 615 | } | 615 | } |
| 616 | break; | 616 | break; |
| 617 | case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: | ||
| 618 | CHECK_TYPE_VAL(STR); | ||
| 619 | break; | ||
| 620 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | ||
| 621 | CHECK_TYPE_VAL(NUM); | ||
| 622 | break; | ||
| 617 | case PARSE_EVENTS__TERM_TYPE_NAME: | 623 | case PARSE_EVENTS__TERM_TYPE_NAME: |
| 618 | CHECK_TYPE_VAL(STR); | 624 | CHECK_TYPE_VAL(STR); |
| 619 | break; | 625 | break; |
| @@ -668,6 +674,12 @@ do { \ | |||
| 668 | case PARSE_EVENTS__TERM_TYPE_TIME: | 674 | case PARSE_EVENTS__TERM_TYPE_TIME: |
| 669 | ADD_CONFIG_TERM(TIME, time, term->val.num); | 675 | ADD_CONFIG_TERM(TIME, time, term->val.num); |
| 670 | break; | 676 | break; |
| 677 | case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: | ||
| 678 | ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str); | ||
| 679 | break; | ||
| 680 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | ||
| 681 | ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); | ||
| 682 | break; | ||
| 671 | default: | 683 | default: |
| 672 | break; | 684 | break; |
| 673 | } | 685 | } |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index ce2d13a16226..a09b0e210997 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
| @@ -65,6 +65,8 @@ enum { | |||
| 65 | PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ, | 65 | PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ, |
| 66 | PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, | 66 | PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, |
| 67 | PARSE_EVENTS__TERM_TYPE_TIME, | 67 | PARSE_EVENTS__TERM_TYPE_TIME, |
| 68 | PARSE_EVENTS__TERM_TYPE_CALLGRAPH, | ||
| 69 | PARSE_EVENTS__TERM_TYPE_STACKSIZE, | ||
| 68 | }; | 70 | }; |
| 69 | 71 | ||
| 70 | struct parse_events_term { | 72 | struct parse_events_term { |
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 4306f5ad75c7..936d566f48d8 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
| @@ -185,6 +185,8 @@ period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } | |||
| 185 | freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); } | 185 | freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); } |
| 186 | branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } | 186 | branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } |
| 187 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } | 187 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } |
| 188 | call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } | ||
| 189 | stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } | ||
| 188 | , { return ','; } | 190 | , { return ','; } |
| 189 | "/" { BEGIN(INITIAL); return '/'; } | 191 | "/" { BEGIN(INITIAL); return '/'; } |
| 190 | {name_minus} { return str(yyscanner, PE_NAME); } | 192 | {name_minus} { return str(yyscanner, PE_NAME); } |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d85f11b8cacf..84cad054d6f7 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
| @@ -634,7 +634,9 @@ static char *formats_error_string(struct list_head *formats) | |||
| 634 | { | 634 | { |
| 635 | struct perf_pmu_format *format; | 635 | struct perf_pmu_format *format; |
| 636 | char *err, *str; | 636 | char *err, *str; |
| 637 | static const char *static_terms = "config,config1,config2,name,period,freq,branch_type,time\n"; | 637 | static const char *static_terms = "config,config1,config2,name," |
| 638 | "period,freq,branch_type,time," | ||
| 639 | "call-graph,stack-size\n"; | ||
| 638 | unsigned i = 0; | 640 | unsigned i = 0; |
| 639 | 641 | ||
| 640 | if (!asprintf(&str, "valid terms:")) | 642 | if (!asprintf(&str, "valid terms:")) |
