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_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, $4)); 337 $$ = list; 338 } 339 | 340 PE_PREFIX_MEM 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)); 348 $$ = list; 349 } 350 351 event_legacy_tracepoint: 352 PE_NAME '-' PE_NAME ':' PE_NAME 353 { 354 struct parse_events_evlist *data = _data; 355 struct list_head *list; 356 char sys_name[128]; 357 snprintf(&sys_name, 128, "%s-%s", $1, $3); 358 359 ALLOC_LIST(list); 360 ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5)); 361 $$ = list; 362 } 363 | 364 PE_NAME ':' PE_NAME 365 { 366 struct parse_events_evlist *data = _data; 367 struct list_head *list; 368 369 ALLOC_LIST(list); 370 ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3)); 371 $$ = list; 372 } 373 374 event_legacy_numeric: 375 PE_VALUE ':' PE_VALUE 376 { 377 struct parse_events_evlist *data = _data; 378 struct list_head *list; 379 380 ALLOC_LIST(list); 381 ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL)); 382 $$ = list; 383 } 384 385 event_legacy_raw: 386 PE_RAW 387 { 388 struct parse_events_evlist *data = _data; 389 struct list_head *list; 390 391 ALLOC_LIST(list); 392 ABORT_ON(parse_events_add_numeric(list, &data->idx, 393 PERF_TYPE_RAW, $1, NULL)); 394 $$ = list; 395 } 396 397 start_terms: event_config 398 { 399 struct parse_events_terms *data = _data; 400 data->terms = $1; 401 } 402 403 event_config: 404 event_config ',' event_term 405 { 406 struct list_head *head = $1; 407 struct parse_events_term *term = $3; 408 409 ABORT_ON(!head); 410 list_add_tail(&term->list, head); 411 $$ = $1; 412 } 413 | 414 event_term 415 { 416 struct list_head *head = malloc(sizeof(*head)); 417 struct parse_events_term *term = $1; 418 419 ABORT_ON(!head); 420 INIT_LIST_HEAD(head); 421 list_add_tail(&term->list, head); 422 $$ = head; 423 } 424 425 event_term: 426 PE_NAME '=' PE_NAME 427 { 428 struct parse_events_term *term; 429 430 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, 431 $1, $3)); 432 $$ = term; 433 } 434 | 435 PE_NAME '=' PE_VALUE 436 { 437 struct parse_events_term *term; 438 439 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 440 $1, $3)); 441 $$ = term; 442 } 443 | 444 PE_NAME '=' PE_VALUE_SYM_HW 445 { 446 struct parse_events_term *term; 447 int config = $3 & 255; 448 449 ABORT_ON(parse_events_term__sym_hw(&term, $1, config)); 450 $$ = term; 451 } 452 | 453 PE_NAME 454 { 455 struct parse_events_term *term; 456 457 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 458 $1, 1)); 459 $$ = term; 460 } 461 | 462 PE_VALUE_SYM_HW 463 { 464 struct parse_events_term *term; 465 int config = $1 & 255; 466 467 ABORT_ON(parse_events_term__sym_hw(&term, NULL, config)); 468 $$ = term; 469 } 470 | 471 PE_TERM '=' PE_NAME 472 { 473 struct parse_events_term *term; 474 475 ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3)); 476 $$ = term; 477 } 478 | 479 PE_TERM '=' PE_VALUE 480 { 481 struct parse_events_term *term; 482 483 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3)); 484 $$ = term; 485 } 486 | 487 PE_TERM 488 { 489 struct parse_events_term *term; 490 491 ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1)); 492 $$ = term; 493 } 494 495 sep_dc: ':' | 496 497 sep_slash_dc: '/' | ':' | 498 499 %% 500 501 void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, 502 char const *msg __maybe_unused) 503 { 504 } 505