diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/Documentation/perf-list.txt | 25 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 47 |
2 files changed, 54 insertions, 18 deletions
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index ce0735021473..28215306a78a 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -278,26 +278,33 @@ also be supplied. For example: perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ... -EVENT QUALIFIERS: +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/ + Sums up the event counts for all hardware threads in a core, e.g.: + perf stat -e cpu/event=0,umask=0x3,percore=1/ cpu: -Specifies the CPU to open the event upon. The value may be repeated to -specify opening the event on multiple CPUs: + Specifies a CPU or a range of CPUs to open the event upon. It may + also reference a PMU to copy the CPU mask from. The value may be + repeated to specify opening the event on multiple CPUs. + Example 1: to open the instructions event on CPUs 0 and 2, the + cycles event on CPUs 1 and 2: + perf stat -e instructions/cpu=0,cpu=2/,cycles/cpu=1-2/ -a sleep 1 - perf stat -e instructions/cpu=0,cpu=2/,cycles/cpu=1,cpu=2/ -a sleep 1 - perf stat -e data_read/cpu=0/,data_write/cpu=1/ -a sleep 1 + Example 2: to open the data_read uncore event on CPU 0 and the + data_write uncore event on CPU 1: + perf stat -e data_read/cpu=0/,data_write/cpu=1/ -a sleep 1 + Example 3: to open the software msr/tsc/ event only on the CPUs + matching those from the cpu_core PMU: + perf stat -e msr/tsc,cpu=cpu_core/ -a sleep 1 EVENT GROUPS ------------ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3fd6cc0c2794..a337e4d22ff2 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -187,10 +187,22 @@ static struct perf_cpu_map *get_config_cpu(const struct parse_events_terms *head list_for_each_entry(term, &head_terms->terms, list) { if (term->type_term == PARSE_EVENTS__TERM_TYPE_CPU) { - struct perf_cpu_map *cpu = perf_cpu_map__new_int(term->val.num); - - perf_cpu_map__merge(&cpus, cpu); - perf_cpu_map__put(cpu); + struct perf_cpu_map *term_cpus; + + if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { + term_cpus = perf_cpu_map__new_int(term->val.num); + } else { + struct perf_pmu *pmu = perf_pmus__find(term->val.str); + + if (pmu && perf_cpu_map__is_empty(pmu->cpus)) + term_cpus = pmu->is_core ? cpu_map__online() : NULL; + else if (pmu) + term_cpus = perf_cpu_map__get(pmu->cpus); + else + term_cpus = perf_cpu_map__new(term->val.str); + } + perf_cpu_map__merge(&cpus, term_cpus); + perf_cpu_map__put(term_cpus); } } @@ -1048,15 +1060,32 @@ do { \ return -EINVAL; } break; - case PARSE_EVENTS__TERM_TYPE_CPU: - CHECK_TYPE_VAL(NUM); - if (term->val.num >= (u64)cpu__max_present_cpu().cpu) { + case PARSE_EVENTS__TERM_TYPE_CPU: { + struct perf_cpu_map *map; + + if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { + if (term->val.num >= (u64)cpu__max_present_cpu().cpu) { + parse_events_error__handle(err, term->err_val, + strdup("too big"), + /*help=*/NULL); + return -EINVAL; + } + break; + } + assert(term->type_val == PARSE_EVENTS__TERM_TYPE_STR); + if (perf_pmus__find(term->val.str) != NULL) + break; + + map = perf_cpu_map__new(term->val.str); + if (!map) { parse_events_error__handle(err, term->err_val, - strdup("too big"), - NULL); + strdup("not a valid PMU or CPU number"), + /*help=*/NULL); return -EINVAL; } + perf_cpu_map__put(map); break; + } case PARSE_EVENTS__TERM_TYPE_DRV_CFG: case PARSE_EVENTS__TERM_TYPE_USER: case PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE: |
