Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/tools/perf/util/parse-events.c
10821 views
1
#include "../../../include/linux/hw_breakpoint.h"
2
#include "util.h"
3
#include "../perf.h"
4
#include "evlist.h"
5
#include "evsel.h"
6
#include "parse-options.h"
7
#include "parse-events.h"
8
#include "exec_cmd.h"
9
#include "string.h"
10
#include "symbol.h"
11
#include "cache.h"
12
#include "header.h"
13
#include "debugfs.h"
14
15
struct event_symbol {
16
u8 type;
17
u64 config;
18
const char *symbol;
19
const char *alias;
20
};
21
22
enum event_result {
23
EVT_FAILED,
24
EVT_HANDLED,
25
EVT_HANDLED_ALL
26
};
27
28
char debugfs_path[MAXPATHLEN];
29
30
#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
32
33
static struct event_symbol event_symbols[] = {
34
{ CHW(CPU_CYCLES), "cpu-cycles", "cycles" },
35
{ CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" },
36
{ CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" },
37
{ CHW(INSTRUCTIONS), "instructions", "" },
38
{ CHW(CACHE_REFERENCES), "cache-references", "" },
39
{ CHW(CACHE_MISSES), "cache-misses", "" },
40
{ CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
41
{ CHW(BRANCH_MISSES), "branch-misses", "" },
42
{ CHW(BUS_CYCLES), "bus-cycles", "" },
43
44
{ CSW(CPU_CLOCK), "cpu-clock", "" },
45
{ CSW(TASK_CLOCK), "task-clock", "" },
46
{ CSW(PAGE_FAULTS), "page-faults", "faults" },
47
{ CSW(PAGE_FAULTS_MIN), "minor-faults", "" },
48
{ CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
49
{ CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
50
{ CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
51
{ CSW(ALIGNMENT_FAULTS), "alignment-faults", "" },
52
{ CSW(EMULATION_FAULTS), "emulation-faults", "" },
53
};
54
55
#define __PERF_EVENT_FIELD(config, name) \
56
((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
57
58
#define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW)
59
#define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG)
60
#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
61
#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
62
63
static const char *hw_event_names[PERF_COUNT_HW_MAX] = {
64
"cycles",
65
"instructions",
66
"cache-references",
67
"cache-misses",
68
"branches",
69
"branch-misses",
70
"bus-cycles",
71
"stalled-cycles-frontend",
72
"stalled-cycles-backend",
73
};
74
75
static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
76
"cpu-clock",
77
"task-clock",
78
"page-faults",
79
"context-switches",
80
"CPU-migrations",
81
"minor-faults",
82
"major-faults",
83
"alignment-faults",
84
"emulation-faults",
85
};
86
87
#define MAX_ALIASES 8
88
89
static const char *hw_cache[][MAX_ALIASES] = {
90
{ "L1-dcache", "l1-d", "l1d", "L1-data", },
91
{ "L1-icache", "l1-i", "l1i", "L1-instruction", },
92
{ "LLC", "L2" },
93
{ "dTLB", "d-tlb", "Data-TLB", },
94
{ "iTLB", "i-tlb", "Instruction-TLB", },
95
{ "branch", "branches", "bpu", "btb", "bpc", },
96
};
97
98
static const char *hw_cache_op[][MAX_ALIASES] = {
99
{ "load", "loads", "read", },
100
{ "store", "stores", "write", },
101
{ "prefetch", "prefetches", "speculative-read", "speculative-load", },
102
};
103
104
static const char *hw_cache_result[][MAX_ALIASES] = {
105
{ "refs", "Reference", "ops", "access", },
106
{ "misses", "miss", },
107
};
108
109
#define C(x) PERF_COUNT_HW_CACHE_##x
110
#define CACHE_READ (1 << C(OP_READ))
111
#define CACHE_WRITE (1 << C(OP_WRITE))
112
#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
113
#define COP(x) (1 << x)
114
115
/*
116
* cache operartion stat
117
* L1I : Read and prefetch only
118
* ITLB and BPU : Read-only
119
*/
120
static unsigned long hw_cache_stat[C(MAX)] = {
121
[C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
122
[C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
123
[C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
124
[C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
125
[C(ITLB)] = (CACHE_READ),
126
[C(BPU)] = (CACHE_READ),
127
};
128
129
#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \
130
while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
131
if (sys_dirent.d_type == DT_DIR && \
132
(strcmp(sys_dirent.d_name, ".")) && \
133
(strcmp(sys_dirent.d_name, "..")))
134
135
static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
136
{
137
char evt_path[MAXPATHLEN];
138
int fd;
139
140
snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
141
sys_dir->d_name, evt_dir->d_name);
142
fd = open(evt_path, O_RDONLY);
143
if (fd < 0)
144
return -EINVAL;
145
close(fd);
146
147
return 0;
148
}
149
150
#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \
151
while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
152
if (evt_dirent.d_type == DT_DIR && \
153
(strcmp(evt_dirent.d_name, ".")) && \
154
(strcmp(evt_dirent.d_name, "..")) && \
155
(!tp_event_has_id(&sys_dirent, &evt_dirent)))
156
157
#define MAX_EVENT_LENGTH 512
158
159
160
struct tracepoint_path *tracepoint_id_to_path(u64 config)
161
{
162
struct tracepoint_path *path = NULL;
163
DIR *sys_dir, *evt_dir;
164
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
165
char id_buf[4];
166
int fd;
167
u64 id;
168
char evt_path[MAXPATHLEN];
169
char dir_path[MAXPATHLEN];
170
171
if (debugfs_valid_mountpoint(debugfs_path))
172
return NULL;
173
174
sys_dir = opendir(debugfs_path);
175
if (!sys_dir)
176
return NULL;
177
178
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
179
180
snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
181
sys_dirent.d_name);
182
evt_dir = opendir(dir_path);
183
if (!evt_dir)
184
continue;
185
186
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
187
188
snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
189
evt_dirent.d_name);
190
fd = open(evt_path, O_RDONLY);
191
if (fd < 0)
192
continue;
193
if (read(fd, id_buf, sizeof(id_buf)) < 0) {
194
close(fd);
195
continue;
196
}
197
close(fd);
198
id = atoll(id_buf);
199
if (id == config) {
200
closedir(evt_dir);
201
closedir(sys_dir);
202
path = zalloc(sizeof(*path));
203
path->system = malloc(MAX_EVENT_LENGTH);
204
if (!path->system) {
205
free(path);
206
return NULL;
207
}
208
path->name = malloc(MAX_EVENT_LENGTH);
209
if (!path->name) {
210
free(path->system);
211
free(path);
212
return NULL;
213
}
214
strncpy(path->system, sys_dirent.d_name,
215
MAX_EVENT_LENGTH);
216
strncpy(path->name, evt_dirent.d_name,
217
MAX_EVENT_LENGTH);
218
return path;
219
}
220
}
221
closedir(evt_dir);
222
}
223
224
closedir(sys_dir);
225
return NULL;
226
}
227
228
#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
229
static const char *tracepoint_id_to_name(u64 config)
230
{
231
static char buf[TP_PATH_LEN];
232
struct tracepoint_path *path;
233
234
path = tracepoint_id_to_path(config);
235
if (path) {
236
snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
237
free(path->name);
238
free(path->system);
239
free(path);
240
} else
241
snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
242
243
return buf;
244
}
245
246
static int is_cache_op_valid(u8 cache_type, u8 cache_op)
247
{
248
if (hw_cache_stat[cache_type] & COP(cache_op))
249
return 1; /* valid */
250
else
251
return 0; /* invalid */
252
}
253
254
static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
255
{
256
static char name[50];
257
258
if (cache_result) {
259
sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
260
hw_cache_op[cache_op][0],
261
hw_cache_result[cache_result][0]);
262
} else {
263
sprintf(name, "%s-%s", hw_cache[cache_type][0],
264
hw_cache_op[cache_op][1]);
265
}
266
267
return name;
268
}
269
270
const char *event_type(int type)
271
{
272
switch (type) {
273
case PERF_TYPE_HARDWARE:
274
return "hardware";
275
276
case PERF_TYPE_SOFTWARE:
277
return "software";
278
279
case PERF_TYPE_TRACEPOINT:
280
return "tracepoint";
281
282
case PERF_TYPE_HW_CACHE:
283
return "hardware-cache";
284
285
default:
286
break;
287
}
288
289
return "unknown";
290
}
291
292
const char *event_name(struct perf_evsel *evsel)
293
{
294
u64 config = evsel->attr.config;
295
int type = evsel->attr.type;
296
297
if (evsel->name)
298
return evsel->name;
299
300
return __event_name(type, config);
301
}
302
303
const char *__event_name(int type, u64 config)
304
{
305
static char buf[32];
306
307
if (type == PERF_TYPE_RAW) {
308
sprintf(buf, "raw 0x%" PRIx64, config);
309
return buf;
310
}
311
312
switch (type) {
313
case PERF_TYPE_HARDWARE:
314
if (config < PERF_COUNT_HW_MAX && hw_event_names[config])
315
return hw_event_names[config];
316
return "unknown-hardware";
317
318
case PERF_TYPE_HW_CACHE: {
319
u8 cache_type, cache_op, cache_result;
320
321
cache_type = (config >> 0) & 0xff;
322
if (cache_type > PERF_COUNT_HW_CACHE_MAX)
323
return "unknown-ext-hardware-cache-type";
324
325
cache_op = (config >> 8) & 0xff;
326
if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
327
return "unknown-ext-hardware-cache-op";
328
329
cache_result = (config >> 16) & 0xff;
330
if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
331
return "unknown-ext-hardware-cache-result";
332
333
if (!is_cache_op_valid(cache_type, cache_op))
334
return "invalid-cache";
335
336
return event_cache_name(cache_type, cache_op, cache_result);
337
}
338
339
case PERF_TYPE_SOFTWARE:
340
if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
341
return sw_event_names[config];
342
return "unknown-software";
343
344
case PERF_TYPE_TRACEPOINT:
345
return tracepoint_id_to_name(config);
346
347
default:
348
break;
349
}
350
351
return "unknown";
352
}
353
354
static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
355
{
356
int i, j;
357
int n, longest = -1;
358
359
for (i = 0; i < size; i++) {
360
for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
361
n = strlen(names[i][j]);
362
if (n > longest && !strncasecmp(*str, names[i][j], n))
363
longest = n;
364
}
365
if (longest > 0) {
366
*str += longest;
367
return i;
368
}
369
}
370
371
return -1;
372
}
373
374
static enum event_result
375
parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
376
{
377
const char *s = *str;
378
int cache_type = -1, cache_op = -1, cache_result = -1;
379
380
cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
381
/*
382
* No fallback - if we cannot get a clear cache type
383
* then bail out:
384
*/
385
if (cache_type == -1)
386
return EVT_FAILED;
387
388
while ((cache_op == -1 || cache_result == -1) && *s == '-') {
389
++s;
390
391
if (cache_op == -1) {
392
cache_op = parse_aliases(&s, hw_cache_op,
393
PERF_COUNT_HW_CACHE_OP_MAX);
394
if (cache_op >= 0) {
395
if (!is_cache_op_valid(cache_type, cache_op))
396
return 0;
397
continue;
398
}
399
}
400
401
if (cache_result == -1) {
402
cache_result = parse_aliases(&s, hw_cache_result,
403
PERF_COUNT_HW_CACHE_RESULT_MAX);
404
if (cache_result >= 0)
405
continue;
406
}
407
408
/*
409
* Can't parse this as a cache op or result, so back up
410
* to the '-'.
411
*/
412
--s;
413
break;
414
}
415
416
/*
417
* Fall back to reads:
418
*/
419
if (cache_op == -1)
420
cache_op = PERF_COUNT_HW_CACHE_OP_READ;
421
422
/*
423
* Fall back to accesses:
424
*/
425
if (cache_result == -1)
426
cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
427
428
attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
429
attr->type = PERF_TYPE_HW_CACHE;
430
431
*str = s;
432
return EVT_HANDLED;
433
}
434
435
static enum event_result
436
parse_single_tracepoint_event(char *sys_name,
437
const char *evt_name,
438
unsigned int evt_length,
439
struct perf_event_attr *attr,
440
const char **strp)
441
{
442
char evt_path[MAXPATHLEN];
443
char id_buf[4];
444
u64 id;
445
int fd;
446
447
snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
448
sys_name, evt_name);
449
450
fd = open(evt_path, O_RDONLY);
451
if (fd < 0)
452
return EVT_FAILED;
453
454
if (read(fd, id_buf, sizeof(id_buf)) < 0) {
455
close(fd);
456
return EVT_FAILED;
457
}
458
459
close(fd);
460
id = atoll(id_buf);
461
attr->config = id;
462
attr->type = PERF_TYPE_TRACEPOINT;
463
*strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
464
465
attr->sample_type |= PERF_SAMPLE_RAW;
466
attr->sample_type |= PERF_SAMPLE_TIME;
467
attr->sample_type |= PERF_SAMPLE_CPU;
468
469
attr->sample_period = 1;
470
471
472
return EVT_HANDLED;
473
}
474
475
/* sys + ':' + event + ':' + flags*/
476
#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
477
static enum event_result
478
parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
479
const char *evt_exp, char *flags)
480
{
481
char evt_path[MAXPATHLEN];
482
struct dirent *evt_ent;
483
DIR *evt_dir;
484
485
snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
486
evt_dir = opendir(evt_path);
487
488
if (!evt_dir) {
489
perror("Can't open event dir");
490
return EVT_FAILED;
491
}
492
493
while ((evt_ent = readdir(evt_dir))) {
494
char event_opt[MAX_EVOPT_LEN + 1];
495
int len;
496
497
if (!strcmp(evt_ent->d_name, ".")
498
|| !strcmp(evt_ent->d_name, "..")
499
|| !strcmp(evt_ent->d_name, "enable")
500
|| !strcmp(evt_ent->d_name, "filter"))
501
continue;
502
503
if (!strglobmatch(evt_ent->d_name, evt_exp))
504
continue;
505
506
len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name,
507
evt_ent->d_name, flags ? ":" : "",
508
flags ?: "");
509
if (len < 0)
510
return EVT_FAILED;
511
512
if (parse_events(opt, event_opt, 0))
513
return EVT_FAILED;
514
}
515
516
return EVT_HANDLED_ALL;
517
}
518
519
static enum event_result
520
parse_tracepoint_event(const struct option *opt, const char **strp,
521
struct perf_event_attr *attr)
522
{
523
const char *evt_name;
524
char *flags = NULL, *comma_loc;
525
char sys_name[MAX_EVENT_LENGTH];
526
unsigned int sys_length, evt_length;
527
528
if (debugfs_valid_mountpoint(debugfs_path))
529
return 0;
530
531
evt_name = strchr(*strp, ':');
532
if (!evt_name)
533
return EVT_FAILED;
534
535
sys_length = evt_name - *strp;
536
if (sys_length >= MAX_EVENT_LENGTH)
537
return 0;
538
539
strncpy(sys_name, *strp, sys_length);
540
sys_name[sys_length] = '\0';
541
evt_name = evt_name + 1;
542
543
comma_loc = strchr(evt_name, ',');
544
if (comma_loc) {
545
/* take the event name up to the comma */
546
evt_name = strndup(evt_name, comma_loc - evt_name);
547
}
548
flags = strchr(evt_name, ':');
549
if (flags) {
550
/* split it out: */
551
evt_name = strndup(evt_name, flags - evt_name);
552
flags++;
553
}
554
555
evt_length = strlen(evt_name);
556
if (evt_length >= MAX_EVENT_LENGTH)
557
return EVT_FAILED;
558
if (strpbrk(evt_name, "*?")) {
559
*strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
560
return parse_multiple_tracepoint_event(opt, sys_name, evt_name,
561
flags);
562
} else {
563
return parse_single_tracepoint_event(sys_name, evt_name,
564
evt_length, attr, strp);
565
}
566
}
567
568
static enum event_result
569
parse_breakpoint_type(const char *type, const char **strp,
570
struct perf_event_attr *attr)
571
{
572
int i;
573
574
for (i = 0; i < 3; i++) {
575
if (!type[i])
576
break;
577
578
switch (type[i]) {
579
case 'r':
580
attr->bp_type |= HW_BREAKPOINT_R;
581
break;
582
case 'w':
583
attr->bp_type |= HW_BREAKPOINT_W;
584
break;
585
case 'x':
586
attr->bp_type |= HW_BREAKPOINT_X;
587
break;
588
default:
589
return EVT_FAILED;
590
}
591
}
592
if (!attr->bp_type) /* Default */
593
attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
594
595
*strp = type + i;
596
597
return EVT_HANDLED;
598
}
599
600
static enum event_result
601
parse_breakpoint_event(const char **strp, struct perf_event_attr *attr)
602
{
603
const char *target;
604
const char *type;
605
char *endaddr;
606
u64 addr;
607
enum event_result err;
608
609
target = strchr(*strp, ':');
610
if (!target)
611
return EVT_FAILED;
612
613
if (strncmp(*strp, "mem", target - *strp) != 0)
614
return EVT_FAILED;
615
616
target++;
617
618
addr = strtoull(target, &endaddr, 0);
619
if (target == endaddr)
620
return EVT_FAILED;
621
622
attr->bp_addr = addr;
623
*strp = endaddr;
624
625
type = strchr(target, ':');
626
627
/* If no type is defined, just rw as default */
628
if (!type) {
629
attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
630
} else {
631
err = parse_breakpoint_type(++type, strp, attr);
632
if (err == EVT_FAILED)
633
return EVT_FAILED;
634
}
635
636
/*
637
* We should find a nice way to override the access length
638
* Provide some defaults for now
639
*/
640
if (attr->bp_type == HW_BREAKPOINT_X)
641
attr->bp_len = sizeof(long);
642
else
643
attr->bp_len = HW_BREAKPOINT_LEN_4;
644
645
attr->type = PERF_TYPE_BREAKPOINT;
646
647
return EVT_HANDLED;
648
}
649
650
static int check_events(const char *str, unsigned int i)
651
{
652
int n;
653
654
n = strlen(event_symbols[i].symbol);
655
if (!strncasecmp(str, event_symbols[i].symbol, n))
656
return n;
657
658
n = strlen(event_symbols[i].alias);
659
if (n) {
660
if (!strncasecmp(str, event_symbols[i].alias, n))
661
return n;
662
}
663
664
return 0;
665
}
666
667
static enum event_result
668
parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
669
{
670
const char *str = *strp;
671
unsigned int i;
672
int n;
673
674
for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
675
n = check_events(str, i);
676
if (n > 0) {
677
attr->type = event_symbols[i].type;
678
attr->config = event_symbols[i].config;
679
*strp = str + n;
680
return EVT_HANDLED;
681
}
682
}
683
return EVT_FAILED;
684
}
685
686
static enum event_result
687
parse_raw_event(const char **strp, struct perf_event_attr *attr)
688
{
689
const char *str = *strp;
690
u64 config;
691
int n;
692
693
if (*str != 'r')
694
return EVT_FAILED;
695
n = hex2u64(str + 1, &config);
696
if (n > 0) {
697
*strp = str + n + 1;
698
attr->type = PERF_TYPE_RAW;
699
attr->config = config;
700
return EVT_HANDLED;
701
}
702
return EVT_FAILED;
703
}
704
705
static enum event_result
706
parse_numeric_event(const char **strp, struct perf_event_attr *attr)
707
{
708
const char *str = *strp;
709
char *endp;
710
unsigned long type;
711
u64 config;
712
713
type = strtoul(str, &endp, 0);
714
if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
715
str = endp + 1;
716
config = strtoul(str, &endp, 0);
717
if (endp > str) {
718
attr->type = type;
719
attr->config = config;
720
*strp = endp;
721
return EVT_HANDLED;
722
}
723
}
724
return EVT_FAILED;
725
}
726
727
static int
728
parse_event_modifier(const char **strp, struct perf_event_attr *attr)
729
{
730
const char *str = *strp;
731
int exclude = 0;
732
int eu = 0, ek = 0, eh = 0, precise = 0;
733
734
if (!*str)
735
return 0;
736
737
if (*str == ',')
738
return 0;
739
740
if (*str++ != ':')
741
return -1;
742
743
while (*str) {
744
if (*str == 'u') {
745
if (!exclude)
746
exclude = eu = ek = eh = 1;
747
eu = 0;
748
} else if (*str == 'k') {
749
if (!exclude)
750
exclude = eu = ek = eh = 1;
751
ek = 0;
752
} else if (*str == 'h') {
753
if (!exclude)
754
exclude = eu = ek = eh = 1;
755
eh = 0;
756
} else if (*str == 'p') {
757
precise++;
758
} else
759
break;
760
761
++str;
762
}
763
if (str < *strp + 2)
764
return -1;
765
766
*strp = str;
767
768
attr->exclude_user = eu;
769
attr->exclude_kernel = ek;
770
attr->exclude_hv = eh;
771
attr->precise_ip = precise;
772
773
return 0;
774
}
775
776
/*
777
* Each event can have multiple symbolic names.
778
* Symbolic names are (almost) exactly matched.
779
*/
780
static enum event_result
781
parse_event_symbols(const struct option *opt, const char **str,
782
struct perf_event_attr *attr)
783
{
784
enum event_result ret;
785
786
ret = parse_tracepoint_event(opt, str, attr);
787
if (ret != EVT_FAILED)
788
goto modifier;
789
790
ret = parse_raw_event(str, attr);
791
if (ret != EVT_FAILED)
792
goto modifier;
793
794
ret = parse_numeric_event(str, attr);
795
if (ret != EVT_FAILED)
796
goto modifier;
797
798
ret = parse_symbolic_event(str, attr);
799
if (ret != EVT_FAILED)
800
goto modifier;
801
802
ret = parse_generic_hw_event(str, attr);
803
if (ret != EVT_FAILED)
804
goto modifier;
805
806
ret = parse_breakpoint_event(str, attr);
807
if (ret != EVT_FAILED)
808
goto modifier;
809
810
fprintf(stderr, "invalid or unsupported event: '%s'\n", *str);
811
fprintf(stderr, "Run 'perf list' for a list of valid events\n");
812
return EVT_FAILED;
813
814
modifier:
815
if (parse_event_modifier(str, attr) < 0) {
816
fprintf(stderr, "invalid event modifier: '%s'\n", *str);
817
fprintf(stderr, "Run 'perf list' for a list of valid events and modifiers\n");
818
819
return EVT_FAILED;
820
}
821
822
return ret;
823
}
824
825
int parse_events(const struct option *opt, const char *str, int unset __used)
826
{
827
struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
828
struct perf_event_attr attr;
829
enum event_result ret;
830
const char *ostr;
831
832
for (;;) {
833
ostr = str;
834
memset(&attr, 0, sizeof(attr));
835
ret = parse_event_symbols(opt, &str, &attr);
836
if (ret == EVT_FAILED)
837
return -1;
838
839
if (!(*str == 0 || *str == ',' || isspace(*str)))
840
return -1;
841
842
if (ret != EVT_HANDLED_ALL) {
843
struct perf_evsel *evsel;
844
evsel = perf_evsel__new(&attr, evlist->nr_entries);
845
if (evsel == NULL)
846
return -1;
847
perf_evlist__add(evlist, evsel);
848
849
evsel->name = calloc(str - ostr + 1, 1);
850
if (!evsel->name)
851
return -1;
852
strncpy(evsel->name, ostr, str - ostr);
853
}
854
855
if (*str == 0)
856
break;
857
if (*str == ',')
858
++str;
859
while (isspace(*str))
860
++str;
861
}
862
863
return 0;
864
}
865
866
int parse_filter(const struct option *opt, const char *str,
867
int unset __used)
868
{
869
struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
870
struct perf_evsel *last = NULL;
871
872
if (evlist->nr_entries > 0)
873
last = list_entry(evlist->entries.prev, struct perf_evsel, node);
874
875
if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
876
fprintf(stderr,
877
"-F option should follow a -e tracepoint option\n");
878
return -1;
879
}
880
881
last->filter = strdup(str);
882
if (last->filter == NULL) {
883
fprintf(stderr, "not enough memory to hold filter string\n");
884
return -1;
885
}
886
887
return 0;
888
}
889
890
static const char * const event_type_descriptors[] = {
891
"Hardware event",
892
"Software event",
893
"Tracepoint event",
894
"Hardware cache event",
895
"Raw hardware event descriptor",
896
"Hardware breakpoint",
897
};
898
899
/*
900
* Print the events from <debugfs_mount_point>/tracing/events
901
*/
902
903
void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
904
{
905
DIR *sys_dir, *evt_dir;
906
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
907
char evt_path[MAXPATHLEN];
908
char dir_path[MAXPATHLEN];
909
910
if (debugfs_valid_mountpoint(debugfs_path))
911
return;
912
913
sys_dir = opendir(debugfs_path);
914
if (!sys_dir)
915
return;
916
917
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
918
if (subsys_glob != NULL &&
919
!strglobmatch(sys_dirent.d_name, subsys_glob))
920
continue;
921
922
snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
923
sys_dirent.d_name);
924
evt_dir = opendir(dir_path);
925
if (!evt_dir)
926
continue;
927
928
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
929
if (event_glob != NULL &&
930
!strglobmatch(evt_dirent.d_name, event_glob))
931
continue;
932
933
snprintf(evt_path, MAXPATHLEN, "%s:%s",
934
sys_dirent.d_name, evt_dirent.d_name);
935
printf(" %-50s [%s]\n", evt_path,
936
event_type_descriptors[PERF_TYPE_TRACEPOINT]);
937
}
938
closedir(evt_dir);
939
}
940
closedir(sys_dir);
941
}
942
943
/*
944
* Check whether event is in <debugfs_mount_point>/tracing/events
945
*/
946
947
int is_valid_tracepoint(const char *event_string)
948
{
949
DIR *sys_dir, *evt_dir;
950
struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
951
char evt_path[MAXPATHLEN];
952
char dir_path[MAXPATHLEN];
953
954
if (debugfs_valid_mountpoint(debugfs_path))
955
return 0;
956
957
sys_dir = opendir(debugfs_path);
958
if (!sys_dir)
959
return 0;
960
961
for_each_subsystem(sys_dir, sys_dirent, sys_next) {
962
963
snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
964
sys_dirent.d_name);
965
evt_dir = opendir(dir_path);
966
if (!evt_dir)
967
continue;
968
969
for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
970
snprintf(evt_path, MAXPATHLEN, "%s:%s",
971
sys_dirent.d_name, evt_dirent.d_name);
972
if (!strcmp(evt_path, event_string)) {
973
closedir(evt_dir);
974
closedir(sys_dir);
975
return 1;
976
}
977
}
978
closedir(evt_dir);
979
}
980
closedir(sys_dir);
981
return 0;
982
}
983
984
void print_events_type(u8 type)
985
{
986
struct event_symbol *syms = event_symbols;
987
unsigned int i;
988
char name[64];
989
990
for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
991
if (type != syms->type)
992
continue;
993
994
if (strlen(syms->alias))
995
snprintf(name, sizeof(name), "%s OR %s",
996
syms->symbol, syms->alias);
997
else
998
snprintf(name, sizeof(name), "%s", syms->symbol);
999
1000
printf(" %-50s [%s]\n", name,
1001
event_type_descriptors[type]);
1002
}
1003
}
1004
1005
int print_hwcache_events(const char *event_glob)
1006
{
1007
unsigned int type, op, i, printed = 0;
1008
1009
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1010
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
1011
/* skip invalid cache type */
1012
if (!is_cache_op_valid(type, op))
1013
continue;
1014
1015
for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
1016
char *name = event_cache_name(type, op, i);
1017
1018
if (event_glob != NULL && !strglobmatch(name, event_glob))
1019
continue;
1020
1021
printf(" %-50s [%s]\n", name,
1022
event_type_descriptors[PERF_TYPE_HW_CACHE]);
1023
++printed;
1024
}
1025
}
1026
}
1027
1028
return printed;
1029
}
1030
1031
#define MAX_NAME_LEN 100
1032
1033
/*
1034
* Print the help text for the event symbols:
1035
*/
1036
void print_events(const char *event_glob)
1037
{
1038
unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
1039
struct event_symbol *syms = event_symbols;
1040
char name[MAX_NAME_LEN];
1041
1042
printf("\n");
1043
printf("List of pre-defined events (to be used in -e):\n");
1044
1045
for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
1046
type = syms->type;
1047
1048
if (type != prev_type && printed) {
1049
printf("\n");
1050
printed = 0;
1051
ntypes_printed++;
1052
}
1053
1054
if (event_glob != NULL &&
1055
!(strglobmatch(syms->symbol, event_glob) ||
1056
(syms->alias && strglobmatch(syms->alias, event_glob))))
1057
continue;
1058
1059
if (strlen(syms->alias))
1060
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
1061
else
1062
strncpy(name, syms->symbol, MAX_NAME_LEN);
1063
printf(" %-50s [%s]\n", name,
1064
event_type_descriptors[type]);
1065
1066
prev_type = type;
1067
++printed;
1068
}
1069
1070
if (ntypes_printed) {
1071
printed = 0;
1072
printf("\n");
1073
}
1074
print_hwcache_events(event_glob);
1075
1076
if (event_glob != NULL)
1077
return;
1078
1079
printf("\n");
1080
printf(" %-50s [%s]\n",
1081
"rNNN (see 'perf list --help' on how to encode it)",
1082
event_type_descriptors[PERF_TYPE_RAW]);
1083
printf("\n");
1084
1085
printf(" %-50s [%s]\n",
1086
"mem:<addr>[:access]",
1087
event_type_descriptors[PERF_TYPE_BREAKPOINT]);
1088
printf("\n");
1089
1090
print_tracepoint_events(NULL, NULL);
1091
1092
exit(129);
1093
}
1094
1095