Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.15 762 lines 14 kB view raw
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 22int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner); 23void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg); 24 25#define PE_ABORT(val) \ 26do { \ 27 if (val == -ENOMEM) \ 28 YYNOMEM; \ 29 YYABORT; \ 30} while (0) 31 32static 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 44static 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_EVENT_NAME 60%token PE_RAW PE_NAME 61%token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH 62%token PE_LEGACY_CACHE 63%token PE_PREFIX_MEM 64%token PE_ERROR 65%token PE_DRV_CFG_TERM 66%token PE_TERM_HW 67%type <num> PE_VALUE 68%type <num> PE_VALUE_SYM_HW 69%type <num> PE_VALUE_SYM_SW 70%type <mod> PE_MODIFIER_EVENT 71%type <term_type> PE_TERM 72%type <num> value_sym 73%type <str> PE_RAW 74%type <str> PE_NAME 75%type <str> PE_LEGACY_CACHE 76%type <str> PE_MODIFIER_BP 77%type <str> PE_EVENT_NAME 78%type <str> PE_DRV_CFG_TERM 79%type <str> name_or_raw 80%destructor { free ($$); } <str> 81%type <term> event_term 82%destructor { parse_events_term__delete ($$); } <term> 83%type <list_terms> event_config 84%type <list_terms> opt_event_config 85%type <list_terms> opt_pmu_config 86%destructor { parse_events_terms__delete ($$); } <list_terms> 87%type <list_evsel> event_pmu 88%type <list_evsel> event_legacy_symbol 89%type <list_evsel> event_legacy_cache 90%type <list_evsel> event_legacy_mem 91%type <list_evsel> event_legacy_tracepoint 92%type <list_evsel> event_legacy_numeric 93%type <list_evsel> event_legacy_raw 94%type <list_evsel> event_def 95%type <list_evsel> event_mod 96%type <list_evsel> event_name 97%type <list_evsel> event 98%type <list_evsel> events 99%type <list_evsel> group_def 100%type <list_evsel> group 101%type <list_evsel> groups 102%destructor { free_list_evsel ($$); } <list_evsel> 103%type <tracepoint_name> tracepoint_name 104%destructor { free ($$.sys); free ($$.event); } <tracepoint_name> 105%type <hardware_term> PE_TERM_HW 106%destructor { free ($$.str); } <hardware_term> 107 108%union 109{ 110 char *str; 111 u64 num; 112 struct parse_events_modifier mod; 113 enum parse_events__term_type term_type; 114 struct list_head *list_evsel; 115 struct parse_events_terms *list_terms; 116 struct parse_events_term *term; 117 struct tracepoint_name { 118 char *sys; 119 char *event; 120 } tracepoint_name; 121 struct hardware_term { 122 char *str; 123 u64 num; 124 } hardware_term; 125} 126%% 127 128 /* 129 * Entry points. We are either parsing events or terminals. Just terminal 130 * parsing is used for parsing events in sysfs. 131 */ 132start: 133PE_START_EVENTS start_events 134| 135PE_START_TERMS start_terms 136 137start_events: groups 138{ 139 /* Take the parsed events, groups.. and place into parse_state. */ 140 struct list_head *groups = $1; 141 struct parse_events_state *parse_state = _parse_state; 142 143 list_splice_tail(groups, &parse_state->list); 144 free(groups); 145} 146 147groups: /* A list of groups or events. */ 148groups ',' group 149{ 150 /* Merge group into the list of events/groups. */ 151 struct list_head *groups = $1; 152 struct list_head *group = $3; 153 154 list_splice_tail(group, groups); 155 free(group); 156 $$ = groups; 157} 158| 159groups ',' event 160{ 161 /* Merge event into the list of events/groups. */ 162 struct list_head *groups = $1; 163 struct list_head *event = $3; 164 165 166 list_splice_tail(event, groups); 167 free(event); 168 $$ = groups; 169} 170| 171group 172| 173event 174 175group: 176group_def ':' PE_MODIFIER_EVENT 177{ 178 /* Apply the modifier to the events in the group_def. */ 179 struct list_head *list = $1; 180 int err; 181 182 err = parse_events__modifier_group(_parse_state, &@3, list, $3); 183 if (err) 184 YYABORT; 185 $$ = list; 186} 187| 188group_def 189 190group_def: 191PE_NAME '{' events '}' 192{ 193 struct list_head *list = $3; 194 195 /* 196 * Set the first entry of list to be the leader. Set the group name on 197 * the leader to $1 taking ownership. 198 */ 199 parse_events__set_leader($1, list); 200 $$ = list; 201} 202| 203'{' events '}' 204{ 205 struct list_head *list = $2; 206 207 /* Set the first entry of list to be the leader clearing the group name. */ 208 parse_events__set_leader(NULL, list); 209 $$ = list; 210} 211 212events: 213events ',' event 214{ 215 struct list_head *events = $1; 216 struct list_head *event = $3; 217 218 list_splice_tail(event, events); 219 free(event); 220 $$ = events; 221} 222| 223event 224 225event: event_mod 226 227event_mod: 228event_name PE_MODIFIER_EVENT 229{ 230 struct list_head *list = $1; 231 int err; 232 233 /* 234 * Apply modifier on all events added by single event definition 235 * (there could be more events added for multiple tracepoint 236 * definitions via '*?'. 237 */ 238 err = parse_events__modifier_event(_parse_state, &@2, list, $2); 239 if (err) 240 YYABORT; 241 $$ = list; 242} 243| 244event_name 245 246event_name: 247PE_EVENT_NAME event_def 248{ 249 /* 250 * When an event is parsed the text is rewound and the entire text of 251 * the event is set to the str of PE_EVENT_NAME token matched here. If 252 * no name was on an event via a term, set the name to the entire text 253 * taking ownership of the allocation. 254 */ 255 int err = parse_events__set_default_name($2, $1); 256 257 if (err) { 258 free_list_evsel($2); 259 YYNOMEM; 260 } 261 $$ = $2; 262} 263| 264event_def 265 266event_def: event_pmu | 267 event_legacy_symbol | 268 event_legacy_cache sep_dc | 269 event_legacy_mem sep_dc | 270 event_legacy_tracepoint sep_dc | 271 event_legacy_numeric sep_dc | 272 event_legacy_raw sep_dc 273 274event_pmu: 275PE_NAME opt_pmu_config 276{ 277 /* List of created evsels. */ 278 struct list_head *list = NULL; 279 int err = parse_events_multi_pmu_add_or_add_pmu(_parse_state, $1, $2, &list, &@1); 280 281 parse_events_terms__delete($2); 282 free($1); 283 if (err) 284 PE_ABORT(err); 285 $$ = list; 286} 287| 288PE_NAME sep_dc 289{ 290 struct list_head *list; 291 int err; 292 293 err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1); 294 if (err < 0) { 295 struct parse_events_state *parse_state = _parse_state; 296 struct parse_events_error *error = parse_state->error; 297 char *help; 298 299 if (asprintf(&help, "Unable to find event on a PMU of '%s'", $1) < 0) 300 help = NULL; 301 parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help); 302 free($1); 303 PE_ABORT(err); 304 } 305 free($1); 306 $$ = list; 307} 308 309value_sym: 310PE_VALUE_SYM_HW 311| 312PE_VALUE_SYM_SW 313 314event_legacy_symbol: 315value_sym '/' event_config '/' 316{ 317 struct list_head *list; 318 int type = $1 >> 16; 319 int config = $1 & 255; 320 int err; 321 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 322 323 list = alloc_list(); 324 if (!list) 325 YYNOMEM; 326 err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard); 327 parse_events_terms__delete($3); 328 if (err) { 329 free_list_evsel(list); 330 PE_ABORT(err); 331 } 332 $$ = list; 333} 334| 335value_sym sep_slash_slash_dc 336{ 337 struct list_head *list; 338 int type = $1 >> 16; 339 int config = $1 & 255; 340 bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE); 341 int err; 342 343 list = alloc_list(); 344 if (!list) 345 YYNOMEM; 346 err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard); 347 if (err) 348 PE_ABORT(err); 349 $$ = list; 350} 351 352event_legacy_cache: 353PE_LEGACY_CACHE opt_event_config 354{ 355 struct parse_events_state *parse_state = _parse_state; 356 struct list_head *list; 357 int err; 358 359 list = alloc_list(); 360 if (!list) 361 YYNOMEM; 362 363 err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2); 364 365 parse_events_terms__delete($2); 366 free($1); 367 if (err) { 368 free_list_evsel(list); 369 PE_ABORT(err); 370 } 371 $$ = list; 372} 373 374event_legacy_mem: 375PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 376{ 377 struct list_head *list; 378 int err; 379 380 list = alloc_list(); 381 if (!list) 382 YYNOMEM; 383 384 err = parse_events_add_breakpoint(_parse_state, list, 385 $2, $6, $4, $7); 386 parse_events_terms__delete($7); 387 free($6); 388 if (err) { 389 free(list); 390 PE_ABORT(err); 391 } 392 $$ = list; 393} 394| 395PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config 396{ 397 struct list_head *list; 398 int err; 399 400 list = alloc_list(); 401 if (!list) 402 YYNOMEM; 403 404 err = parse_events_add_breakpoint(_parse_state, list, 405 $2, NULL, $4, $5); 406 parse_events_terms__delete($5); 407 if (err) { 408 free(list); 409 PE_ABORT(err); 410 } 411 $$ = list; 412} 413| 414PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config 415{ 416 struct list_head *list; 417 int err; 418 419 list = alloc_list(); 420 if (!list) 421 YYNOMEM; 422 423 err = parse_events_add_breakpoint(_parse_state, list, 424 $2, $4, 0, $5); 425 parse_events_terms__delete($5); 426 free($4); 427 if (err) { 428 free(list); 429 PE_ABORT(err); 430 } 431 $$ = list; 432} 433| 434PE_PREFIX_MEM PE_VALUE opt_event_config 435{ 436 struct list_head *list; 437 int err; 438 439 list = alloc_list(); 440 if (!list) 441 YYNOMEM; 442 err = parse_events_add_breakpoint(_parse_state, list, 443 $2, NULL, 0, $3); 444 parse_events_terms__delete($3); 445 if (err) { 446 free(list); 447 PE_ABORT(err); 448 } 449 $$ = list; 450} 451 452event_legacy_tracepoint: 453tracepoint_name opt_event_config 454{ 455 struct parse_events_state *parse_state = _parse_state; 456 struct parse_events_error *error = parse_state->error; 457 struct list_head *list; 458 int err; 459 460 list = alloc_list(); 461 if (!list) 462 YYNOMEM; 463 464 err = parse_events_add_tracepoint(parse_state, list, $1.sys, $1.event, 465 error, $2, &@1); 466 467 parse_events_terms__delete($2); 468 free($1.sys); 469 free($1.event); 470 if (err) { 471 free(list); 472 PE_ABORT(err); 473 } 474 $$ = list; 475} 476 477tracepoint_name: 478PE_NAME ':' PE_NAME 479{ 480 struct tracepoint_name tracepoint = {$1, $3}; 481 482 $$ = tracepoint; 483} 484 485event_legacy_numeric: 486PE_VALUE ':' PE_VALUE opt_event_config 487{ 488 struct list_head *list; 489 int err; 490 491 list = alloc_list(); 492 if (!list) 493 YYNOMEM; 494 err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4, 495 /*wildcard=*/false); 496 parse_events_terms__delete($4); 497 if (err) { 498 free(list); 499 PE_ABORT(err); 500 } 501 $$ = list; 502} 503 504event_legacy_raw: 505PE_RAW opt_event_config 506{ 507 struct list_head *list; 508 int err; 509 u64 num; 510 511 list = alloc_list(); 512 if (!list) 513 YYNOMEM; 514 errno = 0; 515 num = strtoull($1 + 1, NULL, 16); 516 /* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */ 517 if (errno) 518 YYABORT; 519 free($1); 520 err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2, 521 /*wildcard=*/false); 522 parse_events_terms__delete($2); 523 if (err) { 524 free(list); 525 PE_ABORT(err); 526 } 527 $$ = list; 528} 529 530opt_event_config: 531'/' event_config '/' 532{ 533 $$ = $2; 534} 535| 536'/' '/' 537{ 538 $$ = NULL; 539} 540| 541{ 542 $$ = NULL; 543} 544 545opt_pmu_config: 546'/' event_config '/' 547{ 548 $$ = $2; 549} 550| 551'/' '/' 552{ 553 $$ = NULL; 554} 555 556start_terms: event_config 557{ 558 struct parse_events_state *parse_state = _parse_state; 559 if (parse_state->terms) { 560 parse_events_terms__delete ($1); 561 YYABORT; 562 } 563 parse_state->terms = $1; 564} 565 566event_config: 567event_config ',' event_term 568{ 569 struct parse_events_terms *head = $1; 570 struct parse_events_term *term = $3; 571 572 if (!head) { 573 parse_events_term__delete(term); 574 YYABORT; 575 } 576 list_add_tail(&term->list, &head->terms); 577 $$ = $1; 578} 579| 580event_term 581{ 582 struct parse_events_terms *head = malloc(sizeof(*head)); 583 struct parse_events_term *term = $1; 584 585 if (!head) 586 YYNOMEM; 587 parse_events_terms__init(head); 588 list_add_tail(&term->list, &head->terms); 589 $$ = head; 590} 591 592name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE 593| 594PE_TERM_HW 595{ 596 $$ = $1.str; 597} 598 599event_term: 600PE_RAW 601{ 602 struct parse_events_term *term; 603 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW, 604 strdup("raw"), $1, &@1, &@1); 605 606 if (err) { 607 free($1); 608 PE_ABORT(err); 609 } 610 $$ = term; 611} 612| 613name_or_raw '=' name_or_raw 614{ 615 struct parse_events_term *term; 616 int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3); 617 618 if (err) { 619 free($1); 620 free($3); 621 PE_ABORT(err); 622 } 623 $$ = term; 624} 625| 626name_or_raw '=' PE_VALUE 627{ 628 struct parse_events_term *term; 629 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 630 $1, $3, /*novalue=*/false, &@1, &@3); 631 632 if (err) { 633 free($1); 634 PE_ABORT(err); 635 } 636 $$ = term; 637} 638| 639PE_LEGACY_CACHE 640{ 641 struct parse_events_term *term; 642 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE, 643 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL); 644 645 if (err) { 646 free($1); 647 PE_ABORT(err); 648 } 649 $$ = term; 650} 651| 652PE_NAME 653{ 654 struct parse_events_term *term; 655 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER, 656 $1, /*num=*/1, /*novalue=*/true, &@1, /*loc_val=*/NULL); 657 658 if (err) { 659 free($1); 660 PE_ABORT(err); 661 } 662 $$ = term; 663} 664| 665PE_TERM_HW 666{ 667 struct parse_events_term *term; 668 int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE, 669 $1.str, $1.num & 255, /*novalue=*/false, 670 &@1, /*loc_val=*/NULL); 671 672 if (err) { 673 free($1.str); 674 PE_ABORT(err); 675 } 676 $$ = term; 677} 678| 679PE_TERM '=' name_or_raw 680{ 681 struct parse_events_term *term; 682 int err = parse_events_term__str(&term, $1, /*config=*/NULL, $3, &@1, &@3); 683 684 if (err) { 685 free($3); 686 PE_ABORT(err); 687 } 688 $$ = term; 689} 690| 691PE_TERM '=' PE_TERM 692{ 693 struct parse_events_term *term; 694 int err = parse_events_term__term(&term, $1, $3, &@1, &@3); 695 696 if (err) 697 PE_ABORT(err); 698 699 $$ = term; 700} 701| 702PE_TERM '=' PE_VALUE 703{ 704 struct parse_events_term *term; 705 int err = parse_events_term__num(&term, $1, 706 /*config=*/NULL, $3, /*novalue=*/false, 707 &@1, &@3); 708 709 if (err) 710 PE_ABORT(err); 711 712 $$ = term; 713} 714| 715PE_TERM 716{ 717 struct parse_events_term *term; 718 int err = parse_events_term__num(&term, $1, 719 /*config=*/NULL, /*num=*/1, /*novalue=*/true, 720 &@1, /*loc_val=*/NULL); 721 722 if (err) 723 PE_ABORT(err); 724 725 $$ = term; 726} 727| 728PE_DRV_CFG_TERM 729{ 730 struct parse_events_term *term; 731 char *config = strdup($1); 732 int err; 733 734 if (!config) 735 YYNOMEM; 736 err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG, config, $1, &@1, NULL); 737 if (err) { 738 free($1); 739 free(config); 740 PE_ABORT(err); 741 } 742 $$ = term; 743} 744 745sep_dc: ':' | 746 747sep_slash_slash_dc: '/' '/' | ':' | 748 749%% 750 751void parse_events_error(YYLTYPE *loc, void *_parse_state, 752 void *scanner __maybe_unused, 753 char const *msg __maybe_unused) 754{ 755 struct parse_events_state *parse_state = _parse_state; 756 757 if (!parse_state->error || !list_empty(&parse_state->error->list)) 758 return; 759 760 parse_events_error__handle(parse_state->error, loc->last_column, 761 strdup("Unrecognized input"), NULL); 762}