blob: ca8665e19c0d5aad44ea5c250f81b681ac2c6232 [file] [log] [blame]
Frederic Weisbecker1b290d62009-11-23 15:42:35 +01001#include "../../../include/linux/hw_breakpoint.h"
Ingo Molnar8ad8db32009-05-26 11:10:09 +02002#include "util.h"
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -03003#include "../perf.h"
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -02004#include "evlist.h"
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -02005#include "evsel.h"
Ingo Molnar8ad8db32009-05-26 11:10:09 +02006#include "parse-options.h"
7#include "parse-events.h"
8#include "exec_cmd.h"
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -03009#include "string.h"
Arnaldo Carvalho de Melo5aab6212010-03-25 19:59:00 -030010#include "symbol.h"
Jason Baron5beeded2009-07-21 14:16:29 -040011#include "cache.h"
Arjan van de Ven8755a8f2009-09-12 07:52:51 +020012#include "header.h"
Clark Williams549104f2009-11-08 09:03:07 -060013#include "debugfs.h"
Zheng Yanac20de6f2012-06-15 14:31:39 +080014#include "parse-events-bison.h"
Jiri Olsa89812fc2012-03-15 20:09:15 +010015#include "parse-events-flex.h"
Jiri Olsa5f537a22012-03-15 20:09:18 +010016#include "pmu.h"
Jiri Olsa89812fc2012-03-15 20:09:15 +010017
18#define MAX_NAME_LEN 100
Ingo Molnar8ad8db32009-05-26 11:10:09 +020019
Ingo Molnar8ad8db32009-05-26 11:10:09 +020020struct event_symbol {
Ingo Molnar83a09442009-08-15 12:26:57 +020021 u8 type;
22 u64 config;
23 const char *symbol;
24 const char *alias;
Ingo Molnar8ad8db32009-05-26 11:10:09 +020025};
26
Jiri Olsa82ba1f22012-05-21 09:12:50 +020027#ifdef PARSER_DEBUG
28extern int parse_events_debug;
29#endif
Zheng Yanac20de6f2012-06-15 14:31:39 +080030int parse_events_parse(void *data, void *scanner);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +020031
Jaswinder Singh Rajput51e26842009-06-22 16:43:14 +053032#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
33#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
Ingo Molnar8ad8db32009-05-26 11:10:09 +020034
Ingo Molnara21ca2c2009-06-06 09:58:57 +020035static struct event_symbol event_symbols[] = {
Ingo Molnar129c04c2011-04-29 14:41:28 +020036 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" },
37 { CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" },
38 { CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" },
39 { CHW(INSTRUCTIONS), "instructions", "" },
40 { CHW(CACHE_REFERENCES), "cache-references", "" },
41 { CHW(CACHE_MISSES), "cache-misses", "" },
42 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
43 { CHW(BRANCH_MISSES), "branch-misses", "" },
44 { CHW(BUS_CYCLES), "bus-cycles", "" },
Stephane Eranianf1ac18a2011-12-11 00:28:54 +010045 { CHW(REF_CPU_CYCLES), "ref-cycles", "" },
Ingo Molnara21ca2c2009-06-06 09:58:57 +020046
Ingo Molnar129c04c2011-04-29 14:41:28 +020047 { CSW(CPU_CLOCK), "cpu-clock", "" },
48 { CSW(TASK_CLOCK), "task-clock", "" },
49 { CSW(PAGE_FAULTS), "page-faults", "faults" },
50 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" },
51 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
52 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
53 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
54 { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" },
55 { CSW(EMULATION_FAULTS), "emulation-faults", "" },
Ingo Molnar8ad8db32009-05-26 11:10:09 +020056};
57
Ingo Molnarcdd6c482009-09-21 12:02:48 +020058#define __PERF_EVENT_FIELD(config, name) \
59 ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
Ingo Molnar52425192009-05-26 09:17:18 +020060
Ingo Molnar1fc570a2011-04-27 05:20:22 +020061#define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW)
Ingo Molnarcdd6c482009-09-21 12:02:48 +020062#define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG)
Ingo Molnar1fc570a2011-04-27 05:20:22 +020063#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
Ingo Molnarcdd6c482009-09-21 12:02:48 +020064#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
Ingo Molnar52425192009-05-26 09:17:18 +020065
Ingo Molnard3d1e862011-04-29 13:49:08 +020066static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
Ingo Molnar749141d2011-04-27 04:24:57 +020067 "cpu-clock",
68 "task-clock",
Ingo Molnar8faf3b52009-06-06 13:58:12 +020069 "page-faults",
70 "context-switches",
71 "CPU-migrations",
72 "minor-faults",
73 "major-faults",
Anton Blanchardf7d79862009-10-18 01:09:29 +000074 "alignment-faults",
75 "emulation-faults",
Ingo Molnar52425192009-05-26 09:17:18 +020076};
77
Ingo Molnar8326f442009-06-05 20:22:46 +020078#define MAX_ALIASES 8
79
Jiri Olsa01119192011-07-13 22:58:18 +020080static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
Anton Blanchard9590b7b2009-07-06 22:01:31 +100081 { "L1-dcache", "l1-d", "l1d", "L1-data", },
82 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
Jiri Olsa01119192011-07-13 22:58:18 +020083 { "LLC", "L2", },
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +053084 { "dTLB", "d-tlb", "Data-TLB", },
85 { "iTLB", "i-tlb", "Instruction-TLB", },
86 { "branch", "branches", "bpu", "btb", "bpc", },
Jiri Olsa01119192011-07-13 22:58:18 +020087 { "node", },
Ingo Molnar8326f442009-06-05 20:22:46 +020088};
89
Jiri Olsa01119192011-07-13 22:58:18 +020090static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +053091 { "load", "loads", "read", },
92 { "store", "stores", "write", },
93 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
Ingo Molnar8326f442009-06-05 20:22:46 +020094};
95
Jiri Olsa01119192011-07-13 22:58:18 +020096static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
97 [MAX_ALIASES] = {
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +053098 { "refs", "Reference", "ops", "access", },
99 { "misses", "miss", },
Ingo Molnar8326f442009-06-05 20:22:46 +0200100};
101
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530102#define C(x) PERF_COUNT_HW_CACHE_##x
103#define CACHE_READ (1 << C(OP_READ))
104#define CACHE_WRITE (1 << C(OP_WRITE))
105#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
106#define COP(x) (1 << x)
107
108/*
109 * cache operartion stat
110 * L1I : Read and prefetch only
111 * ITLB and BPU : Read-only
112 */
113static unsigned long hw_cache_stat[C(MAX)] = {
114 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
115 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
116 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
117 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
118 [C(ITLB)] = (CACHE_READ),
119 [C(BPU)] = (CACHE_READ),
Jiri Olsa01119192011-07-13 22:58:18 +0200120 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530121};
122
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300123#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \
Jason Baronf6bdafe2009-07-21 12:20:22 -0400124 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300125 if (sys_dirent.d_type == DT_DIR && \
Jason Baronf6bdafe2009-07-21 12:20:22 -0400126 (strcmp(sys_dirent.d_name, ".")) && \
127 (strcmp(sys_dirent.d_name, "..")))
128
Peter Zijlstraae07b632009-08-06 16:48:54 +0200129static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
130{
131 char evt_path[MAXPATHLEN];
132 int fd;
133
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200134 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
Peter Zijlstraae07b632009-08-06 16:48:54 +0200135 sys_dir->d_name, evt_dir->d_name);
136 fd = open(evt_path, O_RDONLY);
137 if (fd < 0)
138 return -EINVAL;
139 close(fd);
140
141 return 0;
142}
143
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300144#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \
Jason Baronf6bdafe2009-07-21 12:20:22 -0400145 while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300146 if (evt_dirent.d_type == DT_DIR && \
Jason Baronf6bdafe2009-07-21 12:20:22 -0400147 (strcmp(evt_dirent.d_name, ".")) && \
Peter Zijlstraae07b632009-08-06 16:48:54 +0200148 (strcmp(evt_dirent.d_name, "..")) && \
149 (!tp_event_has_id(&sys_dirent, &evt_dirent)))
Jason Baronf6bdafe2009-07-21 12:20:22 -0400150
Li Zefan270bbbe2009-09-17 16:34:51 +0800151#define MAX_EVENT_LENGTH 512
Jason Baronf6bdafe2009-07-21 12:20:22 -0400152
Jason Baronf6bdafe2009-07-21 12:20:22 -0400153
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200154struct tracepoint_path *tracepoint_id_to_path(u64 config)
Jason Baronf6bdafe2009-07-21 12:20:22 -0400155{
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200156 struct tracepoint_path *path = NULL;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400157 DIR *sys_dir, *evt_dir;
158 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
Stephane Eranian8aa8a7c2012-03-13 16:51:02 +0100159 char id_buf[24];
Eric Dumazet725b1362009-09-24 15:39:09 +0200160 int fd;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400161 u64 id;
162 char evt_path[MAXPATHLEN];
Eric Dumazet725b1362009-09-24 15:39:09 +0200163 char dir_path[MAXPATHLEN];
Jason Baronf6bdafe2009-07-21 12:20:22 -0400164
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200165 if (debugfs_valid_mountpoint(tracing_events_path))
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200166 return NULL;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400167
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200168 sys_dir = opendir(tracing_events_path);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400169 if (!sys_dir)
Eric Dumazet725b1362009-09-24 15:39:09 +0200170 return NULL;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400171
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300172 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
Eric Dumazet725b1362009-09-24 15:39:09 +0200173
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200174 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
Eric Dumazet725b1362009-09-24 15:39:09 +0200175 sys_dirent.d_name);
176 evt_dir = opendir(dir_path);
177 if (!evt_dir)
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300178 continue;
Eric Dumazet725b1362009-09-24 15:39:09 +0200179
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300180 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
Eric Dumazet725b1362009-09-24 15:39:09 +0200181
182 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
Jason Baronf6bdafe2009-07-21 12:20:22 -0400183 evt_dirent.d_name);
Eric Dumazet725b1362009-09-24 15:39:09 +0200184 fd = open(evt_path, O_RDONLY);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400185 if (fd < 0)
186 continue;
187 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
188 close(fd);
189 continue;
190 }
191 close(fd);
192 id = atoll(id_buf);
193 if (id == config) {
194 closedir(evt_dir);
195 closedir(sys_dir);
Julia Lawall59b4cae2009-12-06 10:16:30 +0100196 path = zalloc(sizeof(*path));
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200197 path->system = malloc(MAX_EVENT_LENGTH);
198 if (!path->system) {
199 free(path);
200 return NULL;
201 }
202 path->name = malloc(MAX_EVENT_LENGTH);
203 if (!path->name) {
204 free(path->system);
205 free(path);
206 return NULL;
207 }
208 strncpy(path->system, sys_dirent.d_name,
209 MAX_EVENT_LENGTH);
210 strncpy(path->name, evt_dirent.d_name,
211 MAX_EVENT_LENGTH);
212 return path;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400213 }
214 }
215 closedir(evt_dir);
216 }
217
Jason Baronf6bdafe2009-07-21 12:20:22 -0400218 closedir(sys_dir);
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200219 return NULL;
220}
221
222#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
223static const char *tracepoint_id_to_name(u64 config)
224{
225 static char buf[TP_PATH_LEN];
226 struct tracepoint_path *path;
227
228 path = tracepoint_id_to_path(config);
229 if (path) {
230 snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
231 free(path->name);
232 free(path->system);
233 free(path);
234 } else
235 snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
236
237 return buf;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400238}
239
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530240static int is_cache_op_valid(u8 cache_type, u8 cache_op)
241{
242 if (hw_cache_stat[cache_type] & COP(cache_op))
243 return 1; /* valid */
244 else
245 return 0; /* invalid */
246}
247
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +0530248static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
249{
250 static char name[50];
251
252 if (cache_result) {
253 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
254 hw_cache_op[cache_op][0],
255 hw_cache_result[cache_result][0]);
256 } else {
257 sprintf(name, "%s-%s", hw_cache[cache_type][0],
258 hw_cache_op[cache_op][1]);
259 }
260
261 return name;
262}
263
David Ahern1424dc92011-03-09 22:23:28 -0700264const char *event_type(int type)
265{
266 switch (type) {
267 case PERF_TYPE_HARDWARE:
268 return "hardware";
269
270 case PERF_TYPE_SOFTWARE:
271 return "software";
272
273 case PERF_TYPE_TRACEPOINT:
274 return "tracepoint";
275
276 case PERF_TYPE_HW_CACHE:
277 return "hardware-cache";
278
279 default:
280 break;
281 }
282
283 return "unknown";
284}
285
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200286const char *event_name(struct perf_evsel *evsel)
Ingo Molnar52425192009-05-26 09:17:18 +0200287{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200288 u64 config = evsel->attr.config;
289 int type = evsel->attr.type;
Peter Zijlstra8f18aec2009-08-06 19:40:28 +0200290
Arnaldo Carvalho de Meloc4104312012-05-25 16:38:11 -0300291 if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) {
292 /*
293 * XXX minimal fix, see comment on perf_evsen__name, this static buffer
294 * will go away together with event_name in the next devel cycle.
295 */
296 static char bf[128];
297 perf_evsel__name(evsel, bf, sizeof(bf));
298 return bf;
299 }
300
Stephane Eranianf0c55bc2011-02-16 15:10:01 +0200301 if (evsel->name)
302 return evsel->name;
303
Peter Zijlstra8f18aec2009-08-06 19:40:28 +0200304 return __event_name(type, config);
305}
306
Ingo Molnar83a09442009-08-15 12:26:57 +0200307const char *__event_name(int type, u64 config)
Peter Zijlstra8f18aec2009-08-06 19:40:28 +0200308{
Ingo Molnar52425192009-05-26 09:17:18 +0200309 static char buf[32];
310
Peter Zijlstra8f18aec2009-08-06 19:40:28 +0200311 if (type == PERF_TYPE_RAW) {
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200312 sprintf(buf, "raw 0x%" PRIx64, config);
Ingo Molnar52425192009-05-26 09:17:18 +0200313 return buf;
314 }
315
316 switch (type) {
317 case PERF_TYPE_HARDWARE:
Arnaldo Carvalho de Meloc4104312012-05-25 16:38:11 -0300318 return __perf_evsel__hw_name(config);
Ingo Molnar52425192009-05-26 09:17:18 +0200319
Ingo Molnar8326f442009-06-05 20:22:46 +0200320 case PERF_TYPE_HW_CACHE: {
Paul Mackerras9cffa8d2009-06-19 22:21:42 +1000321 u8 cache_type, cache_op, cache_result;
Ingo Molnar8326f442009-06-05 20:22:46 +0200322
323 cache_type = (config >> 0) & 0xff;
324 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
325 return "unknown-ext-hardware-cache-type";
326
327 cache_op = (config >> 8) & 0xff;
Ingo Molnar8faf3b52009-06-06 13:58:12 +0200328 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
329 return "unknown-ext-hardware-cache-op";
Ingo Molnar8326f442009-06-05 20:22:46 +0200330
331 cache_result = (config >> 16) & 0xff;
Ingo Molnar8faf3b52009-06-06 13:58:12 +0200332 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
333 return "unknown-ext-hardware-cache-result";
Ingo Molnar8326f442009-06-05 20:22:46 +0200334
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530335 if (!is_cache_op_valid(cache_type, cache_op))
336 return "invalid-cache";
Ingo Molnar8326f442009-06-05 20:22:46 +0200337
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +0530338 return event_cache_name(cache_type, cache_op, cache_result);
Ingo Molnar8326f442009-06-05 20:22:46 +0200339 }
340
Ingo Molnar52425192009-05-26 09:17:18 +0200341 case PERF_TYPE_SOFTWARE:
Ingo Molnar1fc570a2011-04-27 05:20:22 +0200342 if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200343 return sw_event_names[config];
Ingo Molnar52425192009-05-26 09:17:18 +0200344 return "unknown-software";
345
Jason Baronf6bdafe2009-07-21 12:20:22 -0400346 case PERF_TYPE_TRACEPOINT:
347 return tracepoint_id_to_name(config);
348
Ingo Molnar52425192009-05-26 09:17:18 +0200349 default:
350 break;
351 }
352
353 return "unknown";
354}
355
Jiri Olsab847cbd2012-05-21 09:12:51 +0200356static int add_event(struct list_head **_list, int *idx,
Jiri Olsa89812fc2012-03-15 20:09:15 +0100357 struct perf_event_attr *attr, char *name)
358{
359 struct perf_evsel *evsel;
Jiri Olsab847cbd2012-05-21 09:12:51 +0200360 struct list_head *list = *_list;
361
362 if (!list) {
363 list = malloc(sizeof(*list));
364 if (!list)
365 return -ENOMEM;
366 INIT_LIST_HEAD(list);
367 }
Jiri Olsa89812fc2012-03-15 20:09:15 +0100368
369 event_attr_init(attr);
370
371 evsel = perf_evsel__new(attr, (*idx)++);
Jiri Olsab847cbd2012-05-21 09:12:51 +0200372 if (!evsel) {
373 free(list);
Jiri Olsa89812fc2012-03-15 20:09:15 +0100374 return -ENOMEM;
Jiri Olsab847cbd2012-05-21 09:12:51 +0200375 }
Jiri Olsa89812fc2012-03-15 20:09:15 +0100376
377 evsel->name = strdup(name);
Jiri Olsab847cbd2012-05-21 09:12:51 +0200378 list_add_tail(&evsel->node, list);
379 *_list = list;
Jiri Olsa89812fc2012-03-15 20:09:15 +0100380 return 0;
381}
382
383static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size)
Ingo Molnar8326f442009-06-05 20:22:46 +0200384{
385 int i, j;
Paul Mackerras61c45982009-07-01 13:04:34 +1000386 int n, longest = -1;
Ingo Molnar8326f442009-06-05 20:22:46 +0200387
388 for (i = 0; i < size; i++) {
Paul Mackerras61c45982009-07-01 13:04:34 +1000389 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
390 n = strlen(names[i][j]);
Jiri Olsa89812fc2012-03-15 20:09:15 +0100391 if (n > longest && !strncasecmp(str, names[i][j], n))
Paul Mackerras61c45982009-07-01 13:04:34 +1000392 longest = n;
393 }
Jiri Olsa89812fc2012-03-15 20:09:15 +0100394 if (longest > 0)
Paul Mackerras61c45982009-07-01 13:04:34 +1000395 return i;
Ingo Molnar8326f442009-06-05 20:22:46 +0200396 }
397
Ingo Molnar89536452009-06-06 21:04:17 +0200398 return -1;
Ingo Molnar8326f442009-06-05 20:22:46 +0200399}
400
Jiri Olsab847cbd2012-05-21 09:12:51 +0200401int parse_events_add_cache(struct list_head **list, int *idx,
Jiri Olsa89812fc2012-03-15 20:09:15 +0100402 char *type, char *op_result1, char *op_result2)
Ingo Molnar8326f442009-06-05 20:22:46 +0200403{
Jiri Olsa89812fc2012-03-15 20:09:15 +0100404 struct perf_event_attr attr;
405 char name[MAX_NAME_LEN];
Paul Mackerras61c45982009-07-01 13:04:34 +1000406 int cache_type = -1, cache_op = -1, cache_result = -1;
Jiri Olsa89812fc2012-03-15 20:09:15 +0100407 char *op_result[2] = { op_result1, op_result2 };
408 int i, n;
Ingo Molnar8326f442009-06-05 20:22:46 +0200409
Ingo Molnar8326f442009-06-05 20:22:46 +0200410 /*
411 * No fallback - if we cannot get a clear cache type
412 * then bail out:
413 */
Jiri Olsa89812fc2012-03-15 20:09:15 +0100414 cache_type = parse_aliases(type, hw_cache,
415 PERF_COUNT_HW_CACHE_MAX);
Ingo Molnar8326f442009-06-05 20:22:46 +0200416 if (cache_type == -1)
Jiri Olsa89812fc2012-03-15 20:09:15 +0100417 return -EINVAL;
Ingo Molnar8326f442009-06-05 20:22:46 +0200418
Jiri Olsa89812fc2012-03-15 20:09:15 +0100419 n = snprintf(name, MAX_NAME_LEN, "%s", type);
420
421 for (i = 0; (i < 2) && (op_result[i]); i++) {
422 char *str = op_result[i];
423
424 snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);
Paul Mackerras61c45982009-07-01 13:04:34 +1000425
426 if (cache_op == -1) {
Jiri Olsa89812fc2012-03-15 20:09:15 +0100427 cache_op = parse_aliases(str, hw_cache_op,
428 PERF_COUNT_HW_CACHE_OP_MAX);
Paul Mackerras61c45982009-07-01 13:04:34 +1000429 if (cache_op >= 0) {
430 if (!is_cache_op_valid(cache_type, cache_op))
Jiri Olsa89812fc2012-03-15 20:09:15 +0100431 return -EINVAL;
Paul Mackerras61c45982009-07-01 13:04:34 +1000432 continue;
433 }
434 }
435
436 if (cache_result == -1) {
Jiri Olsa89812fc2012-03-15 20:09:15 +0100437 cache_result = parse_aliases(str, hw_cache_result,
Paul Mackerras61c45982009-07-01 13:04:34 +1000438 PERF_COUNT_HW_CACHE_RESULT_MAX);
439 if (cache_result >= 0)
440 continue;
441 }
Paul Mackerras61c45982009-07-01 13:04:34 +1000442 }
443
Ingo Molnar8326f442009-06-05 20:22:46 +0200444 /*
445 * Fall back to reads:
446 */
Ingo Molnar89536452009-06-06 21:04:17 +0200447 if (cache_op == -1)
448 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
Ingo Molnar8326f442009-06-05 20:22:46 +0200449
Ingo Molnar8326f442009-06-05 20:22:46 +0200450 /*
451 * Fall back to accesses:
452 */
453 if (cache_result == -1)
454 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
455
Jiri Olsa89812fc2012-03-15 20:09:15 +0100456 memset(&attr, 0, sizeof(attr));
457 attr.config = cache_type | (cache_op << 8) | (cache_result << 16);
458 attr.type = PERF_TYPE_HW_CACHE;
459 return add_event(list, idx, &attr, name);
Ingo Molnar8326f442009-06-05 20:22:46 +0200460}
461
Jiri Olsab847cbd2012-05-21 09:12:51 +0200462static int add_tracepoint(struct list_head **list, int *idx,
Jiri Olsa89812fc2012-03-15 20:09:15 +0100463 char *sys_name, char *evt_name)
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200464{
Jiri Olsa89812fc2012-03-15 20:09:15 +0100465 struct perf_event_attr attr;
466 char name[MAX_NAME_LEN];
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200467 char evt_path[MAXPATHLEN];
468 char id_buf[4];
469 u64 id;
470 int fd;
471
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200472 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200473 sys_name, evt_name);
474
475 fd = open(evt_path, O_RDONLY);
476 if (fd < 0)
Jiri Olsa89812fc2012-03-15 20:09:15 +0100477 return -1;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200478
479 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
480 close(fd);
Jiri Olsa89812fc2012-03-15 20:09:15 +0100481 return -1;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200482 }
483
484 close(fd);
485 id = atoll(id_buf);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200486
Jiri Olsa89812fc2012-03-15 20:09:15 +0100487 memset(&attr, 0, sizeof(attr));
488 attr.config = id;
489 attr.type = PERF_TYPE_TRACEPOINT;
490 attr.sample_type |= PERF_SAMPLE_RAW;
491 attr.sample_type |= PERF_SAMPLE_TIME;
492 attr.sample_type |= PERF_SAMPLE_CPU;
493 attr.sample_period = 1;
Stephane Eranian5710fca2010-04-21 18:06:01 +0200494
Jiri Olsa89812fc2012-03-15 20:09:15 +0100495 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name);
496 return add_event(list, idx, &attr, name);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200497}
498
Jiri Olsab847cbd2012-05-21 09:12:51 +0200499static int add_tracepoint_multi(struct list_head **list, int *idx,
Jiri Olsa89812fc2012-03-15 20:09:15 +0100500 char *sys_name, char *evt_name)
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200501{
502 char evt_path[MAXPATHLEN];
503 struct dirent *evt_ent;
504 DIR *evt_dir;
Jiri Olsa89812fc2012-03-15 20:09:15 +0100505 int ret = 0;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200506
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200507 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200508 evt_dir = opendir(evt_path);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200509 if (!evt_dir) {
510 perror("Can't open event dir");
Jiri Olsa89812fc2012-03-15 20:09:15 +0100511 return -1;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200512 }
513
Jiri Olsa89812fc2012-03-15 20:09:15 +0100514 while (!ret && (evt_ent = readdir(evt_dir))) {
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200515 if (!strcmp(evt_ent->d_name, ".")
516 || !strcmp(evt_ent->d_name, "..")
517 || !strcmp(evt_ent->d_name, "enable")
518 || !strcmp(evt_ent->d_name, "filter"))
519 continue;
520
Jiri Olsa89812fc2012-03-15 20:09:15 +0100521 if (!strglobmatch(evt_ent->d_name, evt_name))
Masami Hiramatsufb1d2ed2010-01-05 17:47:17 -0500522 continue;
523
Jiri Olsa89812fc2012-03-15 20:09:15 +0100524 ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200525 }
526
Jiri Olsa89812fc2012-03-15 20:09:15 +0100527 return ret;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200528}
529
Jiri Olsab847cbd2012-05-21 09:12:51 +0200530int parse_events_add_tracepoint(struct list_head **list, int *idx,
Jiri Olsa89812fc2012-03-15 20:09:15 +0100531 char *sys, char *event)
Jason Baronf6bdafe2009-07-21 12:20:22 -0400532{
Jiri Olsa89812fc2012-03-15 20:09:15 +0100533 int ret;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400534
Jiri Olsa89812fc2012-03-15 20:09:15 +0100535 ret = debugfs_valid_mountpoint(tracing_events_path);
536 if (ret)
537 return ret;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400538
Jiri Olsa89812fc2012-03-15 20:09:15 +0100539 return strpbrk(event, "*?") ?
540 add_tracepoint_multi(list, idx, sys, event) :
541 add_tracepoint(list, idx, sys, event);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400542}
543
Jiri Olsa89812fc2012-03-15 20:09:15 +0100544static int
545parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100546{
547 int i;
548
549 for (i = 0; i < 3; i++) {
Jiri Olsa89812fc2012-03-15 20:09:15 +0100550 if (!type || !type[i])
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100551 break;
552
553 switch (type[i]) {
554 case 'r':
555 attr->bp_type |= HW_BREAKPOINT_R;
556 break;
557 case 'w':
558 attr->bp_type |= HW_BREAKPOINT_W;
559 break;
560 case 'x':
561 attr->bp_type |= HW_BREAKPOINT_X;
562 break;
563 default:
Jiri Olsa89812fc2012-03-15 20:09:15 +0100564 return -EINVAL;
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100565 }
566 }
Jiri Olsa89812fc2012-03-15 20:09:15 +0100567
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100568 if (!attr->bp_type) /* Default */
569 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
570
Jiri Olsa89812fc2012-03-15 20:09:15 +0100571 return 0;
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100572}
573
Jiri Olsab847cbd2012-05-21 09:12:51 +0200574int parse_events_add_breakpoint(struct list_head **list, int *idx,
Jiri Olsa89812fc2012-03-15 20:09:15 +0100575 void *ptr, char *type)
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100576{
Jiri Olsa89812fc2012-03-15 20:09:15 +0100577 struct perf_event_attr attr;
578 char name[MAX_NAME_LEN];
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100579
Jiri Olsa89812fc2012-03-15 20:09:15 +0100580 memset(&attr, 0, sizeof(attr));
Jiri Olsa9fafd982012-03-20 19:15:39 +0100581 attr.bp_addr = (unsigned long) ptr;
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100582
Jiri Olsa89812fc2012-03-15 20:09:15 +0100583 if (parse_breakpoint_type(type, &attr))
584 return -EINVAL;
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100585
Frederic Weisbeckeraa59a482010-06-24 21:36:19 +0200586 /*
587 * We should find a nice way to override the access length
588 * Provide some defaults for now
589 */
Jiri Olsa89812fc2012-03-15 20:09:15 +0100590 if (attr.bp_type == HW_BREAKPOINT_X)
591 attr.bp_len = sizeof(long);
Frederic Weisbeckeraa59a482010-06-24 21:36:19 +0200592 else
Jiri Olsa89812fc2012-03-15 20:09:15 +0100593 attr.bp_len = HW_BREAKPOINT_LEN_4;
Frederic Weisbeckeraa59a482010-06-24 21:36:19 +0200594
Jiri Olsa89812fc2012-03-15 20:09:15 +0100595 attr.type = PERF_TYPE_BREAKPOINT;
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100596
Jiri Olsa89812fc2012-03-15 20:09:15 +0100597 snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw");
598 return add_event(list, idx, &attr, name);
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100599}
600
Jiri Olsa8f707d82012-03-15 20:09:16 +0100601static int config_term(struct perf_event_attr *attr,
602 struct parse_events__term *term)
603{
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200604#define CHECK_TYPE_VAL(type) \
605do { \
606 if (PARSE_EVENTS__TERM_TYPE_ ## type != term->type_val) \
607 return -EINVAL; \
608} while (0)
609
610 switch (term->type_term) {
Jiri Olsa8f707d82012-03-15 20:09:16 +0100611 case PARSE_EVENTS__TERM_TYPE_CONFIG:
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200612 CHECK_TYPE_VAL(NUM);
Jiri Olsa8f707d82012-03-15 20:09:16 +0100613 attr->config = term->val.num;
614 break;
615 case PARSE_EVENTS__TERM_TYPE_CONFIG1:
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200616 CHECK_TYPE_VAL(NUM);
Jiri Olsa8f707d82012-03-15 20:09:16 +0100617 attr->config1 = term->val.num;
618 break;
619 case PARSE_EVENTS__TERM_TYPE_CONFIG2:
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200620 CHECK_TYPE_VAL(NUM);
Jiri Olsa8f707d82012-03-15 20:09:16 +0100621 attr->config2 = term->val.num;
622 break;
623 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200624 CHECK_TYPE_VAL(NUM);
Jiri Olsa8f707d82012-03-15 20:09:16 +0100625 attr->sample_period = term->val.num;
626 break;
627 case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
628 /*
629 * TODO uncomment when the field is available
630 * attr->branch_sample_type = term->val.num;
631 */
632 break;
Jiri Olsa6b5fc392012-05-21 09:12:53 +0200633 case PARSE_EVENTS__TERM_TYPE_NAME:
634 CHECK_TYPE_VAL(STR);
635 break;
Jiri Olsa8f707d82012-03-15 20:09:16 +0100636 default:
637 return -EINVAL;
638 }
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200639
Jiri Olsa8f707d82012-03-15 20:09:16 +0100640 return 0;
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200641#undef CHECK_TYPE_VAL
Jiri Olsa8f707d82012-03-15 20:09:16 +0100642}
643
644static int config_attr(struct perf_event_attr *attr,
645 struct list_head *head, int fail)
646{
647 struct parse_events__term *term;
648
649 list_for_each_entry(term, head, list)
650 if (config_term(attr, term) && fail)
651 return -EINVAL;
652
653 return 0;
654}
655
Jiri Olsab847cbd2012-05-21 09:12:51 +0200656int parse_events_add_numeric(struct list_head **list, int *idx,
Jiri Olsa8f707d82012-03-15 20:09:16 +0100657 unsigned long type, unsigned long config,
658 struct list_head *head_config)
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530659{
Jiri Olsa89812fc2012-03-15 20:09:15 +0100660 struct perf_event_attr attr;
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530661
Jiri Olsa89812fc2012-03-15 20:09:15 +0100662 memset(&attr, 0, sizeof(attr));
663 attr.type = type;
664 attr.config = config;
Jiri Olsa8f707d82012-03-15 20:09:16 +0100665
666 if (head_config &&
667 config_attr(&attr, head_config, 1))
668 return -EINVAL;
669
Jiri Olsa89812fc2012-03-15 20:09:15 +0100670 return add_event(list, idx, &attr,
671 (char *) __event_name(type, config));
Paul Mackerras61c45982009-07-01 13:04:34 +1000672}
673
Jiri Olsa6b5fc392012-05-21 09:12:53 +0200674static int parse_events__is_name_term(struct parse_events__term *term)
675{
676 return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
677}
678
679static char *pmu_event_name(struct perf_event_attr *attr,
680 struct list_head *head_terms)
681{
682 struct parse_events__term *term;
683
684 list_for_each_entry(term, head_terms, list)
685 if (parse_events__is_name_term(term))
686 return term->val.str;
687
688 return (char *) __event_name(PERF_TYPE_RAW, attr->config);
689}
690
Jiri Olsab847cbd2012-05-21 09:12:51 +0200691int parse_events_add_pmu(struct list_head **list, int *idx,
Jiri Olsa5f537a22012-03-15 20:09:18 +0100692 char *name, struct list_head *head_config)
693{
694 struct perf_event_attr attr;
695 struct perf_pmu *pmu;
696
697 pmu = perf_pmu__find(name);
698 if (!pmu)
699 return -EINVAL;
700
701 memset(&attr, 0, sizeof(attr));
702
703 /*
704 * Configure hardcoded terms first, no need to check
705 * return value when called with fail == 0 ;)
706 */
707 config_attr(&attr, head_config, 0);
708
709 if (perf_pmu__config(pmu, &attr, head_config))
710 return -EINVAL;
711
Jiri Olsa6b5fc392012-05-21 09:12:53 +0200712 return add_event(list, idx, &attr,
713 pmu_event_name(&attr, head_config));
Jiri Olsa5f537a22012-03-15 20:09:18 +0100714}
715
Jiri Olsa5d7be902012-03-20 19:15:40 +0100716void parse_events_update_lists(struct list_head *list_event,
717 struct list_head *list_all)
718{
719 /*
720 * Called for single event definition. Update the
721 * 'all event' list, and reinit the 'signle event'
722 * list, for next event definition.
723 */
724 list_splice_tail(list_event, list_all);
Jiri Olsab847cbd2012-05-21 09:12:51 +0200725 free(list_event);
Jiri Olsa5d7be902012-03-20 19:15:40 +0100726}
727
Jiri Olsa89812fc2012-03-15 20:09:15 +0100728int parse_events_modifier(struct list_head *list, char *str)
Paul Mackerras61c45982009-07-01 13:04:34 +1000729{
Jiri Olsa89812fc2012-03-15 20:09:15 +0100730 struct perf_evsel *evsel;
Joerg Roedel99320cc2012-01-04 17:54:19 +0100731 int exclude = 0, exclude_GH = 0;
732 int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0;
Paul Mackerras61c45982009-07-01 13:04:34 +1000733
Jiri Olsa89812fc2012-03-15 20:09:15 +0100734 if (str == NULL)
Paul Mackerras61c45982009-07-01 13:04:34 +1000735 return 0;
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200736
Paul Mackerras61c45982009-07-01 13:04:34 +1000737 while (*str) {
Peter Zijlstraab608342010-04-08 23:03:20 +0200738 if (*str == 'u') {
739 if (!exclude)
740 exclude = eu = ek = eh = 1;
Paul Mackerras61c45982009-07-01 13:04:34 +1000741 eu = 0;
Peter Zijlstraab608342010-04-08 23:03:20 +0200742 } else if (*str == 'k') {
743 if (!exclude)
744 exclude = eu = ek = eh = 1;
Paul Mackerras61c45982009-07-01 13:04:34 +1000745 ek = 0;
Peter Zijlstraab608342010-04-08 23:03:20 +0200746 } else if (*str == 'h') {
747 if (!exclude)
748 exclude = eu = ek = eh = 1;
Paul Mackerras61c45982009-07-01 13:04:34 +1000749 eh = 0;
Joerg Roedel99320cc2012-01-04 17:54:19 +0100750 } else if (*str == 'G') {
751 if (!exclude_GH)
752 exclude_GH = eG = eH = 1;
753 eG = 0;
754 } else if (*str == 'H') {
755 if (!exclude_GH)
756 exclude_GH = eG = eH = 1;
757 eH = 0;
Peter Zijlstraab608342010-04-08 23:03:20 +0200758 } else if (*str == 'p') {
759 precise++;
760 } else
Paul Mackerras61c45982009-07-01 13:04:34 +1000761 break;
Peter Zijlstraab608342010-04-08 23:03:20 +0200762
Paul Mackerras61c45982009-07-01 13:04:34 +1000763 ++str;
764 }
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200765
Jiri Olsa89812fc2012-03-15 20:09:15 +0100766 /*
767 * precise ip:
768 *
769 * 0 - SAMPLE_IP can have arbitrary skid
770 * 1 - SAMPLE_IP must have constant skid
771 * 2 - SAMPLE_IP requested to have 0 skid
772 * 3 - SAMPLE_IP must have 0 skid
773 *
774 * See also PERF_RECORD_MISC_EXACT_IP
775 */
776 if (precise > 3)
777 return -EINVAL;
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200778
Jiri Olsa89812fc2012-03-15 20:09:15 +0100779 list_for_each_entry(evsel, list, node) {
780 evsel->attr.exclude_user = eu;
781 evsel->attr.exclude_kernel = ek;
782 evsel->attr.exclude_hv = eh;
783 evsel->attr.precise_ip = precise;
784 evsel->attr.exclude_host = eH;
785 evsel->attr.exclude_guest = eG;
786 }
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200787
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530788 return 0;
789}
790
Zheng Yanac20de6f2012-06-15 14:31:39 +0800791static int parse_events__scanner(const char *str, void *data)
792{
793 YY_BUFFER_STATE buffer;
794 void *scanner;
795 int ret;
796
797 ret = parse_events_lex_init(&scanner);
798 if (ret)
799 return ret;
800
801 buffer = parse_events__scan_string(str, scanner);
802
803#ifdef PARSER_DEBUG
804 parse_events_debug = 1;
805#endif
806 ret = parse_events_parse(data, scanner);
807
808 parse_events__flush_buffer(buffer, scanner);
809 parse_events__delete_buffer(buffer, scanner);
810 parse_events_lex_destroy(scanner);
811 return ret;
812}
813
Jiri Olsa89812fc2012-03-15 20:09:15 +0100814int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200815{
Jiri Olsa46010ab2012-06-15 14:31:38 +0800816 struct parse_events_data__events data = {
817 .list = LIST_HEAD_INIT(data.list),
818 .idx = evlist->nr_entries,
819 };
Jiri Olsa46010ab2012-06-15 14:31:38 +0800820 int ret;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200821
Zheng Yanac20de6f2012-06-15 14:31:39 +0800822 ret = parse_events__scanner(str, &data);
Jiri Olsa89812fc2012-03-15 20:09:15 +0100823 if (!ret) {
Jiri Olsa46010ab2012-06-15 14:31:38 +0800824 int entries = data.idx - evlist->nr_entries;
825 perf_evlist__splice_list_tail(evlist, &data.list, entries);
Jiri Olsa89812fc2012-03-15 20:09:15 +0100826 return 0;
827 }
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200828
Jiri Olsa5d7be902012-03-20 19:15:40 +0100829 /*
830 * There are 2 users - builtin-record and builtin-test objects.
831 * Both call perf_evlist__delete in case of error, so we dont
832 * need to bother.
833 */
Jiri Olsa89812fc2012-03-15 20:09:15 +0100834 fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
Marti Raudsepp85df6f62009-10-27 00:33:04 +0000835 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200836 return ret;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200837}
838
Jiri Olsaf120f9d2011-07-14 11:25:32 +0200839int parse_events_option(const struct option *opt, const char *str,
840 int unset __used)
841{
842 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
843 return parse_events(evlist, str, unset);
844}
845
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200846int parse_filter(const struct option *opt, const char *str,
Li Zefanc171b552009-10-15 11:22:07 +0800847 int unset __used)
848{
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200849 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200850 struct perf_evsel *last = NULL;
Li Zefanc171b552009-10-15 11:22:07 +0800851
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200852 if (evlist->nr_entries > 0)
853 last = list_entry(evlist->entries.prev, struct perf_evsel, node);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200854
855 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
Li Zefanc171b552009-10-15 11:22:07 +0800856 fprintf(stderr,
857 "-F option should follow a -e tracepoint option\n");
858 return -1;
859 }
860
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200861 last->filter = strdup(str);
862 if (last->filter == NULL) {
Li Zefanc171b552009-10-15 11:22:07 +0800863 fprintf(stderr, "not enough memory to hold filter string\n");
864 return -1;
865 }
Li Zefanc171b552009-10-15 11:22:07 +0800866
867 return 0;
868}
869
Thomas Gleixner86847b62009-06-06 12:24:17 +0200870static const char * const event_type_descriptors[] = {
Thomas Gleixner86847b62009-06-06 12:24:17 +0200871 "Hardware event",
872 "Software event",
873 "Tracepoint event",
874 "Hardware cache event",
Liming Wang41bdcb22009-12-29 16:37:07 +0800875 "Raw hardware event descriptor",
876 "Hardware breakpoint",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200877};
878
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200879/*
Jason Baronf6bdafe2009-07-21 12:20:22 -0400880 * Print the events from <debugfs_mount_point>/tracing/events
881 */
882
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200883void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
Jason Baronf6bdafe2009-07-21 12:20:22 -0400884{
885 DIR *sys_dir, *evt_dir;
886 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400887 char evt_path[MAXPATHLEN];
Eric Dumazet725b1362009-09-24 15:39:09 +0200888 char dir_path[MAXPATHLEN];
Jason Baronf6bdafe2009-07-21 12:20:22 -0400889
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200890 if (debugfs_valid_mountpoint(tracing_events_path))
Jason Baronf6bdafe2009-07-21 12:20:22 -0400891 return;
892
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200893 sys_dir = opendir(tracing_events_path);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400894 if (!sys_dir)
Eric Dumazet725b1362009-09-24 15:39:09 +0200895 return;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400896
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300897 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200898 if (subsys_glob != NULL &&
899 !strglobmatch(sys_dirent.d_name, subsys_glob))
900 continue;
Eric Dumazet725b1362009-09-24 15:39:09 +0200901
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200902 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
Eric Dumazet725b1362009-09-24 15:39:09 +0200903 sys_dirent.d_name);
904 evt_dir = opendir(dir_path);
905 if (!evt_dir)
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300906 continue;
Eric Dumazet725b1362009-09-24 15:39:09 +0200907
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300908 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200909 if (event_glob != NULL &&
910 !strglobmatch(evt_dirent.d_name, event_glob))
911 continue;
912
Jason Baronf6bdafe2009-07-21 12:20:22 -0400913 snprintf(evt_path, MAXPATHLEN, "%s:%s",
914 sys_dirent.d_name, evt_dirent.d_name);
Ingo Molnar947b4ad2011-04-29 22:52:42 +0200915 printf(" %-50s [%s]\n", evt_path,
Liming Wang41bdcb22009-12-29 16:37:07 +0800916 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400917 }
918 closedir(evt_dir);
919 }
Jason Baronf6bdafe2009-07-21 12:20:22 -0400920 closedir(sys_dir);
921}
922
923/*
Thomas Renninger20c457b2011-01-03 17:50:45 +0100924 * Check whether event is in <debugfs_mount_point>/tracing/events
925 */
926
927int is_valid_tracepoint(const char *event_string)
928{
929 DIR *sys_dir, *evt_dir;
930 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
931 char evt_path[MAXPATHLEN];
932 char dir_path[MAXPATHLEN];
933
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200934 if (debugfs_valid_mountpoint(tracing_events_path))
Thomas Renninger20c457b2011-01-03 17:50:45 +0100935 return 0;
936
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200937 sys_dir = opendir(tracing_events_path);
Thomas Renninger20c457b2011-01-03 17:50:45 +0100938 if (!sys_dir)
939 return 0;
940
941 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
942
Arnaldo Carvalho de Meloebf294b2011-11-16 14:03:07 -0200943 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
Thomas Renninger20c457b2011-01-03 17:50:45 +0100944 sys_dirent.d_name);
945 evt_dir = opendir(dir_path);
946 if (!evt_dir)
947 continue;
948
949 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
950 snprintf(evt_path, MAXPATHLEN, "%s:%s",
951 sys_dirent.d_name, evt_dirent.d_name);
952 if (!strcmp(evt_path, event_string)) {
953 closedir(evt_dir);
954 closedir(sys_dir);
955 return 1;
956 }
957 }
958 closedir(evt_dir);
959 }
960 closedir(sys_dir);
961 return 0;
962}
963
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200964void print_events_type(u8 type)
965{
966 struct event_symbol *syms = event_symbols;
967 unsigned int i;
968 char name[64];
969
970 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
971 if (type != syms->type)
972 continue;
973
974 if (strlen(syms->alias))
975 snprintf(name, sizeof(name), "%s OR %s",
976 syms->symbol, syms->alias);
977 else
978 snprintf(name, sizeof(name), "%s", syms->symbol);
979
Ingo Molnar947b4ad2011-04-29 22:52:42 +0200980 printf(" %-50s [%s]\n", name,
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200981 event_type_descriptors[type]);
982 }
983}
984
985int print_hwcache_events(const char *event_glob)
986{
987 unsigned int type, op, i, printed = 0;
988
989 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
990 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
991 /* skip invalid cache type */
992 if (!is_cache_op_valid(type, op))
993 continue;
994
995 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
996 char *name = event_cache_name(type, op, i);
997
Ingo Molnar947b4ad2011-04-29 22:52:42 +0200998 if (event_glob != NULL && !strglobmatch(name, event_glob))
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200999 continue;
1000
Ingo Molnar947b4ad2011-04-29 22:52:42 +02001001 printf(" %-50s [%s]\n", name,
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001002 event_type_descriptors[PERF_TYPE_HW_CACHE]);
1003 ++printed;
1004 }
1005 }
1006 }
1007
1008 return printed;
1009}
1010
Thomas Renninger20c457b2011-01-03 17:50:45 +01001011/*
Thomas Gleixner86847b62009-06-06 12:24:17 +02001012 * Print the help text for the event symbols:
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001013 */
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001014void print_events(const char *event_glob)
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001015{
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001016 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
Ingo Molnar947b4ad2011-04-29 22:52:42 +02001017 struct event_symbol *syms = event_symbols;
1018 char name[MAX_NAME_LEN];
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001019
Marti Raudsepp689d3012009-10-27 00:33:05 +00001020 printf("\n");
1021 printf("List of pre-defined events (to be used in -e):\n");
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001022
Thomas Gleixner86847b62009-06-06 12:24:17 +02001023 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
Liming Wang41bdcb22009-12-29 16:37:07 +08001024 type = syms->type;
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001025
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001026 if (type != prev_type && printed) {
Marti Raudsepp689d3012009-10-27 00:33:05 +00001027 printf("\n");
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001028 printed = 0;
1029 ntypes_printed++;
1030 }
1031
1032 if (event_glob != NULL &&
1033 !(strglobmatch(syms->symbol, event_glob) ||
1034 (syms->alias && strglobmatch(syms->alias, event_glob))))
1035 continue;
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001036
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +05301037 if (strlen(syms->alias))
Ingo Molnar947b4ad2011-04-29 22:52:42 +02001038 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +05301039 else
Ingo Molnar947b4ad2011-04-29 22:52:42 +02001040 strncpy(name, syms->symbol, MAX_NAME_LEN);
1041 printf(" %-50s [%s]\n", name,
Thomas Gleixner86847b62009-06-06 12:24:17 +02001042 event_type_descriptors[type]);
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001043
Thomas Gleixner86847b62009-06-06 12:24:17 +02001044 prev_type = type;
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001045 ++printed;
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001046 }
1047
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001048 if (ntypes_printed) {
1049 printed = 0;
1050 printf("\n");
Jaswinder Singh Rajput73c24cb2009-07-01 18:36:18 +05301051 }
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001052 print_hwcache_events(event_glob);
1053
1054 if (event_glob != NULL)
1055 return;
Jaswinder Singh Rajput73c24cb2009-07-01 18:36:18 +05301056
Marti Raudsepp689d3012009-10-27 00:33:05 +00001057 printf("\n");
Ingo Molnar947b4ad2011-04-29 22:52:42 +02001058 printf(" %-50s [%s]\n",
Jiri Olsa5f537a22012-03-15 20:09:18 +01001059 "rNNN",
Arnaldo Carvalho de Melo1cf4a062010-05-07 14:07:05 -03001060 event_type_descriptors[PERF_TYPE_RAW]);
Jiri Olsa5f537a22012-03-15 20:09:18 +01001061 printf(" %-50s [%s]\n",
1062 "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
1063 event_type_descriptors[PERF_TYPE_RAW]);
1064 printf(" (see 'perf list --help' on how to encode it)\n");
Marti Raudsepp689d3012009-10-27 00:33:05 +00001065 printf("\n");
Thomas Gleixner86847b62009-06-06 12:24:17 +02001066
Ingo Molnar947b4ad2011-04-29 22:52:42 +02001067 printf(" %-50s [%s]\n",
Liming Wang41bdcb22009-12-29 16:37:07 +08001068 "mem:<addr>[:access]",
1069 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
Frederic Weisbecker1b290d62009-11-23 15:42:35 +01001070 printf("\n");
1071
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001072 print_tracepoint_events(NULL, NULL);
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001073}
Jiri Olsa8f707d82012-03-15 20:09:16 +01001074
1075int parse_events__is_hardcoded_term(struct parse_events__term *term)
1076{
Jiri Olsa16fa7e82012-04-25 18:24:57 +02001077 return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
Jiri Olsa8f707d82012-03-15 20:09:16 +01001078}
1079
Jiri Olsa16fa7e82012-04-25 18:24:57 +02001080static int new_term(struct parse_events__term **_term, int type_val,
1081 int type_term, char *config,
1082 char *str, long num)
Jiri Olsa8f707d82012-03-15 20:09:16 +01001083{
1084 struct parse_events__term *term;
1085
1086 term = zalloc(sizeof(*term));
1087 if (!term)
1088 return -ENOMEM;
1089
1090 INIT_LIST_HEAD(&term->list);
Jiri Olsa16fa7e82012-04-25 18:24:57 +02001091 term->type_val = type_val;
1092 term->type_term = type_term;
Jiri Olsa8f707d82012-03-15 20:09:16 +01001093 term->config = config;
1094
Jiri Olsa16fa7e82012-04-25 18:24:57 +02001095 switch (type_val) {
Jiri Olsa8f707d82012-03-15 20:09:16 +01001096 case PARSE_EVENTS__TERM_TYPE_NUM:
1097 term->val.num = num;
1098 break;
1099 case PARSE_EVENTS__TERM_TYPE_STR:
1100 term->val.str = str;
1101 break;
1102 default:
1103 return -EINVAL;
1104 }
1105
1106 *_term = term;
1107 return 0;
1108}
1109
Jiri Olsa16fa7e82012-04-25 18:24:57 +02001110int parse_events__term_num(struct parse_events__term **term,
1111 int type_term, char *config, long num)
1112{
1113 return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
1114 config, NULL, num);
1115}
1116
1117int parse_events__term_str(struct parse_events__term **term,
1118 int type_term, char *config, char *str)
1119{
1120 return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
1121 config, str, 0);
1122}
1123
Jiri Olsa8f707d82012-03-15 20:09:16 +01001124void parse_events__free_terms(struct list_head *terms)
1125{
1126 struct parse_events__term *term, *h;
1127
1128 list_for_each_entry_safe(term, h, terms, list)
1129 free(term);
1130
1131 free(terms);
1132}