aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--tools/perf/util/evsel.c104
-rw-r--r--tools/perf/util/evsel.h16
-rw-r--r--tools/perf/util/parse-events.c115
3 files changed, 134 insertions, 101 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index dab893804a14..47f1fe2feab8 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -128,6 +128,105 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
128 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); 128 return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
129} 129}
130 130
131const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
132 [PERF_EVSEL__MAX_ALIASES] = {
133 { "L1-dcache", "l1-d", "l1d", "L1-data", },
134 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
135 { "LLC", "L2", },
136 { "dTLB", "d-tlb", "Data-TLB", },
137 { "iTLB", "i-tlb", "Instruction-TLB", },
138 { "branch", "branches", "bpu", "btb", "bpc", },
139 { "node", },
140};
141
142const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
143 [PERF_EVSEL__MAX_ALIASES] = {
144 { "load", "loads", "read", },
145 { "store", "stores", "write", },
146 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
147};
148
149const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
150 [PERF_EVSEL__MAX_ALIASES] = {
151 { "refs", "Reference", "ops", "access", },
152 { "misses", "miss", },
153};
154
155#define C(x) PERF_COUNT_HW_CACHE_##x
156#define CACHE_READ (1 << C(OP_READ))
157#define CACHE_WRITE (1 << C(OP_WRITE))
158#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
159#define COP(x) (1 << x)
160
161/*
162 * cache operartion stat
163 * L1I : Read and prefetch only
164 * ITLB and BPU : Read-only
165 */
166static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
167 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
168 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
169 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
170 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
171 [C(ITLB)] = (CACHE_READ),
172 [C(BPU)] = (CACHE_READ),
173 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
174};
175
176bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
177{
178 if (perf_evsel__hw_cache_stat[type] & COP(op))
179 return true; /* valid */
180 else
181 return false; /* invalid */
182}
183
184int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
185 char *bf, size_t size)
186{
187 if (result) {
188 return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
189 perf_evsel__hw_cache_op[op][0],
190 perf_evsel__hw_cache_result[result][0]);
191 }
192
193 return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
194 perf_evsel__hw_cache_op[op][1]);
195}
196
197int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
198{
199 u8 op, result, type = (config >> 0) & 0xff;
200 const char *err = "unknown-ext-hardware-cache-type";
201
202 if (type > PERF_COUNT_HW_CACHE_MAX)
203 goto out_err;
204
205 op = (config >> 8) & 0xff;
206 err = "unknown-ext-hardware-cache-op";
207 if (op > PERF_COUNT_HW_CACHE_OP_MAX)
208 goto out_err;
209
210 result = (config >> 16) & 0xff;
211 err = "unknown-ext-hardware-cache-result";
212 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
213 goto out_err;
214
215 err = "invalid-cache";
216 if (!perf_evsel__is_cache_op_valid(type, op))
217 goto out_err;
218
219 return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
220out_err:
221 return scnprintf(bf, size, "%s", err);
222}
223
224static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
225{
226 int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
227 return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
228}
229
131int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size) 230int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size)
132{ 231{
133 int ret; 232 int ret;
@@ -140,6 +239,11 @@ int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size)
140 case PERF_TYPE_HARDWARE: 239 case PERF_TYPE_HARDWARE:
141 ret = perf_evsel__hw_name(evsel, bf, size); 240 ret = perf_evsel__hw_name(evsel, bf, size);
142 break; 241 break;
242
243 case PERF_TYPE_HW_CACHE:
244 ret = perf_evsel__hw_cache_name(evsel, bf, size);
245 break;
246
143 default: 247 default:
144 /* 248 /*
145 * FIXME 249 * FIXME
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4ba8b564e6f4..5bf946a05a6b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -83,7 +83,21 @@ void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts, 83 struct perf_record_opts *opts,
84 struct perf_evsel *first); 84 struct perf_evsel *first);
85 85
86const char* __perf_evsel__hw_name(u64 config); 86bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
87
88#define PERF_EVSEL__MAX_ALIASES 8
89
90extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
91 [PERF_EVSEL__MAX_ALIASES];
92extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
93 [PERF_EVSEL__MAX_ALIASES];
94const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
95 [PERF_EVSEL__MAX_ALIASES];
96int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
97 char *bf, size_t size);
98int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size);
99
100const char *__perf_evsel__hw_name(u64 config);
87int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size); 101int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size);
88 102
89int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 103int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
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