aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/parse-events.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2012-06-11 13:08:07 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-06-19 12:06:20 -0400
commit0b668bc9a74ce1bd3b8c5fd93e8d85ed955e11fe (patch)
tree771dbfc4676c223d19c27127f1ad8518e3b9a8b0 /tools/perf/util/parse-events.c
parent27f18617b01dbbc928e9bd3731d1766222fb7e0d (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.c115
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
79static 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
89static 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
95static 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 */
112static 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
239static 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
247static 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
263const char *event_type(int type) 194const 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
382static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size) 296static 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)
970int print_hwcache_events(const char *event_glob) 884int 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