powerpc/perf_counter: Enable alternate PR/HV bits for POWER7
[linux-2.6-block.git] / tools / perf / util / parse-events.c
CommitLineData
8ad8db37
IM
1
2#include "../perf.h"
3#include "util.h"
4#include "parse-options.h"
5#include "parse-events.h"
6#include "exec_cmd.h"
a0055ae2 7#include "string.h"
8ad8db37 8
8326f44d
IM
9extern char *strcasestr(const char *haystack, const char *needle);
10
a21ca2ca 11int nr_counters;
8ad8db37 12
a21ca2ca 13struct perf_counter_attr attrs[MAX_COUNTERS];
8ad8db37
IM
14
15struct event_symbol {
9cffa8d5
PM
16 u8 type;
17 u64 config;
a21ca2ca 18 char *symbol;
74d5b588 19 char *alias;
8ad8db37
IM
20};
21
51e26842
JSR
22#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
23#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
a21ca2ca 24
8ad8db37 25static struct event_symbol event_symbols[] = {
74d5b588
JSR
26 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" },
27 { CHW(INSTRUCTIONS), "instructions", "" },
28 { CHW(CACHE_REFERENCES), "cache-references", "" },
29 { CHW(CACHE_MISSES), "cache-misses", "" },
30 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
31 { CHW(BRANCH_MISSES), "branch-misses", "" },
32 { CHW(BUS_CYCLES), "bus-cycles", "" },
33
34 { CSW(CPU_CLOCK), "cpu-clock", "" },
35 { CSW(TASK_CLOCK), "task-clock", "" },
c0c22dbf 36 { CSW(PAGE_FAULTS), "page-faults", "faults" },
74d5b588
JSR
37 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" },
38 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
39 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
40 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
8ad8db37
IM
41};
42
5242519b
IM
43#define __PERF_COUNTER_FIELD(config, name) \
44 ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
45
46#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
47#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
48#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
49#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
50
51static char *hw_event_names[] = {
8faf3b54 52 "cycles",
5242519b 53 "instructions",
8faf3b54
IM
54 "cache-references",
55 "cache-misses",
5242519b 56 "branches",
8faf3b54
IM
57 "branch-misses",
58 "bus-cycles",
5242519b
IM
59};
60
61static char *sw_event_names[] = {
44175b6f
IM
62 "cpu-clock-msecs",
63 "task-clock-msecs",
8faf3b54
IM
64 "page-faults",
65 "context-switches",
66 "CPU-migrations",
67 "minor-faults",
68 "major-faults",
5242519b
IM
69};
70
8326f44d
IM
71#define MAX_ALIASES 8
72
c0c22dbf 73static char *hw_cache[][MAX_ALIASES] = {
4418351f
JSR
74 { "L1-d$", "l1-d", "l1d", "L1-data", },
75 { "L1-i$", "l1-i", "l1i", "L1-instruction", },
e5c59547
JSR
76 { "LLC", "L2" },
77 { "dTLB", "d-tlb", "Data-TLB", },
78 { "iTLB", "i-tlb", "Instruction-TLB", },
79 { "branch", "branches", "bpu", "btb", "bpc", },
8326f44d
IM
80};
81
c0c22dbf 82static char *hw_cache_op[][MAX_ALIASES] = {
e5c59547
JSR
83 { "load", "loads", "read", },
84 { "store", "stores", "write", },
85 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
8326f44d
IM
86};
87
c0c22dbf 88static char *hw_cache_result[][MAX_ALIASES] = {
e5c59547
JSR
89 { "refs", "Reference", "ops", "access", },
90 { "misses", "miss", },
8326f44d
IM
91};
92
06813f6c
JSR
93#define C(x) PERF_COUNT_HW_CACHE_##x
94#define CACHE_READ (1 << C(OP_READ))
95#define CACHE_WRITE (1 << C(OP_WRITE))
96#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
97#define COP(x) (1 << x)
98
99/*
100 * cache operartion stat
101 * L1I : Read and prefetch only
102 * ITLB and BPU : Read-only
103 */
104static unsigned long hw_cache_stat[C(MAX)] = {
105 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
106 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
107 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
108 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
109 [C(ITLB)] = (CACHE_READ),
110 [C(BPU)] = (CACHE_READ),
111};
112
113static int is_cache_op_valid(u8 cache_type, u8 cache_op)
114{
115 if (hw_cache_stat[cache_type] & COP(cache_op))
116 return 1; /* valid */
117 else
118 return 0; /* invalid */
119}
120
e5c59547
JSR
121static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
122{
123 static char name[50];
124
125 if (cache_result) {
126 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
127 hw_cache_op[cache_op][0],
128 hw_cache_result[cache_result][0]);
129 } else {
130 sprintf(name, "%s-%s", hw_cache[cache_type][0],
131 hw_cache_op[cache_op][1]);
132 }
133
134 return name;
135}
136
a21ca2ca 137char *event_name(int counter)
5242519b 138{
9cffa8d5 139 u64 config = attrs[counter].config;
a21ca2ca 140 int type = attrs[counter].type;
5242519b
IM
141 static char buf[32];
142
a21ca2ca
IM
143 if (attrs[counter].type == PERF_TYPE_RAW) {
144 sprintf(buf, "raw 0x%llx", config);
5242519b
IM
145 return buf;
146 }
147
148 switch (type) {
149 case PERF_TYPE_HARDWARE:
f4dbfa8f 150 if (config < PERF_COUNT_HW_MAX)
a21ca2ca 151 return hw_event_names[config];
5242519b
IM
152 return "unknown-hardware";
153
8326f44d 154 case PERF_TYPE_HW_CACHE: {
9cffa8d5 155 u8 cache_type, cache_op, cache_result;
8326f44d
IM
156
157 cache_type = (config >> 0) & 0xff;
158 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
159 return "unknown-ext-hardware-cache-type";
160
161 cache_op = (config >> 8) & 0xff;
8faf3b54
IM
162 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
163 return "unknown-ext-hardware-cache-op";
8326f44d
IM
164
165 cache_result = (config >> 16) & 0xff;
8faf3b54
IM
166 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
167 return "unknown-ext-hardware-cache-result";
8326f44d 168
06813f6c
JSR
169 if (!is_cache_op_valid(cache_type, cache_op))
170 return "invalid-cache";
8326f44d 171
e5c59547 172 return event_cache_name(cache_type, cache_op, cache_result);
8326f44d
IM
173 }
174
5242519b 175 case PERF_TYPE_SOFTWARE:
f4dbfa8f 176 if (config < PERF_COUNT_SW_MAX)
a21ca2ca 177 return sw_event_names[config];
5242519b
IM
178 return "unknown-software";
179
180 default:
181 break;
182 }
183
184 return "unknown";
185}
186
8326f44d
IM
187static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size)
188{
189 int i, j;
190
191 for (i = 0; i < size; i++) {
192 for (j = 0; j < MAX_ALIASES; j++) {
193 if (!names[i][j])
194 break;
195 if (strcasestr(str, names[i][j]))
196 return i;
197 }
198 }
199
8953645f 200 return -1;
8326f44d
IM
201}
202
c0c22dbf
JSR
203static int
204parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
8326f44d 205{
8953645f 206 int cache_type = -1, cache_op = 0, cache_result = 0;
8326f44d
IM
207
208 cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX);
209 /*
210 * No fallback - if we cannot get a clear cache type
211 * then bail out:
212 */
213 if (cache_type == -1)
214 return -EINVAL;
215
216 cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
217 /*
218 * Fall back to reads:
219 */
8953645f
IM
220 if (cache_op == -1)
221 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
8326f44d 222
06813f6c
JSR
223 if (!is_cache_op_valid(cache_type, cache_op))
224 return -EINVAL;
225
8326f44d
IM
226 cache_result = parse_aliases(str, hw_cache_result,
227 PERF_COUNT_HW_CACHE_RESULT_MAX);
228 /*
229 * Fall back to accesses:
230 */
231 if (cache_result == -1)
232 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
233
234 attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
235 attr->type = PERF_TYPE_HW_CACHE;
236
237 return 0;
238}
239
74d5b588
JSR
240static int check_events(const char *str, unsigned int i)
241{
242 if (!strncmp(str, event_symbols[i].symbol,
243 strlen(event_symbols[i].symbol)))
244 return 1;
245
246 if (strlen(event_symbols[i].alias))
247 if (!strncmp(str, event_symbols[i].alias,
c0c22dbf 248 strlen(event_symbols[i].alias)))
74d5b588
JSR
249 return 1;
250 return 0;
251}
252
8ad8db37
IM
253/*
254 * Each event can have multiple symbolic names.
255 * Symbolic names are (almost) exactly matched.
256 */
8326f44d 257static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
8ad8db37 258{
9cffa8d5 259 u64 config, id;
8ad8db37
IM
260 int type;
261 unsigned int i;
a0055ae2 262 const char *sep, *pstr;
8ad8db37 263
a21ca2ca
IM
264 if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) {
265 attr->type = PERF_TYPE_RAW;
266 attr->config = config;
267
268 return 0;
269 }
8ad8db37 270
a0055ae2
ACM
271 pstr = str;
272 sep = strchr(pstr, ':');
273 if (sep) {
274 type = atoi(pstr);
275 pstr = sep + 1;
276 id = atoi(pstr);
277 sep = strchr(pstr, ':');
278 if (sep) {
279 pstr = sep + 1;
280 if (strchr(pstr, 'k'))
a21ca2ca 281 attr->exclude_user = 1;
a0055ae2 282 if (strchr(pstr, 'u'))
a21ca2ca 283 attr->exclude_kernel = 1;
a0055ae2 284 }
a21ca2ca
IM
285 attr->type = type;
286 attr->config = id;
287
288 return 0;
5242519b 289 }
8ad8db37
IM
290
291 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
74d5b588 292 if (check_events(str, i)) {
a21ca2ca
IM
293 attr->type = event_symbols[i].type;
294 attr->config = event_symbols[i].config;
295
296 return 0;
297 }
8ad8db37
IM
298 }
299
8326f44d 300 return parse_generic_hw_symbols(str, attr);
8ad8db37
IM
301}
302
303int parse_events(const struct option *opt, const char *str, int unset)
304{
a21ca2ca
IM
305 struct perf_counter_attr attr;
306 int ret;
8ad8db37 307
a21ca2ca 308 memset(&attr, 0, sizeof(attr));
8ad8db37
IM
309again:
310 if (nr_counters == MAX_COUNTERS)
311 return -1;
312
8326f44d 313 ret = parse_event_symbols(str, &attr);
a21ca2ca
IM
314 if (ret < 0)
315 return ret;
8ad8db37 316
a21ca2ca 317 attrs[nr_counters] = attr;
8ad8db37
IM
318 nr_counters++;
319
320 str = strstr(str, ",");
321 if (str) {
322 str++;
323 goto again;
324 }
325
326 return 0;
327}
328
86847b62
TG
329static const char * const event_type_descriptors[] = {
330 "",
331 "Hardware event",
332 "Software event",
333 "Tracepoint event",
334 "Hardware cache event",
335};
336
8ad8db37 337/*
86847b62 338 * Print the help text for the event symbols:
8ad8db37 339 */
86847b62 340void print_events(void)
8ad8db37 341{
86847b62
TG
342 struct event_symbol *syms = event_symbols;
343 unsigned int i, type, prev_type = -1;
74d5b588 344 char name[40];
8ad8db37 345
86847b62
TG
346 fprintf(stderr, "\n");
347 fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
8ad8db37 348
86847b62
TG
349 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
350 type = syms->type + 1;
351 if (type > ARRAY_SIZE(event_type_descriptors))
352 type = 0;
8ad8db37 353
86847b62
TG
354 if (type != prev_type)
355 fprintf(stderr, "\n");
8ad8db37 356
74d5b588
JSR
357 if (strlen(syms->alias))
358 sprintf(name, "%s OR %s", syms->symbol, syms->alias);
359 else
360 strcpy(name, syms->symbol);
361 fprintf(stderr, " %-40s [%s]\n", name,
86847b62 362 event_type_descriptors[type]);
8ad8db37 363
86847b62 364 prev_type = type;
8ad8db37
IM
365 }
366
86847b62 367 fprintf(stderr, "\n");
74d5b588 368 fprintf(stderr, " %-40s [raw hardware event descriptor]\n",
86847b62
TG
369 "rNNN");
370 fprintf(stderr, "\n");
371
372 exit(129);
8ad8db37 373}