blob: bbbb735268efa5fbf18931b76ef805c1c717bf4d [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"
Ingo Molnar8ad8db32009-05-26 11:10:09 +020014
Ingo Molnar8ad8db32009-05-26 11:10:09 +020015struct event_symbol {
Ingo Molnar83a09442009-08-15 12:26:57 +020016 u8 type;
17 u64 config;
18 const char *symbol;
19 const char *alias;
Ingo Molnar8ad8db32009-05-26 11:10:09 +020020};
21
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +020022enum event_result {
23 EVT_FAILED,
24 EVT_HANDLED,
25 EVT_HANDLED_ALL
26};
27
Jason Baron5beeded2009-07-21 14:16:29 -040028char debugfs_path[MAXPATHLEN];
29
Jaswinder Singh Rajput51e26842009-06-22 16:43:14 +053030#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
31#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
Ingo Molnar8ad8db32009-05-26 11:10:09 +020032
Ingo Molnara21ca2c2009-06-06 09:58:57 +020033static struct event_symbol event_symbols[] = {
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +053034 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" },
Ingo Molnar1fc570a2011-04-27 05:20:22 +020035 { CHW(STALLED_CYCLES), "stalled-cycles", "idle-cycles" },
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +053036 { CHW(INSTRUCTIONS), "instructions", "" },
37 { CHW(CACHE_REFERENCES), "cache-references", "" },
38 { CHW(CACHE_MISSES), "cache-misses", "" },
39 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
40 { CHW(BRANCH_MISSES), "branch-misses", "" },
41 { CHW(BUS_CYCLES), "bus-cycles", "" },
Ingo Molnara21ca2c2009-06-06 09:58:57 +020042
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +053043 { CSW(CPU_CLOCK), "cpu-clock", "" },
44 { CSW(TASK_CLOCK), "task-clock", "" },
Jaswinder Singh Rajputc0c22db2009-06-22 20:47:26 +053045 { CSW(PAGE_FAULTS), "page-faults", "faults" },
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +053046 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" },
47 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
48 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
49 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
Anton Blanchardf7d79862009-10-18 01:09:29 +000050 { CSW(ALIGNMENT_FAULTS), "alignment-faults", "" },
51 { CSW(EMULATION_FAULTS), "emulation-faults", "" },
Ingo Molnar8ad8db32009-05-26 11:10:09 +020052};
53
Ingo Molnarcdd6c482009-09-21 12:02:48 +020054#define __PERF_EVENT_FIELD(config, name) \
55 ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
Ingo Molnar52425192009-05-26 09:17:18 +020056
Ingo Molnar1fc570a2011-04-27 05:20:22 +020057#define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW)
Ingo Molnarcdd6c482009-09-21 12:02:48 +020058#define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG)
Ingo Molnar1fc570a2011-04-27 05:20:22 +020059#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
Ingo Molnarcdd6c482009-09-21 12:02:48 +020060#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
Ingo Molnar52425192009-05-26 09:17:18 +020061
Ingo Molnar83a09442009-08-15 12:26:57 +020062static const char *hw_event_names[] = {
Ingo Molnar8faf3b52009-06-06 13:58:12 +020063 "cycles",
Ingo Molnar52425192009-05-26 09:17:18 +020064 "instructions",
Ingo Molnar8faf3b52009-06-06 13:58:12 +020065 "cache-references",
66 "cache-misses",
Ingo Molnar52425192009-05-26 09:17:18 +020067 "branches",
Ingo Molnar8faf3b52009-06-06 13:58:12 +020068 "branch-misses",
69 "bus-cycles",
Ingo Molnar1fc570a2011-04-27 05:20:22 +020070 "stalled-cycles",
Ingo Molnar52425192009-05-26 09:17:18 +020071};
72
Ingo Molnar83a09442009-08-15 12:26:57 +020073static const char *sw_event_names[] = {
Ingo Molnar749141d2011-04-27 04:24:57 +020074 "cpu-clock",
75 "task-clock",
Ingo Molnar8faf3b52009-06-06 13:58:12 +020076 "page-faults",
77 "context-switches",
78 "CPU-migrations",
79 "minor-faults",
80 "major-faults",
Anton Blanchardf7d79862009-10-18 01:09:29 +000081 "alignment-faults",
82 "emulation-faults",
Ingo Molnar52425192009-05-26 09:17:18 +020083};
84
Ingo Molnar8326f442009-06-05 20:22:46 +020085#define MAX_ALIASES 8
86
Ingo Molnar83a09442009-08-15 12:26:57 +020087static const char *hw_cache[][MAX_ALIASES] = {
Anton Blanchard9590b7b2009-07-06 22:01:31 +100088 { "L1-dcache", "l1-d", "l1d", "L1-data", },
89 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +053090 { "LLC", "L2" },
91 { "dTLB", "d-tlb", "Data-TLB", },
92 { "iTLB", "i-tlb", "Instruction-TLB", },
93 { "branch", "branches", "bpu", "btb", "bpc", },
Ingo Molnar8326f442009-06-05 20:22:46 +020094};
95
Ingo Molnar83a09442009-08-15 12:26:57 +020096static const char *hw_cache_op[][MAX_ALIASES] = {
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +053097 { "load", "loads", "read", },
98 { "store", "stores", "write", },
99 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
Ingo Molnar8326f442009-06-05 20:22:46 +0200100};
101
Ingo Molnar83a09442009-08-15 12:26:57 +0200102static const char *hw_cache_result[][MAX_ALIASES] = {
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +0530103 { "refs", "Reference", "ops", "access", },
104 { "misses", "miss", },
Ingo Molnar8326f442009-06-05 20:22:46 +0200105};
106
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530107#define C(x) PERF_COUNT_HW_CACHE_##x
108#define CACHE_READ (1 << C(OP_READ))
109#define CACHE_WRITE (1 << C(OP_WRITE))
110#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
111#define COP(x) (1 << x)
112
113/*
114 * cache operartion stat
115 * L1I : Read and prefetch only
116 * ITLB and BPU : Read-only
117 */
118static unsigned long hw_cache_stat[C(MAX)] = {
119 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
120 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
121 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
122 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
123 [C(ITLB)] = (CACHE_READ),
124 [C(BPU)] = (CACHE_READ),
125};
126
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300127#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \
Jason Baronf6bdafe2009-07-21 12:20:22 -0400128 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300129 if (sys_dirent.d_type == DT_DIR && \
Jason Baronf6bdafe2009-07-21 12:20:22 -0400130 (strcmp(sys_dirent.d_name, ".")) && \
131 (strcmp(sys_dirent.d_name, "..")))
132
Peter Zijlstraae07b632009-08-06 16:48:54 +0200133static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
134{
135 char evt_path[MAXPATHLEN];
136 int fd;
137
138 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
139 sys_dir->d_name, evt_dir->d_name);
140 fd = open(evt_path, O_RDONLY);
141 if (fd < 0)
142 return -EINVAL;
143 close(fd);
144
145 return 0;
146}
147
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300148#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \
Jason Baronf6bdafe2009-07-21 12:20:22 -0400149 while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300150 if (evt_dirent.d_type == DT_DIR && \
Jason Baronf6bdafe2009-07-21 12:20:22 -0400151 (strcmp(evt_dirent.d_name, ".")) && \
Peter Zijlstraae07b632009-08-06 16:48:54 +0200152 (strcmp(evt_dirent.d_name, "..")) && \
153 (!tp_event_has_id(&sys_dirent, &evt_dirent)))
Jason Baronf6bdafe2009-07-21 12:20:22 -0400154
Li Zefan270bbbe2009-09-17 16:34:51 +0800155#define MAX_EVENT_LENGTH 512
Jason Baronf6bdafe2009-07-21 12:20:22 -0400156
Jason Baronf6bdafe2009-07-21 12:20:22 -0400157
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200158struct tracepoint_path *tracepoint_id_to_path(u64 config)
Jason Baronf6bdafe2009-07-21 12:20:22 -0400159{
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200160 struct tracepoint_path *path = NULL;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400161 DIR *sys_dir, *evt_dir;
162 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400163 char id_buf[4];
Eric Dumazet725b1362009-09-24 15:39:09 +0200164 int fd;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400165 u64 id;
166 char evt_path[MAXPATHLEN];
Eric Dumazet725b1362009-09-24 15:39:09 +0200167 char dir_path[MAXPATHLEN];
Jason Baronf6bdafe2009-07-21 12:20:22 -0400168
Clark Williams549104f2009-11-08 09:03:07 -0600169 if (debugfs_valid_mountpoint(debugfs_path))
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200170 return NULL;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400171
Jason Baron5beeded2009-07-21 14:16:29 -0400172 sys_dir = opendir(debugfs_path);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400173 if (!sys_dir)
Eric Dumazet725b1362009-09-24 15:39:09 +0200174 return NULL;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400175
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300176 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
Eric Dumazet725b1362009-09-24 15:39:09 +0200177
178 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
179 sys_dirent.d_name);
180 evt_dir = opendir(dir_path);
181 if (!evt_dir)
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300182 continue;
Eric Dumazet725b1362009-09-24 15:39:09 +0200183
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300184 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
Eric Dumazet725b1362009-09-24 15:39:09 +0200185
186 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
Jason Baronf6bdafe2009-07-21 12:20:22 -0400187 evt_dirent.d_name);
Eric Dumazet725b1362009-09-24 15:39:09 +0200188 fd = open(evt_path, O_RDONLY);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400189 if (fd < 0)
190 continue;
191 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
192 close(fd);
193 continue;
194 }
195 close(fd);
196 id = atoll(id_buf);
197 if (id == config) {
198 closedir(evt_dir);
199 closedir(sys_dir);
Julia Lawall59b4cae2009-12-06 10:16:30 +0100200 path = zalloc(sizeof(*path));
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200201 path->system = malloc(MAX_EVENT_LENGTH);
202 if (!path->system) {
203 free(path);
204 return NULL;
205 }
206 path->name = malloc(MAX_EVENT_LENGTH);
207 if (!path->name) {
208 free(path->system);
209 free(path);
210 return NULL;
211 }
212 strncpy(path->system, sys_dirent.d_name,
213 MAX_EVENT_LENGTH);
214 strncpy(path->name, evt_dirent.d_name,
215 MAX_EVENT_LENGTH);
216 return path;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400217 }
218 }
219 closedir(evt_dir);
220 }
221
Jason Baronf6bdafe2009-07-21 12:20:22 -0400222 closedir(sys_dir);
Frederic Weisbecker1ef2ed12009-08-28 03:09:58 +0200223 return NULL;
224}
225
226#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
227static const char *tracepoint_id_to_name(u64 config)
228{
229 static char buf[TP_PATH_LEN];
230 struct tracepoint_path *path;
231
232 path = tracepoint_id_to_path(config);
233 if (path) {
234 snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
235 free(path->name);
236 free(path->system);
237 free(path);
238 } else
239 snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
240
241 return buf;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400242}
243
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530244static int is_cache_op_valid(u8 cache_type, u8 cache_op)
245{
246 if (hw_cache_stat[cache_type] & COP(cache_op))
247 return 1; /* valid */
248 else
249 return 0; /* invalid */
250}
251
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +0530252static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
253{
254 static char name[50];
255
256 if (cache_result) {
257 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
258 hw_cache_op[cache_op][0],
259 hw_cache_result[cache_result][0]);
260 } else {
261 sprintf(name, "%s-%s", hw_cache[cache_type][0],
262 hw_cache_op[cache_op][1]);
263 }
264
265 return name;
266}
267
David Ahern1424dc92011-03-09 22:23:28 -0700268const char *event_type(int type)
269{
270 switch (type) {
271 case PERF_TYPE_HARDWARE:
272 return "hardware";
273
274 case PERF_TYPE_SOFTWARE:
275 return "software";
276
277 case PERF_TYPE_TRACEPOINT:
278 return "tracepoint";
279
280 case PERF_TYPE_HW_CACHE:
281 return "hardware-cache";
282
283 default:
284 break;
285 }
286
287 return "unknown";
288}
289
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200290const char *event_name(struct perf_evsel *evsel)
Ingo Molnar52425192009-05-26 09:17:18 +0200291{
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200292 u64 config = evsel->attr.config;
293 int type = evsel->attr.type;
Peter Zijlstra8f18aec2009-08-06 19:40:28 +0200294
Stephane Eranianf0c55bc2011-02-16 15:10:01 +0200295 if (evsel->name)
296 return evsel->name;
297
Peter Zijlstra8f18aec2009-08-06 19:40:28 +0200298 return __event_name(type, config);
299}
300
Ingo Molnar83a09442009-08-15 12:26:57 +0200301const char *__event_name(int type, u64 config)
Peter Zijlstra8f18aec2009-08-06 19:40:28 +0200302{
Ingo Molnar52425192009-05-26 09:17:18 +0200303 static char buf[32];
304
Peter Zijlstra8f18aec2009-08-06 19:40:28 +0200305 if (type == PERF_TYPE_RAW) {
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200306 sprintf(buf, "raw 0x%" PRIx64, config);
Ingo Molnar52425192009-05-26 09:17:18 +0200307 return buf;
308 }
309
310 switch (type) {
311 case PERF_TYPE_HARDWARE:
Ingo Molnar1fc570a2011-04-27 05:20:22 +0200312 if (config < PERF_COUNT_HW_MAX && hw_event_names[config])
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200313 return hw_event_names[config];
Ingo Molnar52425192009-05-26 09:17:18 +0200314 return "unknown-hardware";
315
Ingo Molnar8326f442009-06-05 20:22:46 +0200316 case PERF_TYPE_HW_CACHE: {
Paul Mackerras9cffa8d2009-06-19 22:21:42 +1000317 u8 cache_type, cache_op, cache_result;
Ingo Molnar8326f442009-06-05 20:22:46 +0200318
319 cache_type = (config >> 0) & 0xff;
320 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
321 return "unknown-ext-hardware-cache-type";
322
323 cache_op = (config >> 8) & 0xff;
Ingo Molnar8faf3b52009-06-06 13:58:12 +0200324 if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
325 return "unknown-ext-hardware-cache-op";
Ingo Molnar8326f442009-06-05 20:22:46 +0200326
327 cache_result = (config >> 16) & 0xff;
Ingo Molnar8faf3b52009-06-06 13:58:12 +0200328 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
329 return "unknown-ext-hardware-cache-result";
Ingo Molnar8326f442009-06-05 20:22:46 +0200330
Jaswinder Singh Rajput06813f62009-06-25 17:16:07 +0530331 if (!is_cache_op_valid(cache_type, cache_op))
332 return "invalid-cache";
Ingo Molnar8326f442009-06-05 20:22:46 +0200333
Jaswinder Singh Rajpute5c59542009-06-25 18:25:22 +0530334 return event_cache_name(cache_type, cache_op, cache_result);
Ingo Molnar8326f442009-06-05 20:22:46 +0200335 }
336
Ingo Molnar52425192009-05-26 09:17:18 +0200337 case PERF_TYPE_SOFTWARE:
Ingo Molnar1fc570a2011-04-27 05:20:22 +0200338 if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200339 return sw_event_names[config];
Ingo Molnar52425192009-05-26 09:17:18 +0200340 return "unknown-software";
341
Jason Baronf6bdafe2009-07-21 12:20:22 -0400342 case PERF_TYPE_TRACEPOINT:
343 return tracepoint_id_to_name(config);
344
Ingo Molnar52425192009-05-26 09:17:18 +0200345 default:
346 break;
347 }
348
349 return "unknown";
350}
351
Ingo Molnar83a09442009-08-15 12:26:57 +0200352static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
Ingo Molnar8326f442009-06-05 20:22:46 +0200353{
354 int i, j;
Paul Mackerras61c45982009-07-01 13:04:34 +1000355 int n, longest = -1;
Ingo Molnar8326f442009-06-05 20:22:46 +0200356
357 for (i = 0; i < size; i++) {
Paul Mackerras61c45982009-07-01 13:04:34 +1000358 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
359 n = strlen(names[i][j]);
360 if (n > longest && !strncasecmp(*str, names[i][j], n))
361 longest = n;
362 }
363 if (longest > 0) {
364 *str += longest;
365 return i;
Ingo Molnar8326f442009-06-05 20:22:46 +0200366 }
367 }
368
Ingo Molnar89536452009-06-06 21:04:17 +0200369 return -1;
Ingo Molnar8326f442009-06-05 20:22:46 +0200370}
371
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200372static enum event_result
Ingo Molnarcdd6c482009-09-21 12:02:48 +0200373parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
Ingo Molnar8326f442009-06-05 20:22:46 +0200374{
Paul Mackerras61c45982009-07-01 13:04:34 +1000375 const char *s = *str;
376 int cache_type = -1, cache_op = -1, cache_result = -1;
Ingo Molnar8326f442009-06-05 20:22:46 +0200377
Paul Mackerras61c45982009-07-01 13:04:34 +1000378 cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
Ingo Molnar8326f442009-06-05 20:22:46 +0200379 /*
380 * No fallback - if we cannot get a clear cache type
381 * then bail out:
382 */
383 if (cache_type == -1)
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200384 return EVT_FAILED;
Ingo Molnar8326f442009-06-05 20:22:46 +0200385
Paul Mackerras61c45982009-07-01 13:04:34 +1000386 while ((cache_op == -1 || cache_result == -1) && *s == '-') {
387 ++s;
388
389 if (cache_op == -1) {
390 cache_op = parse_aliases(&s, hw_cache_op,
391 PERF_COUNT_HW_CACHE_OP_MAX);
392 if (cache_op >= 0) {
393 if (!is_cache_op_valid(cache_type, cache_op))
394 return 0;
395 continue;
396 }
397 }
398
399 if (cache_result == -1) {
400 cache_result = parse_aliases(&s, hw_cache_result,
401 PERF_COUNT_HW_CACHE_RESULT_MAX);
402 if (cache_result >= 0)
403 continue;
404 }
405
406 /*
407 * Can't parse this as a cache op or result, so back up
408 * to the '-'.
409 */
410 --s;
411 break;
412 }
413
Ingo Molnar8326f442009-06-05 20:22:46 +0200414 /*
415 * Fall back to reads:
416 */
Ingo Molnar89536452009-06-06 21:04:17 +0200417 if (cache_op == -1)
418 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
Ingo Molnar8326f442009-06-05 20:22:46 +0200419
Ingo Molnar8326f442009-06-05 20:22:46 +0200420 /*
421 * Fall back to accesses:
422 */
423 if (cache_result == -1)
424 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
425
426 attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
427 attr->type = PERF_TYPE_HW_CACHE;
428
Paul Mackerras61c45982009-07-01 13:04:34 +1000429 *str = s;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200430 return EVT_HANDLED;
Ingo Molnar8326f442009-06-05 20:22:46 +0200431}
432
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200433static enum event_result
434parse_single_tracepoint_event(char *sys_name,
435 const char *evt_name,
436 unsigned int evt_length,
Ingo Molnarcdd6c482009-09-21 12:02:48 +0200437 struct perf_event_attr *attr,
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200438 const char **strp)
439{
440 char evt_path[MAXPATHLEN];
441 char id_buf[4];
442 u64 id;
443 int fd;
444
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200445 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
446 sys_name, evt_name);
447
448 fd = open(evt_path, O_RDONLY);
449 if (fd < 0)
450 return EVT_FAILED;
451
452 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
453 close(fd);
454 return EVT_FAILED;
455 }
456
457 close(fd);
458 id = atoll(id_buf);
459 attr->config = id;
460 attr->type = PERF_TYPE_TRACEPOINT;
Corey Ashford4c635a42010-11-30 14:27:01 -0800461 *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200462
Stephane Eranian5710fca2010-04-21 18:06:01 +0200463 attr->sample_type |= PERF_SAMPLE_RAW;
464 attr->sample_type |= PERF_SAMPLE_TIME;
465 attr->sample_type |= PERF_SAMPLE_CPU;
466
467 attr->sample_period = 1;
468
469
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200470 return EVT_HANDLED;
471}
472
473/* sys + ':' + event + ':' + flags*/
474#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
475static enum event_result
Arnaldo Carvalho de Melo17ea1b72011-01-17 14:40:46 -0200476parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
477 const char *evt_exp, char *flags)
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200478{
479 char evt_path[MAXPATHLEN];
480 struct dirent *evt_ent;
481 DIR *evt_dir;
482
483 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
484 evt_dir = opendir(evt_path);
485
486 if (!evt_dir) {
487 perror("Can't open event dir");
488 return EVT_FAILED;
489 }
490
491 while ((evt_ent = readdir(evt_dir))) {
492 char event_opt[MAX_EVOPT_LEN + 1];
493 int len;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200494
495 if (!strcmp(evt_ent->d_name, ".")
496 || !strcmp(evt_ent->d_name, "..")
497 || !strcmp(evt_ent->d_name, "enable")
498 || !strcmp(evt_ent->d_name, "filter"))
499 continue;
500
Masami Hiramatsufb1d2ed2010-01-05 17:47:17 -0500501 if (!strglobmatch(evt_ent->d_name, evt_exp))
502 continue;
503
Ulrich Drepper180570f2009-12-06 13:25:30 -0500504 len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name,
505 evt_ent->d_name, flags ? ":" : "",
506 flags ?: "");
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200507 if (len < 0)
508 return EVT_FAILED;
509
Arnaldo Carvalho de Melo17ea1b72011-01-17 14:40:46 -0200510 if (parse_events(opt, event_opt, 0))
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200511 return EVT_FAILED;
512 }
513
514 return EVT_HANDLED_ALL;
515}
516
Arnaldo Carvalho de Melo17ea1b72011-01-17 14:40:46 -0200517static enum event_result
518parse_tracepoint_event(const struct option *opt, const char **strp,
519 struct perf_event_attr *attr)
Jason Baronf6bdafe2009-07-21 12:20:22 -0400520{
521 const char *evt_name;
Corey Ashford4c635a42010-11-30 14:27:01 -0800522 char *flags = NULL, *comma_loc;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400523 char sys_name[MAX_EVENT_LENGTH];
Jason Baronf6bdafe2009-07-21 12:20:22 -0400524 unsigned int sys_length, evt_length;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400525
Clark Williams549104f2009-11-08 09:03:07 -0600526 if (debugfs_valid_mountpoint(debugfs_path))
Jason Baronf6bdafe2009-07-21 12:20:22 -0400527 return 0;
528
529 evt_name = strchr(*strp, ':');
530 if (!evt_name)
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200531 return EVT_FAILED;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400532
533 sys_length = evt_name - *strp;
534 if (sys_length >= MAX_EVENT_LENGTH)
535 return 0;
536
537 strncpy(sys_name, *strp, sys_length);
538 sys_name[sys_length] = '\0';
539 evt_name = evt_name + 1;
Frederic Weisbecker3a9f1312009-08-13 10:27:18 +0200540
Corey Ashford4c635a42010-11-30 14:27:01 -0800541 comma_loc = strchr(evt_name, ',');
542 if (comma_loc) {
543 /* take the event name up to the comma */
544 evt_name = strndup(evt_name, comma_loc - evt_name);
545 }
Frederic Weisbecker3a9f1312009-08-13 10:27:18 +0200546 flags = strchr(evt_name, ':');
547 if (flags) {
Ingo Molnar1fc35b22009-09-13 09:44:29 +0200548 /* split it out: */
549 evt_name = strndup(evt_name, flags - evt_name);
Frederic Weisbecker3a9f1312009-08-13 10:27:18 +0200550 flags++;
Frederic Weisbecker3a9f1312009-08-13 10:27:18 +0200551 }
552
Jason Baronf6bdafe2009-07-21 12:20:22 -0400553 evt_length = strlen(evt_name);
554 if (evt_length >= MAX_EVENT_LENGTH)
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200555 return EVT_FAILED;
Masami Hiramatsufb1d2ed2010-01-05 17:47:17 -0500556 if (strpbrk(evt_name, "*?")) {
Arnaldo Carvalho de Melodd9a9ad2011-01-17 14:25:06 -0200557 *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
Arnaldo Carvalho de Melo17ea1b72011-01-17 14:40:46 -0200558 return parse_multiple_tracepoint_event(opt, sys_name, evt_name,
Masami Hiramatsufb1d2ed2010-01-05 17:47:17 -0500559 flags);
Han Pingtianf006d252011-01-06 17:39:22 +0800560 } else {
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200561 return parse_single_tracepoint_event(sys_name, evt_name,
Frederic Weisbeckerbdef3b02010-04-14 20:05:17 +0200562 evt_length, attr, strp);
Han Pingtianf006d252011-01-06 17:39:22 +0800563 }
Jason Baronf6bdafe2009-07-21 12:20:22 -0400564}
565
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100566static enum event_result
567parse_breakpoint_type(const char *type, const char **strp,
568 struct perf_event_attr *attr)
569{
570 int i;
571
572 for (i = 0; i < 3; i++) {
573 if (!type[i])
574 break;
575
576 switch (type[i]) {
577 case 'r':
578 attr->bp_type |= HW_BREAKPOINT_R;
579 break;
580 case 'w':
581 attr->bp_type |= HW_BREAKPOINT_W;
582 break;
583 case 'x':
584 attr->bp_type |= HW_BREAKPOINT_X;
585 break;
586 default:
587 return EVT_FAILED;
588 }
589 }
590 if (!attr->bp_type) /* Default */
591 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
592
593 *strp = type + i;
594
595 return EVT_HANDLED;
596}
597
598static enum event_result
599parse_breakpoint_event(const char **strp, struct perf_event_attr *attr)
600{
601 const char *target;
602 const char *type;
603 char *endaddr;
604 u64 addr;
605 enum event_result err;
606
607 target = strchr(*strp, ':');
608 if (!target)
609 return EVT_FAILED;
610
611 if (strncmp(*strp, "mem", target - *strp) != 0)
612 return EVT_FAILED;
613
614 target++;
615
616 addr = strtoull(target, &endaddr, 0);
617 if (target == endaddr)
618 return EVT_FAILED;
619
620 attr->bp_addr = addr;
621 *strp = endaddr;
622
623 type = strchr(target, ':');
624
625 /* If no type is defined, just rw as default */
626 if (!type) {
627 attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
628 } else {
629 err = parse_breakpoint_type(++type, strp, attr);
630 if (err == EVT_FAILED)
631 return EVT_FAILED;
632 }
633
Frederic Weisbeckeraa59a482010-06-24 21:36:19 +0200634 /*
635 * We should find a nice way to override the access length
636 * Provide some defaults for now
637 */
638 if (attr->bp_type == HW_BREAKPOINT_X)
639 attr->bp_len = sizeof(long);
640 else
641 attr->bp_len = HW_BREAKPOINT_LEN_4;
642
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100643 attr->type = PERF_TYPE_BREAKPOINT;
644
645 return EVT_HANDLED;
646}
647
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530648static int check_events(const char *str, unsigned int i)
649{
Paul Mackerras61c45982009-07-01 13:04:34 +1000650 int n;
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530651
Paul Mackerras61c45982009-07-01 13:04:34 +1000652 n = strlen(event_symbols[i].symbol);
Ingo Molnarb908deb2011-04-27 03:55:40 +0200653 if (!strncasecmp(str, event_symbols[i].symbol, n))
Paul Mackerras61c45982009-07-01 13:04:34 +1000654 return n;
655
656 n = strlen(event_symbols[i].alias);
Ingo Molnarb908deb2011-04-27 03:55:40 +0200657 if (n) {
658 if (!strncasecmp(str, event_symbols[i].alias, n))
Paul Mackerras61c45982009-07-01 13:04:34 +1000659 return n;
Ingo Molnarb908deb2011-04-27 03:55:40 +0200660 }
661
Paul Mackerras61c45982009-07-01 13:04:34 +1000662 return 0;
663}
664
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200665static enum event_result
Ingo Molnarcdd6c482009-09-21 12:02:48 +0200666parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
Paul Mackerras61c45982009-07-01 13:04:34 +1000667{
668 const char *str = *strp;
669 unsigned int i;
670 int n;
671
672 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
673 n = check_events(str, i);
674 if (n > 0) {
675 attr->type = event_symbols[i].type;
676 attr->config = event_symbols[i].config;
677 *strp = str + n;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200678 return EVT_HANDLED;
Paul Mackerras61c45982009-07-01 13:04:34 +1000679 }
680 }
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200681 return EVT_FAILED;
Paul Mackerras61c45982009-07-01 13:04:34 +1000682}
683
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200684static enum event_result
Ingo Molnarcdd6c482009-09-21 12:02:48 +0200685parse_raw_event(const char **strp, struct perf_event_attr *attr)
Paul Mackerras61c45982009-07-01 13:04:34 +1000686{
687 const char *str = *strp;
688 u64 config;
689 int n;
690
691 if (*str != 'r')
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200692 return EVT_FAILED;
Paul Mackerras61c45982009-07-01 13:04:34 +1000693 n = hex2u64(str + 1, &config);
694 if (n > 0) {
695 *strp = str + n + 1;
696 attr->type = PERF_TYPE_RAW;
697 attr->config = config;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200698 return EVT_HANDLED;
Paul Mackerras61c45982009-07-01 13:04:34 +1000699 }
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200700 return EVT_FAILED;
Paul Mackerras61c45982009-07-01 13:04:34 +1000701}
702
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200703static enum event_result
Ingo Molnarcdd6c482009-09-21 12:02:48 +0200704parse_numeric_event(const char **strp, struct perf_event_attr *attr)
Paul Mackerras61c45982009-07-01 13:04:34 +1000705{
706 const char *str = *strp;
707 char *endp;
708 unsigned long type;
709 u64 config;
710
711 type = strtoul(str, &endp, 0);
712 if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
713 str = endp + 1;
714 config = strtoul(str, &endp, 0);
715 if (endp > str) {
716 attr->type = type;
717 attr->config = config;
718 *strp = endp;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200719 return EVT_HANDLED;
Paul Mackerras61c45982009-07-01 13:04:34 +1000720 }
721 }
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200722 return EVT_FAILED;
Paul Mackerras61c45982009-07-01 13:04:34 +1000723}
724
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200725static int
Ingo Molnarcdd6c482009-09-21 12:02:48 +0200726parse_event_modifier(const char **strp, struct perf_event_attr *attr)
Paul Mackerras61c45982009-07-01 13:04:34 +1000727{
728 const char *str = *strp;
Peter Zijlstraab608342010-04-08 23:03:20 +0200729 int exclude = 0;
730 int eu = 0, ek = 0, eh = 0, precise = 0;
Paul Mackerras61c45982009-07-01 13:04:34 +1000731
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200732 if (!*str)
Paul Mackerras61c45982009-07-01 13:04:34 +1000733 return 0;
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200734
735 if (*str++ != ':')
736 return -1;
737
Paul Mackerras61c45982009-07-01 13:04:34 +1000738 while (*str) {
Peter Zijlstraab608342010-04-08 23:03:20 +0200739 if (*str == 'u') {
740 if (!exclude)
741 exclude = eu = ek = eh = 1;
Paul Mackerras61c45982009-07-01 13:04:34 +1000742 eu = 0;
Peter Zijlstraab608342010-04-08 23:03:20 +0200743 } else if (*str == 'k') {
744 if (!exclude)
745 exclude = eu = ek = eh = 1;
Paul Mackerras61c45982009-07-01 13:04:34 +1000746 ek = 0;
Peter Zijlstraab608342010-04-08 23:03:20 +0200747 } else if (*str == 'h') {
748 if (!exclude)
749 exclude = eu = ek = eh = 1;
Paul Mackerras61c45982009-07-01 13:04:34 +1000750 eh = 0;
Peter Zijlstraab608342010-04-08 23:03:20 +0200751 } else if (*str == 'p') {
752 precise++;
753 } else
Paul Mackerras61c45982009-07-01 13:04:34 +1000754 break;
Peter Zijlstraab608342010-04-08 23:03:20 +0200755
Paul Mackerras61c45982009-07-01 13:04:34 +1000756 ++str;
757 }
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200758 if (str < *strp + 2)
759 return -1;
760
761 *strp = str;
762
763 attr->exclude_user = eu;
764 attr->exclude_kernel = ek;
765 attr->exclude_hv = eh;
766 attr->precise_ip = precise;
767
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +0530768 return 0;
769}
770
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200771/*
772 * Each event can have multiple symbolic names.
773 * Symbolic names are (almost) exactly matched.
774 */
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200775static enum event_result
Arnaldo Carvalho de Melo17ea1b72011-01-17 14:40:46 -0200776parse_event_symbols(const struct option *opt, const char **str,
777 struct perf_event_attr *attr)
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200778{
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200779 enum event_result ret;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200780
Arnaldo Carvalho de Melo17ea1b72011-01-17 14:40:46 -0200781 ret = parse_tracepoint_event(opt, str, attr);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200782 if (ret != EVT_FAILED)
783 goto modifier;
784
785 ret = parse_raw_event(str, attr);
786 if (ret != EVT_FAILED)
787 goto modifier;
788
789 ret = parse_numeric_event(str, attr);
790 if (ret != EVT_FAILED)
791 goto modifier;
792
793 ret = parse_symbolic_event(str, attr);
794 if (ret != EVT_FAILED)
795 goto modifier;
796
797 ret = parse_generic_hw_event(str, attr);
798 if (ret != EVT_FAILED)
799 goto modifier;
800
Frederic Weisbecker1b290d62009-11-23 15:42:35 +0100801 ret = parse_breakpoint_event(str, attr);
802 if (ret != EVT_FAILED)
803 goto modifier;
804
Marti Raudsepp85df6f62009-10-27 00:33:04 +0000805 fprintf(stderr, "invalid or unsupported event: '%s'\n", *str);
806 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200807 return EVT_FAILED;
808
809modifier:
Ingo Molnarceb53fb2011-04-27 04:06:33 +0200810 if (parse_event_modifier(str, attr) < 0) {
811 fprintf(stderr, "invalid event modifier: '%s'\n", *str);
812 fprintf(stderr, "Run 'perf list' for a list of valid events and modifiers\n");
813
814 return EVT_FAILED;
815 }
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200816
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200817 return ret;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200818}
819
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200820int parse_events(const struct option *opt, const char *str, int unset __used)
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200821{
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200822 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
Ingo Molnarcdd6c482009-09-21 12:02:48 +0200823 struct perf_event_attr attr;
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200824 enum event_result ret;
Stephane Eranianf0c55bc2011-02-16 15:10:01 +0200825 const char *ostr;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200826
Paul Mackerras61c45982009-07-01 13:04:34 +1000827 for (;;) {
Stephane Eranianf0c55bc2011-02-16 15:10:01 +0200828 ostr = str;
Paul Mackerras61c45982009-07-01 13:04:34 +1000829 memset(&attr, 0, sizeof(attr));
Arnaldo Carvalho de Melo17ea1b72011-01-17 14:40:46 -0200830 ret = parse_event_symbols(opt, &str, &attr);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200831 if (ret == EVT_FAILED)
Paul Mackerras61c45982009-07-01 13:04:34 +1000832 return -1;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200833
Paul Mackerras61c45982009-07-01 13:04:34 +1000834 if (!(*str == 0 || *str == ',' || isspace(*str)))
835 return -1;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200836
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200837 if (ret != EVT_HANDLED_ALL) {
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200838 struct perf_evsel *evsel;
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200839 evsel = perf_evsel__new(&attr, evlist->nr_entries);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200840 if (evsel == NULL)
841 return -1;
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200842 perf_evlist__add(evlist, evsel);
Stephane Eranianf0c55bc2011-02-16 15:10:01 +0200843
844 evsel->name = calloc(str - ostr + 1, 1);
845 if (!evsel->name)
846 return -1;
847 strncpy(evsel->name, ostr, str - ostr);
Frederic Weisbeckerbcd32792009-09-11 23:19:45 +0200848 }
Paul Mackerras61c45982009-07-01 13:04:34 +1000849
850 if (*str == 0)
851 break;
852 if (*str == ',')
853 ++str;
854 while (isspace(*str))
855 ++str;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200856 }
857
858 return 0;
859}
860
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200861int parse_filter(const struct option *opt, const char *str,
Li Zefanc171b552009-10-15 11:22:07 +0800862 int unset __used)
863{
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200864 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200865 struct perf_evsel *last = NULL;
Li Zefanc171b552009-10-15 11:22:07 +0800866
Arnaldo Carvalho de Melo361c99a2011-01-11 20:56:53 -0200867 if (evlist->nr_entries > 0)
868 last = list_entry(evlist->entries.prev, struct perf_evsel, node);
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200869
870 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
Li Zefanc171b552009-10-15 11:22:07 +0800871 fprintf(stderr,
872 "-F option should follow a -e tracepoint option\n");
873 return -1;
874 }
875
Arnaldo Carvalho de Melo69aad6f2011-01-03 16:39:04 -0200876 last->filter = strdup(str);
877 if (last->filter == NULL) {
Li Zefanc171b552009-10-15 11:22:07 +0800878 fprintf(stderr, "not enough memory to hold filter string\n");
879 return -1;
880 }
Li Zefanc171b552009-10-15 11:22:07 +0800881
882 return 0;
883}
884
Thomas Gleixner86847b62009-06-06 12:24:17 +0200885static const char * const event_type_descriptors[] = {
Thomas Gleixner86847b62009-06-06 12:24:17 +0200886 "Hardware event",
887 "Software event",
888 "Tracepoint event",
889 "Hardware cache event",
Liming Wang41bdcb22009-12-29 16:37:07 +0800890 "Raw hardware event descriptor",
891 "Hardware breakpoint",
Thomas Gleixner86847b62009-06-06 12:24:17 +0200892};
893
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200894/*
Jason Baronf6bdafe2009-07-21 12:20:22 -0400895 * Print the events from <debugfs_mount_point>/tracing/events
896 */
897
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200898void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
Jason Baronf6bdafe2009-07-21 12:20:22 -0400899{
900 DIR *sys_dir, *evt_dir;
901 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400902 char evt_path[MAXPATHLEN];
Eric Dumazet725b1362009-09-24 15:39:09 +0200903 char dir_path[MAXPATHLEN];
Jason Baronf6bdafe2009-07-21 12:20:22 -0400904
Clark Williams549104f2009-11-08 09:03:07 -0600905 if (debugfs_valid_mountpoint(debugfs_path))
Jason Baronf6bdafe2009-07-21 12:20:22 -0400906 return;
907
Jason Baron5beeded2009-07-21 14:16:29 -0400908 sys_dir = opendir(debugfs_path);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400909 if (!sys_dir)
Eric Dumazet725b1362009-09-24 15:39:09 +0200910 return;
Jason Baronf6bdafe2009-07-21 12:20:22 -0400911
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300912 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200913 if (subsys_glob != NULL &&
914 !strglobmatch(sys_dirent.d_name, subsys_glob))
915 continue;
Eric Dumazet725b1362009-09-24 15:39:09 +0200916
917 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
918 sys_dirent.d_name);
919 evt_dir = opendir(dir_path);
920 if (!evt_dir)
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300921 continue;
Eric Dumazet725b1362009-09-24 15:39:09 +0200922
Ulrich Drepper6b58e7f2009-09-04 16:39:51 -0300923 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200924 if (event_glob != NULL &&
925 !strglobmatch(evt_dirent.d_name, event_glob))
926 continue;
927
Jason Baronf6bdafe2009-07-21 12:20:22 -0400928 snprintf(evt_path, MAXPATHLEN, "%s:%s",
929 sys_dirent.d_name, evt_dirent.d_name);
Marti Raudsepp689d3012009-10-27 00:33:05 +0000930 printf(" %-42s [%s]\n", evt_path,
Liming Wang41bdcb22009-12-29 16:37:07 +0800931 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
Jason Baronf6bdafe2009-07-21 12:20:22 -0400932 }
933 closedir(evt_dir);
934 }
Jason Baronf6bdafe2009-07-21 12:20:22 -0400935 closedir(sys_dir);
936}
937
938/*
Thomas Renninger20c457b2011-01-03 17:50:45 +0100939 * Check whether event is in <debugfs_mount_point>/tracing/events
940 */
941
942int is_valid_tracepoint(const char *event_string)
943{
944 DIR *sys_dir, *evt_dir;
945 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
946 char evt_path[MAXPATHLEN];
947 char dir_path[MAXPATHLEN];
948
949 if (debugfs_valid_mountpoint(debugfs_path))
950 return 0;
951
952 sys_dir = opendir(debugfs_path);
953 if (!sys_dir)
954 return 0;
955
956 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
957
958 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
959 sys_dirent.d_name);
960 evt_dir = opendir(dir_path);
961 if (!evt_dir)
962 continue;
963
964 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
965 snprintf(evt_path, MAXPATHLEN, "%s:%s",
966 sys_dirent.d_name, evt_dirent.d_name);
967 if (!strcmp(evt_path, event_string)) {
968 closedir(evt_dir);
969 closedir(sys_dir);
970 return 1;
971 }
972 }
973 closedir(evt_dir);
974 }
975 closedir(sys_dir);
976 return 0;
977}
978
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -0200979void print_events_type(u8 type)
980{
981 struct event_symbol *syms = event_symbols;
982 unsigned int i;
983 char name[64];
984
985 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
986 if (type != syms->type)
987 continue;
988
989 if (strlen(syms->alias))
990 snprintf(name, sizeof(name), "%s OR %s",
991 syms->symbol, syms->alias);
992 else
993 snprintf(name, sizeof(name), "%s", syms->symbol);
994
995 printf(" %-42s [%s]\n", name,
996 event_type_descriptors[type]);
997 }
998}
999
1000int print_hwcache_events(const char *event_glob)
1001{
1002 unsigned int type, op, i, printed = 0;
1003
1004 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1005 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
1006 /* skip invalid cache type */
1007 if (!is_cache_op_valid(type, op))
1008 continue;
1009
1010 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
1011 char *name = event_cache_name(type, op, i);
1012
1013 if (event_glob != NULL &&
1014 !strglobmatch(name, event_glob))
1015 continue;
1016
1017 printf(" %-42s [%s]\n", name,
1018 event_type_descriptors[PERF_TYPE_HW_CACHE]);
1019 ++printed;
1020 }
1021 }
1022 }
1023
1024 return printed;
1025}
1026
Thomas Renninger20c457b2011-01-03 17:50:45 +01001027/*
Thomas Gleixner86847b62009-06-06 12:24:17 +02001028 * Print the help text for the event symbols:
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001029 */
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001030void print_events(const char *event_glob)
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001031{
Thomas Gleixner86847b62009-06-06 12:24:17 +02001032 struct event_symbol *syms = event_symbols;
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001033 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +05301034 char name[40];
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001035
Marti Raudsepp689d3012009-10-27 00:33:05 +00001036 printf("\n");
1037 printf("List of pre-defined events (to be used in -e):\n");
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001038
Thomas Gleixner86847b62009-06-06 12:24:17 +02001039 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
Liming Wang41bdcb22009-12-29 16:37:07 +08001040 type = syms->type;
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001041
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001042 if (type != prev_type && printed) {
Marti Raudsepp689d3012009-10-27 00:33:05 +00001043 printf("\n");
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001044 printed = 0;
1045 ntypes_printed++;
1046 }
1047
1048 if (event_glob != NULL &&
1049 !(strglobmatch(syms->symbol, event_glob) ||
1050 (syms->alias && strglobmatch(syms->alias, event_glob))))
1051 continue;
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001052
Jaswinder Singh Rajput74d5b582009-06-22 16:44:28 +05301053 if (strlen(syms->alias))
1054 sprintf(name, "%s OR %s", syms->symbol, syms->alias);
1055 else
1056 strcpy(name, syms->symbol);
Marti Raudsepp689d3012009-10-27 00:33:05 +00001057 printf(" %-42s [%s]\n", name,
Thomas Gleixner86847b62009-06-06 12:24:17 +02001058 event_type_descriptors[type]);
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001059
Thomas Gleixner86847b62009-06-06 12:24:17 +02001060 prev_type = type;
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001061 ++printed;
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001062 }
1063
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001064 if (ntypes_printed) {
1065 printed = 0;
1066 printf("\n");
Jaswinder Singh Rajput73c24cb2009-07-01 18:36:18 +05301067 }
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001068 print_hwcache_events(event_glob);
1069
1070 if (event_glob != NULL)
1071 return;
Jaswinder Singh Rajput73c24cb2009-07-01 18:36:18 +05301072
Marti Raudsepp689d3012009-10-27 00:33:05 +00001073 printf("\n");
Liming Wang41bdcb22009-12-29 16:37:07 +08001074 printf(" %-42s [%s]\n",
Arnaldo Carvalho de Melo1cf4a062010-05-07 14:07:05 -03001075 "rNNN (see 'perf list --help' on how to encode it)",
1076 event_type_descriptors[PERF_TYPE_RAW]);
Marti Raudsepp689d3012009-10-27 00:33:05 +00001077 printf("\n");
Thomas Gleixner86847b62009-06-06 12:24:17 +02001078
Liming Wang41bdcb22009-12-29 16:37:07 +08001079 printf(" %-42s [%s]\n",
1080 "mem:<addr>[:access]",
1081 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
Frederic Weisbecker1b290d62009-11-23 15:42:35 +01001082 printf("\n");
1083
Arnaldo Carvalho de Melo668b8782011-02-17 15:38:58 -02001084 print_tracepoint_events(NULL, NULL);
Jason Baronf6bdafe2009-07-21 12:20:22 -04001085
Thomas Gleixner86847b62009-06-06 12:24:17 +02001086 exit(129);
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001087}