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