Merge tag 'trace-v4.17-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rosted...
[sfrench/cifs-2.6.git] / tools / perf / util / parse-events.y
1 %pure-parser
2 %parse-param {void *_parse_state}
3 %parse-param {void *scanner}
4 %lex-param {void* scanner}
5 %locations
6
7 %{
8
9 #define YYDEBUG 1
10
11 #include <fnmatch.h>
12 #include <linux/compiler.h>
13 #include <linux/list.h>
14 #include <linux/types.h>
15 #include "util.h"
16 #include "pmu.h"
17 #include "debug.h"
18 #include "parse-events.h"
19 #include "parse-events-bison.h"
20
21 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
22
23 #define ABORT_ON(val) \
24 do { \
25         if (val) \
26                 YYABORT; \
27 } while (0)
28
29 #define ALLOC_LIST(list) \
30 do { \
31         list = malloc(sizeof(*list)); \
32         ABORT_ON(!list);              \
33         INIT_LIST_HEAD(list);         \
34 } while (0)
35
36 static void inc_group_count(struct list_head *list,
37                        struct parse_events_state *parse_state)
38 {
39         /* Count groups only have more than 1 members */
40         if (!list_is_last(list->next, list))
41                 parse_state->nr_groups++;
42 }
43
44 %}
45
46 %token PE_START_EVENTS PE_START_TERMS
47 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
48 %token PE_EVENT_NAME
49 %token PE_NAME
50 %token PE_BPF_OBJECT PE_BPF_SOURCE
51 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
52 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
53 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
54 %token PE_ERROR
55 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
56 %token PE_ARRAY_ALL PE_ARRAY_RANGE
57 %token PE_DRV_CFG_TERM
58 %type <num> PE_VALUE
59 %type <num> PE_VALUE_SYM_HW
60 %type <num> PE_VALUE_SYM_SW
61 %type <num> PE_RAW
62 %type <num> PE_TERM
63 %type <str> PE_NAME
64 %type <str> PE_BPF_OBJECT
65 %type <str> PE_BPF_SOURCE
66 %type <str> PE_NAME_CACHE_TYPE
67 %type <str> PE_NAME_CACHE_OP_RESULT
68 %type <str> PE_MODIFIER_EVENT
69 %type <str> PE_MODIFIER_BP
70 %type <str> PE_EVENT_NAME
71 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
72 %type <str> PE_DRV_CFG_TERM
73 %type <num> value_sym
74 %type <head> event_config
75 %type <head> opt_event_config
76 %type <term> event_term
77 %type <head> event_pmu
78 %type <head> event_legacy_symbol
79 %type <head> event_legacy_cache
80 %type <head> event_legacy_mem
81 %type <head> event_legacy_tracepoint
82 %type <tracepoint_name> tracepoint_name
83 %type <head> event_legacy_numeric
84 %type <head> event_legacy_raw
85 %type <head> event_bpf_file
86 %type <head> event_def
87 %type <head> event_mod
88 %type <head> event_name
89 %type <head> event
90 %type <head> events
91 %type <head> group_def
92 %type <head> group
93 %type <head> groups
94 %type <array> array
95 %type <array> array_term
96 %type <array> array_terms
97
98 %union
99 {
100         char *str;
101         u64 num;
102         struct list_head *head;
103         struct parse_events_term *term;
104         struct tracepoint_name {
105                 char *sys;
106                 char *event;
107         } tracepoint_name;
108         struct parse_events_array array;
109 }
110 %%
111
112 start:
113 PE_START_EVENTS start_events
114 |
115 PE_START_TERMS  start_terms
116
117 start_events: groups
118 {
119         struct parse_events_state *parse_state = _parse_state;
120
121         parse_events_update_lists($1, &parse_state->list);
122 }
123
124 groups:
125 groups ',' group
126 {
127         struct list_head *list  = $1;
128         struct list_head *group = $3;
129
130         parse_events_update_lists(group, list);
131         $$ = list;
132 }
133 |
134 groups ',' event
135 {
136         struct list_head *list  = $1;
137         struct list_head *event = $3;
138
139         parse_events_update_lists(event, list);
140         $$ = list;
141 }
142 |
143 group
144 |
145 event
146
147 group:
148 group_def ':' PE_MODIFIER_EVENT
149 {
150         struct list_head *list = $1;
151
152         ABORT_ON(parse_events__modifier_group(list, $3));
153         $$ = list;
154 }
155 |
156 group_def
157
158 group_def:
159 PE_NAME '{' events '}'
160 {
161         struct list_head *list = $3;
162
163         inc_group_count(list, _parse_state);
164         parse_events__set_leader($1, list);
165         $$ = list;
166 }
167 |
168 '{' events '}'
169 {
170         struct list_head *list = $2;
171
172         inc_group_count(list, _parse_state);
173         parse_events__set_leader(NULL, list);
174         $$ = list;
175 }
176
177 events:
178 events ',' event
179 {
180         struct list_head *event = $3;
181         struct list_head *list  = $1;
182
183         parse_events_update_lists(event, list);
184         $$ = list;
185 }
186 |
187 event
188
189 event: event_mod
190
191 event_mod:
192 event_name PE_MODIFIER_EVENT
193 {
194         struct list_head *list = $1;
195
196         /*
197          * Apply modifier on all events added by single event definition
198          * (there could be more events added for multiple tracepoint
199          * definitions via '*?'.
200          */
201         ABORT_ON(parse_events__modifier_event(list, $2, false));
202         $$ = list;
203 }
204 |
205 event_name
206
207 event_name:
208 PE_EVENT_NAME event_def
209 {
210         ABORT_ON(parse_events_name($2, $1));
211         free($1);
212         $$ = $2;
213 }
214 |
215 event_def
216
217 event_def: event_pmu |
218            event_legacy_symbol |
219            event_legacy_cache sep_dc |
220            event_legacy_mem |
221            event_legacy_tracepoint sep_dc |
222            event_legacy_numeric sep_dc |
223            event_legacy_raw sep_dc |
224            event_bpf_file
225
226 event_pmu:
227 PE_NAME '/' event_config '/'
228 {
229         struct list_head *list, *orig_terms, *terms;
230
231         if (parse_events_copy_term_list($3, &orig_terms))
232                 YYABORT;
233
234         ALLOC_LIST(list);
235         if (parse_events_add_pmu(_parse_state, list, $1, $3, false)) {
236                 struct perf_pmu *pmu = NULL;
237                 int ok = 0;
238                 char *pattern;
239
240                 if (asprintf(&pattern, "%s*", $1) < 0)
241                         YYABORT;
242
243                 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
244                         char *name = pmu->name;
245
246                         if (!strncmp(name, "uncore_", 7) &&
247                             strncmp($1, "uncore_", 7))
248                                 name += 7;
249                         if (!fnmatch(pattern, name, 0)) {
250                                 if (parse_events_copy_term_list(orig_terms, &terms)) {
251                                         free(pattern);
252                                         YYABORT;
253                                 }
254                                 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true))
255                                         ok++;
256                                 parse_events_terms__delete(terms);
257                         }
258                 }
259
260                 free(pattern);
261
262                 if (!ok)
263                         YYABORT;
264         }
265         parse_events_terms__delete($3);
266         parse_events_terms__delete(orig_terms);
267         $$ = list;
268 }
269 |
270 PE_KERNEL_PMU_EVENT sep_dc
271 {
272         struct list_head *list;
273
274         if (parse_events_multi_pmu_add(_parse_state, $1, &list) < 0)
275                 YYABORT;
276         $$ = list;
277 }
278 |
279 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
280 {
281         struct list_head *list;
282         char pmu_name[128];
283
284         snprintf(&pmu_name, 128, "%s-%s", $1, $3);
285         if (parse_events_multi_pmu_add(_parse_state, pmu_name, &list) < 0)
286                 YYABORT;
287         $$ = list;
288 }
289
290 value_sym:
291 PE_VALUE_SYM_HW
292 |
293 PE_VALUE_SYM_SW
294
295 event_legacy_symbol:
296 value_sym '/' event_config '/'
297 {
298         struct list_head *list;
299         int type = $1 >> 16;
300         int config = $1 & 255;
301
302         ALLOC_LIST(list);
303         ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, $3));
304         parse_events_terms__delete($3);
305         $$ = list;
306 }
307 |
308 value_sym sep_slash_dc
309 {
310         struct list_head *list;
311         int type = $1 >> 16;
312         int config = $1 & 255;
313
314         ALLOC_LIST(list);
315         ABORT_ON(parse_events_add_numeric(_parse_state, list, type, config, NULL));
316         $$ = list;
317 }
318
319 event_legacy_cache:
320 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config
321 {
322         struct parse_events_state *parse_state = _parse_state;
323         struct parse_events_error *error = parse_state->error;
324         struct list_head *list;
325
326         ALLOC_LIST(list);
327         ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6));
328         parse_events_terms__delete($6);
329         $$ = list;
330 }
331 |
332 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config
333 {
334         struct parse_events_state *parse_state = _parse_state;
335         struct parse_events_error *error = parse_state->error;
336         struct list_head *list;
337
338         ALLOC_LIST(list);
339         ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4));
340         parse_events_terms__delete($4);
341         $$ = list;
342 }
343 |
344 PE_NAME_CACHE_TYPE opt_event_config
345 {
346         struct parse_events_state *parse_state = _parse_state;
347         struct parse_events_error *error = parse_state->error;
348         struct list_head *list;
349
350         ALLOC_LIST(list);
351         ABORT_ON(parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2));
352         parse_events_terms__delete($2);
353         $$ = list;
354 }
355
356 event_legacy_mem:
357 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
358 {
359         struct parse_events_state *parse_state = _parse_state;
360         struct list_head *list;
361
362         ALLOC_LIST(list);
363         ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx,
364                                              (void *) $2, $6, $4));
365         $$ = list;
366 }
367 |
368 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
369 {
370         struct parse_events_state *parse_state = _parse_state;
371         struct list_head *list;
372
373         ALLOC_LIST(list);
374         ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx,
375                                              (void *) $2, NULL, $4));
376         $$ = list;
377 }
378 |
379 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
380 {
381         struct parse_events_state *parse_state = _parse_state;
382         struct list_head *list;
383
384         ALLOC_LIST(list);
385         ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx,
386                                              (void *) $2, $4, 0));
387         $$ = list;
388 }
389 |
390 PE_PREFIX_MEM PE_VALUE sep_dc
391 {
392         struct parse_events_state *parse_state = _parse_state;
393         struct list_head *list;
394
395         ALLOC_LIST(list);
396         ABORT_ON(parse_events_add_breakpoint(list, &parse_state->idx,
397                                              (void *) $2, NULL, 0));
398         $$ = list;
399 }
400
401 event_legacy_tracepoint:
402 tracepoint_name opt_event_config
403 {
404         struct parse_events_state *parse_state = _parse_state;
405         struct parse_events_error *error = parse_state->error;
406         struct list_head *list;
407
408         ALLOC_LIST(list);
409         if (error)
410                 error->idx = @1.first_column;
411
412         if (parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
413                                         error, $2))
414                 return -1;
415
416         $$ = list;
417 }
418
419 tracepoint_name:
420 PE_NAME '-' PE_NAME ':' PE_NAME
421 {
422         char sys_name[128];
423         struct tracepoint_name tracepoint;
424
425         snprintf(&sys_name, 128, "%s-%s", $1, $3);
426         tracepoint.sys = &sys_name;
427         tracepoint.event = $5;
428
429         $$ = tracepoint;
430 }
431 |
432 PE_NAME ':' PE_NAME
433 {
434         struct tracepoint_name tracepoint = {$1, $3};
435
436         $$ = tracepoint;
437 }
438
439 event_legacy_numeric:
440 PE_VALUE ':' PE_VALUE opt_event_config
441 {
442         struct list_head *list;
443
444         ALLOC_LIST(list);
445         ABORT_ON(parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4));
446         parse_events_terms__delete($4);
447         $$ = list;
448 }
449
450 event_legacy_raw:
451 PE_RAW opt_event_config
452 {
453         struct list_head *list;
454
455         ALLOC_LIST(list);
456         ABORT_ON(parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, $1, $2));
457         parse_events_terms__delete($2);
458         $$ = list;
459 }
460
461 event_bpf_file:
462 PE_BPF_OBJECT opt_event_config
463 {
464         struct parse_events_state *parse_state = _parse_state;
465         struct parse_events_error *error = parse_state->error;
466         struct list_head *list;
467
468         ALLOC_LIST(list);
469         ABORT_ON(parse_events_load_bpf(parse_state, list, $1, false, $2));
470         parse_events_terms__delete($2);
471         $$ = list;
472 }
473 |
474 PE_BPF_SOURCE opt_event_config
475 {
476         struct list_head *list;
477
478         ALLOC_LIST(list);
479         ABORT_ON(parse_events_load_bpf(_parse_state, list, $1, true, $2));
480         parse_events_terms__delete($2);
481         $$ = list;
482 }
483
484 opt_event_config:
485 '/' event_config '/'
486 {
487         $$ = $2;
488 }
489 |
490 '/' '/'
491 {
492         $$ = NULL;
493 }
494 |
495 {
496         $$ = NULL;
497 }
498
499 start_terms: event_config
500 {
501         struct parse_events_state *parse_state = _parse_state;
502         parse_state->terms = $1;
503 }
504
505 event_config:
506 event_config ',' event_term
507 {
508         struct list_head *head = $1;
509         struct parse_events_term *term = $3;
510
511         ABORT_ON(!head);
512         list_add_tail(&term->list, head);
513         $$ = $1;
514 }
515 |
516 event_term
517 {
518         struct list_head *head = malloc(sizeof(*head));
519         struct parse_events_term *term = $1;
520
521         ABORT_ON(!head);
522         INIT_LIST_HEAD(head);
523         list_add_tail(&term->list, head);
524         $$ = head;
525 }
526
527 event_term:
528 PE_NAME '=' PE_NAME
529 {
530         struct parse_events_term *term;
531
532         ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
533                                         $1, $3, &@1, &@3));
534         $$ = term;
535 }
536 |
537 PE_NAME '=' PE_VALUE
538 {
539         struct parse_events_term *term;
540
541         ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
542                                         $1, $3, false, &@1, &@3));
543         $$ = term;
544 }
545 |
546 PE_NAME '=' PE_VALUE_SYM_HW
547 {
548         struct parse_events_term *term;
549         int config = $3 & 255;
550
551         ABORT_ON(parse_events_term__sym_hw(&term, $1, config));
552         $$ = term;
553 }
554 |
555 PE_NAME
556 {
557         struct parse_events_term *term;
558
559         ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
560                                         $1, 1, true, &@1, NULL));
561         $$ = term;
562 }
563 |
564 PE_VALUE_SYM_HW
565 {
566         struct parse_events_term *term;
567         int config = $1 & 255;
568
569         ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
570         $$ = term;
571 }
572 |
573 PE_TERM '=' PE_NAME
574 {
575         struct parse_events_term *term;
576
577         ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3));
578         $$ = term;
579 }
580 |
581 PE_TERM '=' PE_VALUE
582 {
583         struct parse_events_term *term;
584
585         ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3));
586         $$ = term;
587 }
588 |
589 PE_TERM
590 {
591         struct parse_events_term *term;
592
593         ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL));
594         $$ = term;
595 }
596 |
597 PE_NAME array '=' PE_NAME
598 {
599         struct parse_events_term *term;
600         int i;
601
602         ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
603                                         $1, $4, &@1, &@4));
604
605         term->array = $2;
606         $$ = term;
607 }
608 |
609 PE_NAME array '=' PE_VALUE
610 {
611         struct parse_events_term *term;
612
613         ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
614                                         $1, $4, false, &@1, &@4));
615         term->array = $2;
616         $$ = term;
617 }
618 |
619 PE_DRV_CFG_TERM
620 {
621         struct parse_events_term *term;
622
623         ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG,
624                                         $1, $1, &@1, NULL));
625         $$ = term;
626 }
627
628 array:
629 '[' array_terms ']'
630 {
631         $$ = $2;
632 }
633 |
634 PE_ARRAY_ALL
635 {
636         $$.nr_ranges = 0;
637         $$.ranges = NULL;
638 }
639
640 array_terms:
641 array_terms ',' array_term
642 {
643         struct parse_events_array new_array;
644
645         new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
646         new_array.ranges = malloc(sizeof(new_array.ranges[0]) *
647                                   new_array.nr_ranges);
648         ABORT_ON(!new_array.ranges);
649         memcpy(&new_array.ranges[0], $1.ranges,
650                $1.nr_ranges * sizeof(new_array.ranges[0]));
651         memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
652                $3.nr_ranges * sizeof(new_array.ranges[0]));
653         free($1.ranges);
654         free($3.ranges);
655         $$ = new_array;
656 }
657 |
658 array_term
659
660 array_term:
661 PE_VALUE
662 {
663         struct parse_events_array array;
664
665         array.nr_ranges = 1;
666         array.ranges = malloc(sizeof(array.ranges[0]));
667         ABORT_ON(!array.ranges);
668         array.ranges[0].start = $1;
669         array.ranges[0].length = 1;
670         $$ = array;
671 }
672 |
673 PE_VALUE PE_ARRAY_RANGE PE_VALUE
674 {
675         struct parse_events_array array;
676
677         ABORT_ON($3 < $1);
678         array.nr_ranges = 1;
679         array.ranges = malloc(sizeof(array.ranges[0]));
680         ABORT_ON(!array.ranges);
681         array.ranges[0].start = $1;
682         array.ranges[0].length = $3 - $1 + 1;
683         $$ = array;
684 }
685
686 sep_dc: ':' |
687
688 sep_slash_dc: '/' | ':' |
689
690 %%
691
692 void parse_events_error(YYLTYPE *loc, void *parse_state,
693                         void *scanner __maybe_unused,
694                         char const *msg __maybe_unused)
695 {
696         parse_events_evlist_error(parse_state, loc->last_column, "parser error");
697 }