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 17extern int parse_events_lex (YYSTYPE* lvalp, void* scanner); 18 19#define ABORT_ON(val) \ 20do { \ 21 if (val) \ 22 YYABORT; \ 23} while (0) 24 25#define ALLOC_LIST(list) \ 26do { \ 27 list = malloc(sizeof(*list)); \ 28 ABORT_ON(!list); \ 29 INIT_LIST_HEAD(list); \ 30} while (0) 31 32static 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 91start: 92PE_START_EVENTS start_events 93| 94PE_START_TERMS start_terms 95 96start_events: groups 97{ 98 struct parse_events_evlist *data = _data; 99 100 parse_events_update_lists($1, &data->list); 101} 102 103groups: 104groups ',' 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| 113groups ',' 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| 122group 123| 124event 125 126group: 127group_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| 135group_def 136 137group_def: 138PE_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 156events: 157events ',' 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| 166event 167 168event: event_mod 169 170event_mod: 171event_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| 184event_name 185 186event_name: 187PE_EVENT_NAME event_def 188{ 189 ABORT_ON(parse_events_name($2, $1)); 190 free($1); 191 $$ = $2; 192} 193| 194event_def 195 196event_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 204event_pmu: 205PE_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| 216PE_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| 226PE_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| 244PE_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 264value_sym: 265PE_VALUE_SYM_HW 266| 267PE_VALUE_SYM_SW 268 269event_legacy_symbol: 270value_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| 284value_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 297event_legacy_cache: 298PE_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| 308PE_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| 318PE_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 328event_legacy_mem: 329PE_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| 340PE_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| 351PE_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| 362PE_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 373event_legacy_tracepoint: 374PE_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| 386PE_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 396event_legacy_numeric: 397PE_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 407event_legacy_raw: 408PE_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 419start_terms: event_config 420{ 421 struct parse_events_terms *data = _data; 422 data->terms = $1; 423} 424 425event_config: 426event_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| 436event_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 447event_term: 448PE_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| 457PE_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| 466PE_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| 475PE_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| 484PE_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| 493PE_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| 501PE_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| 509PE_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 517sep_dc: ':' | 518 519sep_slash_dc: '/' | ':' | 520 521%% 522 523void parse_events_error(void *data __maybe_unused, void *scanner __maybe_unused, 524 char const *msg __maybe_unused) 525{ 526} 527