Merge tag 'irq-urgent-2024-03-17' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / tools / perf / util / parse-events.y
1 %define api.pure full
2 %parse-param {void *_parse_state}
3 %parse-param {void *scanner}
4 %lex-param {void* scanner}
5 %locations
6
7 %{
8
9 #ifndef NDEBUG
10 #define YYDEBUG 1
11 #endif
12
13 #include <errno.h>
14 #include <linux/compiler.h>
15 #include <linux/types.h>
16 #include "pmu.h"
17 #include "pmus.h"
18 #include "evsel.h"
19 #include "parse-events.h"
20 #include "parse-events-bison.h"
21
22 int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner);
23 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
24
25 #define PE_ABORT(val) \
26 do { \
27         if (val == -ENOMEM) \
28                 YYNOMEM; \
29         YYABORT; \
30 } while (0)
31
32 static struct list_head* alloc_list(void)
33 {
34         struct list_head *list;
35
36         list = malloc(sizeof(*list));
37         if (!list)
38                 return NULL;
39
40         INIT_LIST_HEAD(list);
41         return list;
42 }
43
44 static void free_list_evsel(struct list_head* list_evsel)
45 {
46         struct evsel *evsel, *tmp;
47
48         list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
49                 list_del_init(&evsel->core.node);
50                 evsel__delete(evsel);
51         }
52         free(list_evsel);
53 }
54
55 %}
56
57 %token PE_START_EVENTS PE_START_TERMS
58 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
59 %token PE_VALUE_SYM_TOOL
60 %token PE_EVENT_NAME
61 %token PE_RAW PE_NAME
62 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
63 %token PE_LEGACY_CACHE
64 %token PE_PREFIX_MEM
65 %token PE_ERROR
66 %token PE_DRV_CFG_TERM
67 %token PE_TERM_HW
68 %type <num> PE_VALUE
69 %type <num> PE_VALUE_SYM_HW
70 %type <num> PE_VALUE_SYM_SW
71 %type <num> PE_VALUE_SYM_TOOL
72 %type <term_type> PE_TERM
73 %type <num> value_sym
74 %type <str> PE_RAW
75 %type <str> PE_NAME
76 %type <str> PE_LEGACY_CACHE
77 %type <str> PE_MODIFIER_EVENT
78 %type <str> PE_MODIFIER_BP
79 %type <str> PE_EVENT_NAME
80 %type <str> PE_DRV_CFG_TERM
81 %type <str> name_or_raw
82 %destructor { free ($$); } <str>
83 %type <term> event_term
84 %destructor { parse_events_term__delete ($$); } <term>
85 %type <list_terms> event_config
86 %type <list_terms> opt_event_config
87 %type <list_terms> opt_pmu_config
88 %destructor { parse_events_terms__delete ($$); } <list_terms>
89 %type <list_evsel> event_pmu
90 %type <list_evsel> event_legacy_symbol
91 %type <list_evsel> event_legacy_cache
92 %type <list_evsel> event_legacy_mem
93 %type <list_evsel> event_legacy_tracepoint
94 %type <list_evsel> event_legacy_numeric
95 %type <list_evsel> event_legacy_raw
96 %type <list_evsel> event_def
97 %type <list_evsel> event_mod
98 %type <list_evsel> event_name
99 %type <list_evsel> event
100 %type <list_evsel> events
101 %type <list_evsel> group_def
102 %type <list_evsel> group
103 %type <list_evsel> groups
104 %destructor { free_list_evsel ($$); } <list_evsel>
105 %type <tracepoint_name> tracepoint_name
106 %destructor { free ($$.sys); free ($$.event); } <tracepoint_name>
107 %type <hardware_term> PE_TERM_HW
108 %destructor { free ($$.str); } <hardware_term>
109
110 %union
111 {
112         char *str;
113         u64 num;
114         enum parse_events__term_type term_type;
115         struct list_head *list_evsel;
116         struct parse_events_terms *list_terms;
117         struct parse_events_term *term;
118         struct tracepoint_name {
119                 char *sys;
120                 char *event;
121         } tracepoint_name;
122         struct hardware_term {
123                 char *str;
124                 u64 num;
125         } hardware_term;
126 }
127 %%
128
129 start:
130 PE_START_EVENTS start_events
131 |
132 PE_START_TERMS  start_terms
133
134 start_events: groups
135 {
136         struct parse_events_state *parse_state = _parse_state;
137
138         /* frees $1 */
139         parse_events_update_lists($1, &parse_state->list);
140 }
141
142 groups:
143 groups ',' group
144 {
145         struct list_head *list  = $1;
146         struct list_head *group = $3;
147
148         /* frees $3 */
149         parse_events_update_lists(group, list);
150         $$ = list;
151 }
152 |
153 groups ',' event
154 {
155         struct list_head *list  = $1;
156         struct list_head *event = $3;
157
158         /* frees $3 */
159         parse_events_update_lists(event, list);
160         $$ = list;
161 }
162 |
163 group
164 |
165 event
166
167 group:
168 group_def ':' PE_MODIFIER_EVENT
169 {
170         struct list_head *list = $1;
171         int err;
172
173         err = parse_events__modifier_group(list, $3);
174         free($3);
175         if (err) {
176                 struct parse_events_state *parse_state = _parse_state;
177                 struct parse_events_error *error = parse_state->error;
178
179                 parse_events_error__handle(error, @3.first_column,
180                                            strdup("Bad modifier"), NULL);
181                 free_list_evsel(list);
182                 YYABORT;
183         }
184         $$ = list;
185 }
186 |
187 group_def
188
189 group_def:
190 PE_NAME '{' events '}'
191 {
192         struct list_head *list = $3;
193
194         /* Takes ownership of $1. */
195         parse_events__set_leader($1, list);
196         $$ = list;
197 }
198 |
199 '{' events '}'
200 {
201         struct list_head *list = $2;
202
203         parse_events__set_leader(NULL, list);
204         $$ = list;
205 }
206
207 events:
208 events ',' event
209 {
210         struct list_head *event = $3;
211         struct list_head *list  = $1;
212
213         /* frees $3 */
214         parse_events_update_lists(event, list);
215         $$ = list;
216 }
217 |
218 event
219
220 event: event_mod
221
222 event_mod:
223 event_name PE_MODIFIER_EVENT
224 {
225         struct list_head *list = $1;
226         int err;
227
228         /*
229          * Apply modifier on all events added by single event definition
230          * (there could be more events added for multiple tracepoint
231          * definitions via '*?'.
232          */
233         err = parse_events__modifier_event(list, $2, false);
234         free($2);
235         if (err) {
236                 struct parse_events_state *parse_state = _parse_state;
237                 struct parse_events_error *error = parse_state->error;
238
239                 parse_events_error__handle(error, @2.first_column,
240                                            strdup("Bad modifier"), NULL);
241                 free_list_evsel(list);
242                 YYABORT;
243         }
244         $$ = list;
245 }
246 |
247 event_name
248
249 event_name:
250 PE_EVENT_NAME event_def
251 {
252         int err;
253
254         err = parse_events_name($2, $1);
255         free($1);
256         if (err) {
257                 free_list_evsel($2);
258                 YYNOMEM;
259         }
260         $$ = $2;
261 }
262 |
263 event_def
264
265 event_def: event_pmu |
266            event_legacy_symbol |
267            event_legacy_cache sep_dc |
268            event_legacy_mem sep_dc |
269            event_legacy_tracepoint sep_dc |
270            event_legacy_numeric sep_dc |
271            event_legacy_raw sep_dc
272
273 event_pmu:
274 PE_NAME opt_pmu_config
275 {
276         struct parse_events_state *parse_state = _parse_state;
277         /* List of created evsels. */
278         struct list_head *list = NULL;
279         char *pattern = NULL;
280
281 #define CLEANUP                                         \
282         do {                                            \
283                 parse_events_terms__delete($2);         \
284                 free(list);                             \
285                 free($1);                               \
286                 free(pattern);                          \
287         } while(0)
288
289         list = alloc_list();
290         if (!list) {
291                 CLEANUP;
292                 YYNOMEM;
293         }
294         /* Attempt to add to list assuming $1 is a PMU name. */
295         if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false, &@1)) {
296                 struct perf_pmu *pmu = NULL;
297                 int ok = 0;
298
299                 /* Failure to add, try wildcard expansion of $1 as a PMU name. */
300                 if (asprintf(&pattern, "%s*", $1) < 0) {
301                         CLEANUP;
302                         YYNOMEM;
303                 }
304
305                 while ((pmu = perf_pmus__scan(pmu)) != NULL) {
306                         const char *name = pmu->name;
307
308                         if (parse_events__filter_pmu(parse_state, pmu))
309                                 continue;
310
311                         if (!strncmp(name, "uncore_", 7) &&
312                             strncmp($1, "uncore_", 7))
313                                 name += 7;
314                         if (!perf_pmu__match(pattern, name, $1) ||
315                             !perf_pmu__match(pattern, pmu->alias_name, $1)) {
316                                 bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu);
317
318                                 if (!parse_events_add_pmu(parse_state, list, pmu->name, $2,
319                                                           auto_merge_stats, &@1)) {
320                                         ok++;
321                                         parse_state->wild_card_pmus = true;
322                                 }
323                         }
324                 }
325
326                 if (!ok) {
327                         /* Failure to add, assume $1 is an event name. */
328                         zfree(&list);
329                         ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1);
330                 }
331                 if (!ok) {
332                         struct parse_events_error *error = parse_state->error;
333                         char *help;
334
335                         if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", $1) < 0)
336                                 help = NULL;
337                         parse_events_error__handle(error, @1.first_column,
338                                                    strdup("Bad event or PMU"),
339                                                    help);
340                         CLEANUP;
341                         YYABORT;
342                 }
343         }
344         $$ = list;
345         list = NULL;
346         CLEANUP;
347 #undef CLEANUP
348 }
349 |
350 PE_NAME sep_dc
351 {
352         struct list_head *list;
353         int err;
354
355         err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
356         if (err < 0) {
357                 struct parse_events_state *parse_state = _parse_state;
358                 struct parse_events_error *error = parse_state->error;
359                 char *help;
360
361                 if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0)
362                         help = NULL;
363                 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
364                 free($1);
365                 PE_ABORT(err);
366         }
367         free($1);
368         $$ = list;
369 }
370
371 value_sym:
372 PE_VALUE_SYM_HW
373 |
374 PE_VALUE_SYM_SW
375
376 event_legacy_symbol:
377 value_sym '/' event_config '/'
378 {
379         struct list_head *list;
380         int type = $1 >> 16;
381         int config = $1 & 255;
382         int err;
383         bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
384
385         list = alloc_list();
386         if (!list)
387                 YYNOMEM;
388         err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
389         parse_events_terms__delete($3);
390         if (err) {
391                 free_list_evsel(list);
392                 PE_ABORT(err);
393         }
394         $$ = list;
395 }
396 |
397 value_sym sep_slash_slash_dc
398 {
399         struct list_head *list;
400         int type = $1 >> 16;
401         int config = $1 & 255;
402         bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
403         int err;
404
405         list = alloc_list();
406         if (!list)
407                 YYNOMEM;
408         err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
409         if (err)
410                 PE_ABORT(err);
411         $$ = list;
412 }
413 |
414 PE_VALUE_SYM_TOOL sep_slash_slash_dc
415 {
416         struct list_head *list;
417         int err;
418
419         list = alloc_list();
420         if (!list)
421                 YYNOMEM;
422         err = parse_events_add_tool(_parse_state, list, $1);
423         if (err)
424                 YYNOMEM;
425         $$ = list;
426 }
427
428 event_legacy_cache:
429 PE_LEGACY_CACHE opt_event_config
430 {
431         struct parse_events_state *parse_state = _parse_state;
432         struct list_head *list;
433         int err;
434
435         list = alloc_list();
436         if (!list)
437                 YYNOMEM;
438
439         err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
440
441         parse_events_terms__delete($2);
442         free($1);
443         if (err) {
444                 free_list_evsel(list);
445                 PE_ABORT(err);
446         }
447         $$ = list;
448 }
449
450 event_legacy_mem:
451 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
452 {
453         struct list_head *list;
454         int err;
455
456         list = alloc_list();
457         if (!list)
458                 YYNOMEM;
459
460         err = parse_events_add_breakpoint(_parse_state, list,
461                                           $2, $6, $4, $7);
462         parse_events_terms__delete($7);
463         free($6);
464         if (err) {
465                 free(list);
466                 PE_ABORT(err);
467         }
468         $$ = list;
469 }
470 |
471 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
472 {
473         struct list_head *list;
474         int err;
475
476         list = alloc_list();
477         if (!list)
478                 YYNOMEM;
479
480         err = parse_events_add_breakpoint(_parse_state, list,
481                                           $2, NULL, $4, $5);
482         parse_events_terms__delete($5);
483         if (err) {
484                 free(list);
485                 PE_ABORT(err);
486         }
487         $$ = list;
488 }
489 |
490 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
491 {
492         struct list_head *list;
493         int err;
494
495         list = alloc_list();
496         if (!list)
497                 YYNOMEM;
498
499         err = parse_events_add_breakpoint(_parse_state, list,
500                                           $2, $4, 0, $5);
501         parse_events_terms__delete($5);
502         free($4);
503         if (err) {
504                 free(list);
505                 PE_ABORT(err);
506         }
507         $$ = list;
508 }
509 |
510 PE_PREFIX_MEM PE_VALUE opt_event_config
511 {
512         struct list_head *list;
513         int err;
514
515         list = alloc_list();
516         if (!list)
517                 YYNOMEM;
518         err = parse_events_add_breakpoint(_parse_state, list,
519                                           $2, NULL, 0, $3);
520         parse_events_terms__delete($3);
521         if (err) {
522                 free(list);
523                 PE_ABORT(err);
524         }
525         $$ = list;
526 }
527
528 event_legacy_tracepoint:
529 tracepoint_name opt_event_config
530 {
531         struct parse_events_state *parse_state = _parse_state;
532         struct parse_events_error *error = parse_state->error;
533         struct list_head *list;
534         int err;
535
536         list = alloc_list();
537         if (!list)
538                 YYNOMEM;
539
540         err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
541                                         error, $2, &@1);
542
543         parse_events_terms__delete($2);
544         free($1.sys);
545         free($1.event);
546         if (err) {
547                 free(list);
548                 PE_ABORT(err);
549         }
550         $$ = list;
551 }
552
553 tracepoint_name:
554 PE_NAME ':' PE_NAME
555 {
556         struct tracepoint_name tracepoint = {$1, $3};
557
558         $$ = tracepoint;
559 }
560
561 event_legacy_numeric:
562 PE_VALUE ':' PE_VALUE opt_event_config
563 {
564         struct list_head *list;
565         int err;
566
567         list = alloc_list();
568         if (!list)
569                 YYNOMEM;
570         err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
571                                        /*wildcard=*/false);
572         parse_events_terms__delete($4);
573         if (err) {
574                 free(list);
575                 PE_ABORT(err);
576         }
577         $$ = list;
578 }
579
580 event_legacy_raw:
581 PE_RAW opt_event_config
582 {
583         struct list_head *list;
584         int err;
585         u64 num;
586
587         list = alloc_list();
588         if (!list)
589                 YYNOMEM;
590         errno = 0;
591         num = strtoull($1 + 1, NULL, 16);
592         /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
593         if (errno)
594                 YYABORT;
595         free($1);
596         err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
597                                        /*wildcard=*/false);
598         parse_events_terms__delete($2);
599         if (err) {
600                 free(list);
601                 PE_ABORT(err);
602         }
603         $$ = list;
604 }
605
606 opt_event_config:
607 '/' event_config '/'
608 {
609         $$ = $2;
610 }
611 |
612 '/' '/'
613 {
614         $$ = NULL;
615 }
616 |
617 {
618         $$ = NULL;
619 }
620
621 opt_pmu_config:
622 '/' event_config '/'
623 {
624         $$ = $2;
625 }
626 |
627 '/' '/'
628 {
629         $$ = NULL;
630 }
631
632 start_terms: event_config
633 {
634         struct parse_events_state *parse_state = _parse_state;
635         if (parse_state->terms) {
636                 parse_events_terms__delete ($1);
637                 YYABORT;
638         }
639         parse_state->terms = $1;
640 }
641
642 event_config:
643 event_config ',' event_term
644 {
645         struct parse_events_terms *head = $1;
646         struct parse_events_term *term = $3;
647
648         if (!head) {
649                 parse_events_term__delete(term);
650                 YYABORT;
651         }
652         list_add_tail(&term->list, &head->terms);
653         $$ = $1;
654 }
655 |
656 event_term
657 {
658         struct parse_events_terms *head = malloc(sizeof(*head));
659         struct parse_events_term *term = $1;
660
661         if (!head)
662                 YYNOMEM;
663         parse_events_terms__init(head);
664         list_add_tail(&term->list, &head->terms);
665         $$ = head;
666 }
667
668 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
669
670 event_term:
671 PE_RAW
672 {
673         struct parse_events_term *term;
674         int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
675                                          strdup("raw"), $1, &@1, &@1);
676
677         if (err) {
678                 free($1);
679                 PE_ABORT(err);
680         }
681         $$ = term;
682 }
683 |
684 name_or_raw '=' name_or_raw
685 {
686         struct parse_events_term *term;
687         int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
688
689         if (err) {
690                 free($1);
691                 free($3);
692                 PE_ABORT(err);
693         }
694         $$ = term;
695 }
696 |
697 name_or_raw '=' PE_VALUE
698 {
699         struct parse_events_term *term;
700         int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
701                                          $1, $3, /*novalue=*/false, &@1, &@3);
702
703         if (err) {
704                 free($1);
705                 PE_ABORT(err);
706         }
707         $$ = term;
708 }
709 |
710 name_or_raw '=' PE_TERM_HW
711 {
712         struct parse_events_term *term;
713         int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
714                                          $1, $3.str, &@1, &@3);
715
716         if (err) {
717                 free($1);
718                 free($3.str);
719                 PE_ABORT(err);
720         }
721         $$ = term;
722 }
723 |
724 PE_LEGACY_CACHE
725 {
726         struct parse_events_term *term;
727         int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
728                                          $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
729
730         if (err) {
731                 free($1);
732                 PE_ABORT(err);
733         }
734         $$ = term;
735 }
736 |
737 PE_NAME
738 {
739         struct parse_events_term *term;
740         int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
741                                          $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL);
742
743         if (err) {
744                 free($1);
745                 PE_ABORT(err);
746         }
747         $$ = term;
748 }
749 |
750 PE_TERM_HW
751 {
752         struct parse_events_term *term;
753         int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
754                                          $1.str, $1.num & 255, /*novalue=*/false,
755                                          &@1, /*loc_val=*/NULL);
756
757         if (err) {
758                 free($1.str);
759                 PE_ABORT(err);
760         }
761         $$ = term;
762 }
763 |
764 PE_TERM '=' name_or_raw
765 {
766         struct parse_events_term *term;
767         int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3);
768
769         if (err) {
770                 free($3);
771                 PE_ABORT(err);
772         }
773         $$ = term;
774 }
775 |
776 PE_TERM '=' PE_TERM_HW
777 {
778         struct parse_events_term *term;
779         int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3.str, &@1, &@3);
780
781         if (err) {
782                 free($3.str);
783                 PE_ABORT(err);
784         }
785         $$ = term;
786 }
787 |
788 PE_TERM '=' PE_TERM
789 {
790         struct parse_events_term *term;
791         int err = parse_events_term__term(&term, $1, $3, &@1, &@3);
792
793         if (err)
794                 PE_ABORT(err);
795
796         $$ = term;
797 }
798 |
799 PE_TERM '=' PE_VALUE
800 {
801         struct parse_events_term *term;
802         int err = parse_events_term__num(&term, $1,
803                                          /*config=*/NULL, $3, /*novalue=*/false,
804                                          &@1, &@3);
805
806         if (err)
807                 PE_ABORT(err);
808
809         $$ = term;
810 }
811 |
812 PE_TERM
813 {
814         struct parse_events_term *term;
815         int err = parse_events_term__num(&term, $1,
816                                          /*config=*/NULL, /*num=*/1, /*novalue=*/true,
817                                          &@1, /*loc_val=*/NULL);
818
819         if (err)
820                 PE_ABORT(err);
821
822         $$ = term;
823 }
824 |
825 PE_DRV_CFG_TERM
826 {
827         struct parse_events_term *term;
828         char *config = strdup($1);
829         int err;
830
831         if (!config)
832                 YYNOMEM;
833         err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL);
834         if (err) {
835                 free($1);
836                 free(config);
837                 PE_ABORT(err);
838         }
839         $$ = term;
840 }
841
842 sep_dc: ':' |
843
844 sep_slash_slash_dc: '/' '/' | ':' |
845
846 %%
847
848 void parse_events_error(YYLTYPE *loc, void *parse_state,
849                         void *scanner __maybe_unused,
850                         char const *msg __maybe_unused)
851 {
852         parse_events_evlist_error(parse_state, loc->last_column, "parser error");
853 }