diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-06-11 13:08:07 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-06-19 12:06:20 -0400 |
commit | 0b668bc9a74ce1bd3b8c5fd93e8d85ed955e11fe (patch) | |
tree | 771dbfc4676c223d19c27127f1ad8518e3b9a8b0 /tools/perf/util/parse-events.c | |
parent | 27f18617b01dbbc928e9bd3731d1766222fb7e0d (diff) |
perf tools: Reconstruct hw cache event with modifiers from perf_event_attr
[root@sandy ~]# perf record -a -e dTLB-load-misses:u usleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.486 MB perf.data (~21216 samples) ]
Before:
[root@sandy ~]# perf evlist
dTLB-load-misses
[root@sandy ~]#
After:
[root@sandy ~]# perf evlist
dTLB-load-misses:u
[root@sandy ~]#
Ditto for other tools.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-7x1b0e6jthkr93lfjzsuakk5@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 115 |
1 files changed, 15 insertions, 100 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 05dbc8b3c767..c8f8cf4a6920 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -74,51 +74,6 @@ static const char *sw_event_names[PERF_COUNT_SW_MAX] = { | |||
74 | "emulation-faults", | 74 | "emulation-faults", |
75 | }; | 75 | }; |
76 | 76 | ||
77 | #define MAX_ALIASES 8 | ||
78 | |||
79 | static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = { | ||
80 | { "L1-dcache", "l1-d", "l1d", "L1-data", }, | ||
81 | { "L1-icache", "l1-i", "l1i", "L1-instruction", }, | ||
82 | { "LLC", "L2", }, | ||
83 | { "dTLB", "d-tlb", "Data-TLB", }, | ||
84 | { "iTLB", "i-tlb", "Instruction-TLB", }, | ||
85 | { "branch", "branches", "bpu", "btb", "bpc", }, | ||
86 | { "node", }, | ||
87 | }; | ||
88 | |||
89 | static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = { | ||
90 | { "load", "loads", "read", }, | ||
91 | { "store", "stores", "write", }, | ||
92 | { "prefetch", "prefetches", "speculative-read", "speculative-load", }, | ||
93 | }; | ||
94 | |||
95 | static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] | ||
96 | [MAX_ALIASES] = { | ||
97 | { "refs", "Reference", "ops", "access", }, | ||
98 | { "misses", "miss", }, | ||
99 | }; | ||
100 | |||
101 | #define C(x) PERF_COUNT_HW_CACHE_##x | ||
102 | #define CACHE_READ (1 << C(OP_READ)) | ||
103 | #define CACHE_WRITE (1 << C(OP_WRITE)) | ||
104 | #define CACHE_PREFETCH (1 << C(OP_PREFETCH)) | ||
105 | #define COP(x) (1 << x) | ||
106 | |||
107 | /* | ||
108 | * cache operartion stat | ||
109 | * L1I : Read and prefetch only | ||
110 | * ITLB and BPU : Read-only | ||
111 | */ | ||
112 | static unsigned long hw_cache_stat[C(MAX)] = { | ||
113 | [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), | ||
114 | [C(L1I)] = (CACHE_READ | CACHE_PREFETCH), | ||
115 | [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), | ||
116 | [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), | ||
117 | [C(ITLB)] = (CACHE_READ), | ||
118 | [C(BPU)] = (CACHE_READ), | ||
119 | [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), | ||
120 | }; | ||
121 | |||
122 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ | 77 | #define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ |
123 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ | 78 | while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ |
124 | if (sys_dirent.d_type == DT_DIR && \ | 79 | if (sys_dirent.d_type == DT_DIR && \ |
@@ -236,30 +191,6 @@ static const char *tracepoint_id_to_name(u64 config) | |||
236 | return buf; | 191 | return buf; |
237 | } | 192 | } |
238 | 193 | ||
239 | static int is_cache_op_valid(u8 cache_type, u8 cache_op) | ||
240 | { | ||
241 | if (hw_cache_stat[cache_type] & COP(cache_op)) | ||
242 | return 1; /* valid */ | ||
243 | else | ||
244 | return 0; /* invalid */ | ||
245 | } | ||
246 | |||
247 | static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result) | ||
248 | { | ||
249 | static char name[50]; | ||
250 | |||
251 | if (cache_result) { | ||
252 | sprintf(name, "%s-%s-%s", hw_cache[cache_type][0], | ||
253 | hw_cache_op[cache_op][0], | ||
254 | hw_cache_result[cache_result][0]); | ||
255 | } else { | ||
256 | sprintf(name, "%s-%s", hw_cache[cache_type][0], | ||
257 | hw_cache_op[cache_op][1]); | ||
258 | } | ||
259 | |||
260 | return name; | ||
261 | } | ||
262 | |||
263 | const char *event_type(int type) | 194 | const char *event_type(int type) |
264 | { | 195 | { |
265 | switch (type) { | 196 | switch (type) { |
@@ -287,7 +218,7 @@ const char *event_name(struct perf_evsel *evsel) | |||
287 | u64 config = evsel->attr.config; | 218 | u64 config = evsel->attr.config; |
288 | int type = evsel->attr.type; | 219 | int type = evsel->attr.type; |
289 | 220 | ||
290 | if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) { | 221 | if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE) { |
291 | /* | 222 | /* |
292 | * XXX minimal fix, see comment on perf_evsen__name, this static buffer | 223 | * XXX minimal fix, see comment on perf_evsen__name, this static buffer |
293 | * will go away together with event_name in the next devel cycle. | 224 | * will go away together with event_name in the next devel cycle. |
@@ -316,26 +247,9 @@ const char *__event_name(int type, u64 config) | |||
316 | case PERF_TYPE_HARDWARE: | 247 | case PERF_TYPE_HARDWARE: |
317 | return __perf_evsel__hw_name(config); | 248 | return __perf_evsel__hw_name(config); |
318 | 249 | ||
319 | case PERF_TYPE_HW_CACHE: { | 250 | case PERF_TYPE_HW_CACHE: |
320 | u8 cache_type, cache_op, cache_result; | 251 | __perf_evsel__hw_cache_name(config, buf, sizeof(buf)); |
321 | 252 | return buf; | |
322 | cache_type = (config >> 0) & 0xff; | ||
323 | if (cache_type > PERF_COUNT_HW_CACHE_MAX) | ||
324 | return "unknown-ext-hardware-cache-type"; | ||
325 | |||
326 | cache_op = (config >> 8) & 0xff; | ||
327 | if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX) | ||
328 | return "unknown-ext-hardware-cache-op"; | ||
329 | |||
330 | cache_result = (config >> 16) & 0xff; | ||
331 | if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) | ||
332 | return "unknown-ext-hardware-cache-result"; | ||
333 | |||
334 | if (!is_cache_op_valid(cache_type, cache_op)) | ||
335 | return "invalid-cache"; | ||
336 | |||
337 | return event_cache_name(cache_type, cache_op, cache_result); | ||
338 | } | ||
339 | 253 | ||
340 | case PERF_TYPE_SOFTWARE: | 254 | case PERF_TYPE_SOFTWARE: |
341 | if (config < PERF_COUNT_SW_MAX && sw_event_names[config]) | 255 | if (config < PERF_COUNT_SW_MAX && sw_event_names[config]) |
@@ -379,13 +293,13 @@ static int add_event(struct list_head **_list, int *idx, | |||
379 | return 0; | 293 | return 0; |
380 | } | 294 | } |
381 | 295 | ||
382 | static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size) | 296 | static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) |
383 | { | 297 | { |
384 | int i, j; | 298 | int i, j; |
385 | int n, longest = -1; | 299 | int n, longest = -1; |
386 | 300 | ||
387 | for (i = 0; i < size; i++) { | 301 | for (i = 0; i < size; i++) { |
388 | for (j = 0; j < MAX_ALIASES && names[i][j]; j++) { | 302 | for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) { |
389 | n = strlen(names[i][j]); | 303 | n = strlen(names[i][j]); |
390 | if (n > longest && !strncasecmp(str, names[i][j], n)) | 304 | if (n > longest && !strncasecmp(str, names[i][j], n)) |
391 | longest = n; | 305 | longest = n; |
@@ -410,7 +324,7 @@ int parse_events_add_cache(struct list_head **list, int *idx, | |||
410 | * No fallback - if we cannot get a clear cache type | 324 | * No fallback - if we cannot get a clear cache type |
411 | * then bail out: | 325 | * then bail out: |
412 | */ | 326 | */ |
413 | cache_type = parse_aliases(type, hw_cache, | 327 | cache_type = parse_aliases(type, perf_evsel__hw_cache, |
414 | PERF_COUNT_HW_CACHE_MAX); | 328 | PERF_COUNT_HW_CACHE_MAX); |
415 | if (cache_type == -1) | 329 | if (cache_type == -1) |
416 | return -EINVAL; | 330 | return -EINVAL; |
@@ -423,18 +337,18 @@ int parse_events_add_cache(struct list_head **list, int *idx, | |||
423 | snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); | 337 | snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); |
424 | 338 | ||
425 | if (cache_op == -1) { | 339 | if (cache_op == -1) { |
426 | cache_op = parse_aliases(str, hw_cache_op, | 340 | cache_op = parse_aliases(str, perf_evsel__hw_cache_op, |
427 | PERF_COUNT_HW_CACHE_OP_MAX); | 341 | PERF_COUNT_HW_CACHE_OP_MAX); |
428 | if (cache_op >= 0) { | 342 | if (cache_op >= 0) { |
429 | if (!is_cache_op_valid(cache_type, cache_op)) | 343 | if (!perf_evsel__is_cache_op_valid(cache_type, cache_op)) |
430 | return -EINVAL; | 344 | return -EINVAL; |
431 | continue; | 345 | continue; |
432 | } | 346 | } |
433 | } | 347 | } |
434 | 348 | ||
435 | if (cache_result == -1) { | 349 | if (cache_result == -1) { |
436 | cache_result = parse_aliases(str, hw_cache_result, | 350 | cache_result = parse_aliases(str, perf_evsel__hw_cache_result, |
437 | PERF_COUNT_HW_CACHE_RESULT_MAX); | 351 | PERF_COUNT_HW_CACHE_RESULT_MAX); |
438 | if (cache_result >= 0) | 352 | if (cache_result >= 0) |
439 | continue; | 353 | continue; |
440 | } | 354 | } |
@@ -970,16 +884,17 @@ void print_events_type(u8 type) | |||
970 | int print_hwcache_events(const char *event_glob) | 884 | int print_hwcache_events(const char *event_glob) |
971 | { | 885 | { |
972 | unsigned int type, op, i, printed = 0; | 886 | unsigned int type, op, i, printed = 0; |
887 | char name[64]; | ||
973 | 888 | ||
974 | for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { | 889 | for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { |
975 | for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { | 890 | for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { |
976 | /* skip invalid cache type */ | 891 | /* skip invalid cache type */ |
977 | if (!is_cache_op_valid(type, op)) | 892 | if (!perf_evsel__is_cache_op_valid(type, op)) |
978 | continue; | 893 | continue; |
979 | 894 | ||
980 | for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { | 895 | for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { |
981 | char *name = event_cache_name(type, op, i); | 896 | __perf_evsel__hw_cache_type_op_res_name(type, op, i, |
982 | 897 | name, sizeof(name)); | |
983 | if (event_glob != NULL && !strglobmatch(name, event_glob)) | 898 | if (event_glob != NULL && !strglobmatch(name, event_glob)) |
984 | continue; | 899 | continue; |
985 | 900 | ||