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