diff options
-rw-r--r-- | tools/perf/Documentation/perf-list.txt | 12 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 2 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 3 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 27 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 1 | ||||
-rw-r--r-- | tools/perf/util/parse-events.l | 1 |
6 files changed, 46 insertions, 0 deletions
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 138fb6e94b3c..18ed1b0fceb3 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -199,6 +199,18 @@ also be supplied. For example: perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ... +EVENT QUALIFIERS: + +It is also possible to add extra qualifiers to an event: + +percore: + +Sums up the event counts for all hardware threads in a core, e.g.: + + + perf stat -e cpu/event=0,umask=0x3,percore=1/ + + EVENT GROUPS ------------ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index a10cf4cde920..a6f572a40deb 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -813,6 +813,8 @@ static void apply_config_terms(struct perf_evsel *evsel, break; case PERF_EVSEL__CONFIG_TERM_DRV_CFG: break; + case PERF_EVSEL__CONFIG_TERM_PERCORE: + break; default: break; } diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 6d190cbf1070..cad54e8ba522 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -50,6 +50,7 @@ enum term_type { PERF_EVSEL__CONFIG_TERM_OVERWRITE, PERF_EVSEL__CONFIG_TERM_DRV_CFG, PERF_EVSEL__CONFIG_TERM_BRANCH, + PERF_EVSEL__CONFIG_TERM_PERCORE, }; struct perf_evsel_config_term { @@ -67,6 +68,7 @@ struct perf_evsel_config_term { bool overwrite; char *branch; unsigned long max_events; + bool percore; } val; bool weak; }; @@ -158,6 +160,7 @@ struct perf_evsel { struct perf_evsel **metric_events; bool collect_stat; bool weak_group; + bool percore; const char *pmu_name; struct { perf_evsel__sb_cb_t *cb; diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 4432bfe039fd..cf0b9b81c5aa 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -950,6 +950,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", + [PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore", }; static bool config_term_shrinked; @@ -970,6 +971,7 @@ config_term_avail(int term_type, struct parse_events_error *err) case PARSE_EVENTS__TERM_TYPE_CONFIG2: case PARSE_EVENTS__TERM_TYPE_NAME: case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: + case PARSE_EVENTS__TERM_TYPE_PERCORE: return true; default: if (!err) @@ -1061,6 +1063,14 @@ do { \ case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: CHECK_TYPE_VAL(NUM); break; + case PARSE_EVENTS__TERM_TYPE_PERCORE: + CHECK_TYPE_VAL(NUM); + if ((unsigned int)term->val.num > 1) { + err->str = strdup("expected 0 or 1"); + err->idx = term->err_val; + return -EINVAL; + } + break; default: err->str = strdup("unknown term"); err->idx = term->err_term; @@ -1199,6 +1209,10 @@ do { \ case PARSE_EVENTS__TERM_TYPE_DRV_CFG: ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str); break; + case PARSE_EVENTS__TERM_TYPE_PERCORE: + ADD_CONFIG_TERM(PERCORE, percore, + term->val.num ? true : false); + break; default: break; } @@ -1260,6 +1274,18 @@ int parse_events_add_tool(struct parse_events_state *parse_state, return add_event_tool(list, &parse_state->idx, tool_event); } +static bool config_term_percore(struct list_head *config_terms) +{ + struct perf_evsel_config_term *term; + + list_for_each_entry(term, config_terms, list) { + if (term->type == PERF_EVSEL__CONFIG_TERM_PERCORE) + return term->val.percore; + } + + return false; +} + int parse_events_add_pmu(struct parse_events_state *parse_state, struct list_head *list, char *name, struct list_head *head_config, @@ -1333,6 +1359,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, evsel->metric_name = info.metric_name; evsel->pmu_name = name; evsel->use_uncore_alias = use_uncore_alias; + evsel->percore = config_term_percore(&evsel->config_terms); } return evsel ? 0 : -ENOMEM; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index a052cd6ac63e..f7139e1a2fd3 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -75,6 +75,7 @@ enum { PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, PARSE_EVENTS__TERM_TYPE_OVERWRITE, PARSE_EVENTS__TERM_TYPE_DRV_CFG, + PARSE_EVENTS__TERM_TYPE_PERCORE, __PARSE_EVENTS__TERM_TYPE_NR, }; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index c54bfe88626c..ca6098874fe2 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -283,6 +283,7 @@ inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } +percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); } , { return ','; } "/" { BEGIN(INITIAL); return '/'; } {name_minus} { return str(yyscanner, PE_NAME); } |