1 %pure-parser 2 %parse-param {void *_data} 3 %parse-param {void *scanner} 4 %lex-param {void* scanner} 5 6 %{ 7 8 #define YYDEBUG 1 9 10 #include <linux/compiler.h> 11 #include <linux/list.h> 12 #include <linux/types.h> 13 #include "util.h" 14 #include "parse-events.h" 15 #include "parse-events-bison.h" 16 17 extern int parse_events_lex (YYSTYPE* lvalp, void* scanner); 18 19 #define ABORT_ON(val) \ 20 do { \ 21 if (val) \ 22 YYABORT; \ 23 } while (0) 24 25 #define ALLOC_LIST(list) \ 26 do { \ 27 list = malloc(sizeof(*list)); \ 28 ABORT_ON(!list); \ 29 INIT_LIST_HEAD(list); \ 30 } while (0) 31 32 static inc_group_count(struct list_head *list, 33 struct parse_events_evlist *data) 34 { 35 /* Count groups only have more than 1 members */ 36 if (!list_is_last(list->next, list)) 37 data->nr_groups++; 38 } 39 40 %} 41 42 %token PE_START_EVENTS PE_START_TERMS 43 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM 44 %token PE_EVENT_NAME 45 %token PE_NAME 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_NAME_CACHE_TYPE 58 %type <str> PE_NAME_CACHE_OP_RESULT 59 %type <str> PE_MODIFIER_EVENT 60 %type <str> PE_MODIFIER_BP 61 %type <str> PE_EVENT_NAME 62 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 63 %type <num> value_sym 64 %type <head> event_config 65 %type <term> event_term 66 %type <head> event_pmu 67 %type <head> event_legacy_symbol 68 %type <head> event_legacy_cache 69 %type <head> event_legacy_mem 70 %type <head> event_legacy_tracepoint 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 } 89 %% 90 91 start: 92 PE_START_EVENTS start_events 93 | 94 PE_START_TERMS start_terms 95 96 start_events: groups 97 { 98 struct parse_events_evlist *data = _data; 99 100 parse_events_update_lists($1, &data->list); 101 } 102 103 groups: 104 groups ',' group 105 { 106 struct list_head *list = $1; 107 struct list_head *group = $3; 108 109 parse_events_update_lists(group, list); 110 $$ = list; 111 } 112 | 113 groups ',' event 114 { 115 struct list_head *list = $1; 116 struct list_head *event = $3; 117 118 parse_events_update_lists(event, list); 119 $$ = list; 120 } 121 | 122 group 123 | 124 event 125 126 group: 127 group_def ':' PE_MODIFIER_EVENT 128 { 129 struct list_head *list = $1; 130 131 ABORT_ON(parse_events__modifier_group(list, $3)); 132 $$ = list; 133 } 134 | 135 group_def 136 137 group_def: 138 PE_NAME '{' events '}' 139 { 140 struct list_head *list = $3; 141 142 inc_group_count(list, _data); 143 parse_events__set_leader($1, list); 144 $$ = list; 145 } 146 | 147 '{' events '}' 148 { 149 struct list_head *list = $2; 150 151 inc_group_count(list, _data); 152 parse_events__set_leader(NULL, list); 153 $$ = list; 154 } 155 156 events: 157 events ',' event 158 { 159 struct list_head *event = $3; 160 struct list_head *list = $1; 161 162 parse_events_update_lists(event, list); 163 $$ = list; 164 } 165 | 166 event 167 168 event: event_mod 169 170 event_mod: 171 event_name PE_MODIFIER_EVENT 172 { 173 struct list_head *list = $1; 174 175 /* 176 * Apply modifier on all events added by single event definition 177 * (there could be more events added for multiple tracepoint 178 * definitions via '*?'. 179 */ 180 ABORT_ON(parse_events__modifier_event(list, $2, false)); 181 $$ = list; 182 } 183 | 184 event_name 185 186 event_name: 187 PE_EVENT_NAME event_def 188 { 189 ABORT_ON(parse_events_name($2, $1)); 190 free($1); 191 $$ = $2; 192 } 193 | 194 event_def 195 196 event_def: event_pmu | 197 event_legacy_symbol | 198 event_legacy_cache sep_dc | 199 event_legacy_mem | 200 event_legacy_tracepoint sep_dc | 201 event_legacy_numeric sep_dc | 202 event_legacy_raw sep_dc 203 204 event_pmu: 205 PE_NAME '/' event_config '/' 206 { 207 struct parse_events_evlist *data = _data; 208 struct list_head *list; 209 210 ALLOC_LIST(list); 211 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3)); 212 parse_events__free_terms($3); 213 $$ = list; 214 } 215 | 216 PE_NAME '/' '/' 217 { 218 struct parse_events_evlist *data = _data; 219 struct list_head *list; 220 221 ALLOC_LIST(list); 222 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL)); 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)); 236 list_add_tail(&term->list, head); 237 238 ALLOC_LIST(list); 239 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head)); 240 parse_events__free_terms(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)); 256 list_add_tail(&term->list, head); 257 258 ALLOC_LIST(list); 259 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head)); 260 parse_events__free_terms(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(list, &data->idx, 279 type, config, $3)); 280 parse_events__free_terms($3); 281 $$ = list; 282 } 283 | 284 value_sym sep_slash_dc 285 { 286 struct parse_events_evlist *data = _data; 287 struct list_head *list; 288 int type = $1 >> 16; 289 int config = $1 & 255; 290 291 ALLOC_LIST(list); 292 ABORT_ON(parse_events_add_numeric(list, &data->idx, 293 type, config, NULL)); 294 $$ = list; 295 } 296 297 event_legacy_cache: 298 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT 299 { 300 struct parse_events_evlist *data = _data; 301 struct list_head *list; 302 303 ALLOC_LIST(list); 304 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5)); 305 $$ = list; 306 } 307 | 308 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT 309 { 310 struct parse_events_evlist *data = _data; 311 struct list_head *list; 312 313 ALLOC_LIST(list); 314 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL)); 315 $$ = list; 316 } 317 | 318 PE_NAME_CACHE_TYPE 319 { 320 struct parse_events_evlist *data = _data; 321 struct list_head *list; 322 323 ALLOC_LIST(list); 324 ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL)); 325 $$ = list; 326 } 327 328 event_legacy_mem: 329 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc 330 { 331 struct parse_events_evlist *data = _data; 332 struct list_head *list; 333 334 ALLOC_LIST(list); 335 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 336 (void *) $2, $6, $4)); 337 $$ = list; 338 } 339 | 340 PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc 341 { 342 struct parse_events_evlist *data = _data; 343 struct list_head *list; 344 345 ALLOC_LIST(list); 346 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 347 (void *) $2, NULL, $4)); 348 $$ = list; 349 } 350 | 351 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc 352 { 353 struct parse_events_evlist *data = _data; 354 struct list_head *list; 355 356 ALLOC_LIST(list); 357 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 358 (void *) $2, $4, 0)); 359 $$ = list; 360 } 361 | 362 PE_PREFIX_MEM PE_VALUE sep_dc 363 { 364 struct parse_events_evlist *data = _data; 365 struct list_head *list; 366 367 ALLOC_LIST(list); 368 ABORT_ON(parse_events_add_breakpoint(list, &data->idx, 369 (void *) $2, NULL, 0)); 370 $$ = list; 371 } 372 373 event_legacy_tracepoint: 374 PE_NAME '-' PE_NAME ':' PE_NAME 375 { 376 struct parse_events_evlist *data = _data; 377 struct list_head *list; 378 char sys_name[128]; 379 snprintf(&sys_name, 128, "%s-%s", $1, $3); 380 381 ALLOC_LIST(list); 382 ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5)); 383 $$ = list; 384 } 385 | 386 PE_NAME ':' PE_NAME 387 { 388 struct parse_events_evlist *data = _data; 389 struct list_head *list; 390 391 ALLOC_LIST(list); 392 ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3)); 393 $$ = list; 394 } 395 396 event_legacy_numeric: 397 PE_VALUE ':' PE_VALUE 398 { 399 struct parse_events_evlist *data = _data; 400 struct list_head *list; 401 402 ALLOC_LIST(list); 403 ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL)); 404 $$ = list; 405 } 406 407 event_legacy_raw: 408 PE_RAW 409 { 410 struct parse_events_evlist *data = _data; 411 struct list_head *list; 412 413 ALLOC_LIST(list); 414 ABORT_ON(parse_events_add_numeric(list, &data->idx, 415 PERF_TYPE_RAW, $1, NULL)); 416 $$ = list; 417 } 418 419 start_terms: event_config 420 { 421 struct parse_events_terms *data = _data; 422 data->terms = $1; 423 } 424 425 event_config: 426 event_config ',' event_term 427 { 428 struct list_head *head = $1; 429 struct parse_events_term *term = $3; 430 431 ABORT_ON(!head); 432 list_add_tail(&term->list, head); 433 $$ = $1; 434 } 435 | 436 event_term 437 { 438 struct list_head *head = malloc(sizeof(*head)); 439 struct parse_events_term *term = $1; 440 441 ABORT_ON(!head); 442 INIT_LIST_HEAD(head); 443 list_add_tail(&term->list, head); 444 $$ = head; 445 } 446 447 event_term: 448 PE_NAME '=' PE_NAME 449 { 450 struct parse_events_term *term; 451 452 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 453 $1, $3)); 454 $$ = term; 455 } 456 | 457 PE_NAME '=' PE_VALUE 458 { 459 struct parse_events_term *term; 460 461 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 462 $1, $3)); 463 $$ = term; 464 } 465 | 466 PE_NAME '=' PE_VALUE_SYM_HW 467 { 468 struct parse_events_term *term; 469 int config = $3 & 255; 470 471 ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); 472 $$ = term; 473 } 474 | 475 PE_NAME 476 { 477 struct parse_events_term *term; 478 479 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 480 $1, 1)); 481 $$ = term; 482 } 483 | 484 PE_VALUE_SYM_HW 485 { 486 struct parse_events_term *term; 487 int config = $1 & 255; 488 489 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 490 $$ = term; 491 } 492 | 493 PE_TERM '=' PE_NAME 494 { 495 struct parse_events_term *term; 496 497 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3)); 498 $$ = term; 499 } 500 | 501 PE_TERM '=' PE_VALUE 502 { 503 struct parse_events_term *term; 504 505 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3)); 506 $$ = term; 507 } 508 | 509 PE_TERM 510 { 511 struct parse_events_term *term; 512 513 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1)); 514 $$ = term; 515 } 516 517 sep_dc: ':' | 518 519 sep_slash_dc: '/' | ':' | 520 521 %% 522 523 void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, 524 char const *msg __maybe_unused) 525 { 526 } 527