1 2 %option reentrant 3 %option bison-bridge 4 %option prefix="parse_events_" 5 %option stack 6 %option bison-locations 7 %option yylineno 8 %option reject 9 10 %{ 11 #include <errno.h> 12 #include <sys/types.h> 13 #include <sys/stat.h> 14 #include <unistd.h> 15 #include "parse-events.h" 16 #include "parse-events-bison.h" 17 #include "evsel.h" 18 19 char *parse_events_get_text(yyscan_t yyscanner); 20 YYSTYPE *parse_events_get_lval(yyscan_t yyscanner); 21 int parse_events_get_column(yyscan_t yyscanner); 22 int parse_events_get_leng(yyscan_t yyscanner); 23 24 static int get_column(yyscan_t scanner) 25 { 26 return parse_events_get_column(scanner) - parse_events_get_leng(scanner); 27 } 28 29 static int value(struct parse_events_state *parse_state, yyscan_t scanner, int base) 30 { 31 YYSTYPE *yylval = parse_events_get_lval(scanner); 32 char *text = parse_events_get_text(scanner); 33 u64 num; 34 35 errno = 0; 36 num = strtoull(text, NULL, base); 37 if (errno) { 38 struct parse_events_error *error = parse_state->error; 39 char *help = NULL; 40 41 if (asprintf(&help, "Bad base %d number \"%s\"", base, text) > 0) 42 parse_events_error__handle(error, get_column(scanner), help , NULL); 43 44 return PE_ERROR; 45 } 46 47 yylval->num = num; 48 return PE_VALUE; 49 } 50 51 static int str(yyscan_t scanner, int token) 52 { 53 YYSTYPE *yylval = parse_events_get_lval(scanner); 54 char *text = parse_events_get_text(scanner); 55 56 if (text[0] != '\'') { 57 yylval->str = strdup(text); 58 } else { 59 /* 60 * If a text tag specified on the command line 61 * contains opening single quite ' then it is 62 * expected that the tag ends with single quote 63 * as well, like this: 64 * name=\'CPU_CLK_UNHALTED.THREAD:cmask=1\' 65 * quotes need to be escaped to bypass shell 66 * processing. 67 */ 68 yylval->str = strndup(&text[1], strlen(text) - 2); 69 } 70 71 return token; 72 } 73 74 static int lc_str(yyscan_t scanner, const struct parse_events_state *state) 75 { 76 return str(scanner, state->match_legacy_cache_terms ? PE_LEGACY_CACHE : PE_NAME); 77 } 78 79 /* 80 * This function is called when the parser gets two kind of input: 81 * 82 * @cfg1 or @cfg2=config 83 * 84 * The leading '@' is stripped off before 'cfg1' and 'cfg2=config' are given to 85 * bison. In the latter case it is necessary to keep the string intact so that 86 * the PMU kernel driver can determine what configurable is associated to 87 * 'config'. 88 */ 89 static int drv_str(yyscan_t scanner, int token) 90 { 91 YYSTYPE *yylval = parse_events_get_lval(scanner); 92 char *text = parse_events_get_text(scanner); 93 94 /* Strip off the '@' */ 95 yylval->str = strdup(text + 1); 96 return token; 97 } 98 99 /* 100 * Use yyless to return all the characaters to the input. Update the column for 101 * location debugging. If __alloc is non-zero set yylval to the text for the 102 * returned token's value. 103 */ 104 #define REWIND(__alloc) \ 105 do { \ 106 YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \ 107 char *text = parse_events_get_text(yyscanner); \ 108 \ 109 if (__alloc) \ 110 __yylval->str = strdup(text); \ 111 \ 112 yycolumn -= strlen(text); \ 113 yyless(0); \ 114 } while (0) 115 116 static int sym(yyscan_t scanner, int type, int config) 117 { 118 YYSTYPE *yylval = parse_events_get_lval(scanner); 119 120 yylval->num = (type << 16) + config; 121 return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW; 122 } 123 124 static int term(yyscan_t scanner, enum parse_events__term_type type) 125 { 126 YYSTYPE *yylval = parse_events_get_lval(scanner); 127 128 yylval->term_type = type; 129 return PE_TERM; 130 } 131 132 static int hw_term(yyscan_t scanner, int config) 133 { 134 YYSTYPE *yylval = parse_events_get_lval(scanner); 135 char *text = parse_events_get_text(scanner); 136 137 yylval->hardware_term.str = strdup(text); 138 yylval->hardware_term.num = PERF_TYPE_HARDWARE + config; 139 return PE_TERM_HW; 140 } 141 142 static void modifiers_error(struct parse_events_state *parse_state, yyscan_t scanner, 143 int pos, char mod_char, const char *mod_name) 144 { 145 struct parse_events_error *error = parse_state->error; 146 char *help = NULL; 147 148 if (asprintf(&help, "Duplicate modifier '%c' (%s)", mod_char, mod_name) > 0) 149 parse_events_error__handle(error, get_column(scanner) + pos, help , NULL); 150 } 151 152 static int modifiers(struct parse_events_state *parse_state, yyscan_t scanner) 153 { 154 YYSTYPE *yylval = parse_events_get_lval(scanner); 155 char *text = parse_events_get_text(scanner); 156 struct parse_events_modifier mod = { .precise = 0, }; 157 158 for (size_t i = 0, n = strlen(text); i < n; i++) { 159 #define CASE(c, field) \ 160 case c: \ 161 if (mod.field) { \ 162 modifiers_error(parse_state, scanner, i, c, #field); \ 163 return PE_ERROR; \ 164 } \ 165 mod.field = true; \ 166 break 167 168 switch (text[i]) { 169 CASE('u', user); 170 CASE('k', kernel); 171 CASE('h', hypervisor); 172 CASE('I', non_idle); 173 CASE('G', guest); 174 CASE('H', host); 175 case 'p': 176 mod.precise++; 177 /* 178 * precise ip: 179 * 180 * 0 - SAMPLE_IP can have arbitrary skid 181 * 1 - SAMPLE_IP must have constant skid 182 * 2 - SAMPLE_IP requested to have 0 skid 183 * 3 - SAMPLE_IP must have 0 skid 184 * 185 * See also PERF_RECORD_MISC_EXACT_IP 186 */ 187 if (mod.precise > 3) { 188 struct parse_events_error *error = parse_state->error; 189 char *help = strdup("Maximum precise value is 3"); 190 191 if (help) { 192 parse_events_error__handle(error, get_column(scanner) + i, 193 help , NULL); 194 } 195 return PE_ERROR; 196 } 197 break; 198 CASE('P', precise_max); 199 CASE('S', sample_read); 200 CASE('D', pinned); 201 CASE('W', weak); 202 CASE('e', exclusive); 203 CASE('b', bpf); 204 CASE('R', retire_lat); 205 default: 206 return PE_ERROR; 207 } 208 #undef CASE 209 } 210 yylval->mod = mod; 211 return PE_MODIFIER_EVENT; 212 } 213 214 #define YY_USER_ACTION \ 215 do { \ 216 yylloc->last_column = yylloc->first_column; \ 217 yylloc->first_column = yycolumn; \ 218 yycolumn += yyleng; \ 219 } while (0); 220 221 #define USER_REJECT \ 222 yycolumn -= yyleng; \ 223 REJECT 224 225 %} 226 227 %x mem 228 %s config 229 %x event 230 231 group [^,{}/]*[{][^}]*[}][^,{}/]* 232 event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* 233 event [^,{}/]+ 234 235 num_dec [0-9]+ 236 num_hex 0x[a-fA-F0-9]{1,16} 237 num_raw_hex [a-fA-F0-9]{1,16} 238 name [a-zA-Z0-9_*?\[\]][a-zA-Z0-9_*?.\[\]!\-]* 239 name_tag [\'][a-zA-Z0-9_*?\[\]][a-zA-Z0-9_*?\-,\.\[\]:=]*[\'] 240 name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 241 drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)? 242 /* 243 * If you add a modifier you need to update check_modifier(). 244 * Also, the letters in modifier_event must not be in modifier_bp. 245 */ 246 modifier_event [ukhpPGHSDIWebR]{1,16} 247 modifier_bp [rwx]{1,3} 248 lc_type (L1-dcache|l1-d|l1d|L1-data|L1-icache|l1-i|l1i|L1-instruction|LLC|L2|dTLB|d-tlb|Data-TLB|iTLB|i-tlb|Instruction-TLB|branch|branches|bpu|btb|bpc|node) 249 lc_op_result (load|loads|read|store|stores|write|prefetch|prefetches|speculative-read|speculative-load|refs|Reference|ops|access|misses|miss) 250 digit [0-9] 251 non_digit [^0-9] 252 253 %% 254 255 %{ 256 struct parse_events_state *_parse_state = parse_events_get_extra(yyscanner); 257 { 258 int start_token = _parse_state->stoken; 259 260 if (start_token == PE_START_TERMS) 261 BEGIN(config); 262 else if (start_token == PE_START_EVENTS) 263 BEGIN(event); 264 265 if (start_token) { 266 _parse_state->stoken = 0; 267 /* 268 * The flex parser does not init locations variable 269 * via the scan_string interface, so we need do the 270 * init in here. 271 */ 272 yycolumn = 0; 273 return start_token; 274 } 275 } 276 %} 277 278 <event>{ 279 280 {group} { 281 BEGIN(INITIAL); 282 REWIND(0); 283 } 284 285 {event_pmu} | 286 {event} { 287 BEGIN(INITIAL); 288 REWIND(1); 289 return PE_EVENT_NAME; 290 } 291 292 <<EOF>> { 293 BEGIN(INITIAL); 294 REWIND(0); 295 } 296 , { 297 return ','; 298 } 299 } 300 301 <config>{ 302 /* 303 * Please update config_term_names when new static term is added. 304 */ 305 config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } 306 config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); } 307 config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } 308 config3 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG3); } 309 name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } 310 period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } 311 freq { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ); } 312 branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 313 time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } 314 call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } 315 stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } 316 max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); } 317 nr { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_EVENTS); } 318 inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } 319 no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } 320 overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } 321 no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } 322 percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); } 323 aux-output { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); } 324 aux-sample-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); } 325 metric-id { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_METRIC_ID); } 326 cpu-cycles|cycles { return hw_term(yyscanner, PERF_COUNT_HW_CPU_CYCLES); } 327 stalled-cycles-frontend|idle-cycles-frontend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 328 stalled-cycles-backend|idle-cycles-backend { return hw_term(yyscanner, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 329 instructions { return hw_term(yyscanner, PERF_COUNT_HW_INSTRUCTIONS); } 330 cache-references { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_REFERENCES); } 331 cache-misses { return hw_term(yyscanner, PERF_COUNT_HW_CACHE_MISSES); } 332 branch-instructions|branches { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } 333 branch-misses { return hw_term(yyscanner, PERF_COUNT_HW_BRANCH_MISSES); } 334 bus-cycles { return hw_term(yyscanner, PERF_COUNT_HW_BUS_CYCLES); } 335 ref-cycles { return hw_term(yyscanner, PERF_COUNT_HW_REF_CPU_CYCLES); } 336 r{num_raw_hex} { return str(yyscanner, PE_RAW); } 337 r0x{num_raw_hex} { return str(yyscanner, PE_RAW); } 338 , { return ','; } 339 "/" { BEGIN(INITIAL); return '/'; } 340 {lc_type} { return lc_str(yyscanner, _parse_state); } 341 {lc_type}-{lc_op_result} { return lc_str(yyscanner, _parse_state); } 342 {lc_type}-{lc_op_result}-{lc_op_result} { return lc_str(yyscanner, _parse_state); } 343 {name_minus} { return str(yyscanner, PE_NAME); } 344 @{drv_cfg_term} { return drv_str(yyscanner, PE_DRV_CFG_TERM); } 345 } 346 347 <mem>{ 348 {modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); } 349 /* 350 * The colon before memory access modifiers can get mixed up with the 351 * colon before event modifiers. Fortunately none of the option letters 352 * are the same, so trailing context can be used disambiguate the two 353 * cases. 354 */ 355 ":"/{modifier_bp} { return PE_BP_COLON; } 356 /* 357 * The slash before memory length can get mixed up with the slash before 358 * config terms. Fortunately config terms do not start with a numeric 359 * digit, so trailing context can be used disambiguate the two cases. 360 */ 361 "/"/{digit} { return PE_BP_SLASH; } 362 "/"/{non_digit} { BEGIN(config); return '/'; } 363 {num_dec} { return value(_parse_state, yyscanner, 10); } 364 {num_hex} { return value(_parse_state, yyscanner, 16); } 365 /* 366 * We need to separate 'mem:' scanner part, in order to get specific 367 * modifier bits parsed out. Otherwise we would need to handle PE_NAME 368 * and we'd need to parse it manually. During the escape from <mem> 369 * state we need to put the escaping char back, so we dont miss it. 370 */ 371 . { unput(*yytext); BEGIN(INITIAL); } 372 /* 373 * We destroy the scanner after reaching EOF, 374 * but anyway just to be sure get back to INIT state. 375 */ 376 <<EOF>> { BEGIN(INITIAL); } 377 } 378 379 cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 380 stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 381 stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 382 instructions { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); } 383 cache-references { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); } 384 cache-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); } 385 branch-instructions|branches { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); } 386 branch-misses { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); } 387 bus-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); } 388 ref-cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); } 389 cpu-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); } 390 task-clock { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); } 391 page-faults|faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); } 392 minor-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); } 393 major-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); } 394 context-switches|cs { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); } 395 cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); } 396 alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } 397 emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 398 dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } 399 bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); } 400 cgroup-switches { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); } 401 402 {lc_type} { return str(yyscanner, PE_LEGACY_CACHE); } 403 {lc_type}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); } 404 {lc_type}-{lc_op_result}-{lc_op_result} { return str(yyscanner, PE_LEGACY_CACHE); } 405 mem: { BEGIN(mem); return PE_PREFIX_MEM; } 406 r{num_raw_hex} { return str(yyscanner, PE_RAW); } 407 {num_dec} { return value(_parse_state, yyscanner, 10); } 408 {num_hex} { return value(_parse_state, yyscanner, 16); } 409 410 {modifier_event} { return modifiers(_parse_state, yyscanner); } 411 {name} { return str(yyscanner, PE_NAME); } 412 {name_tag} { return str(yyscanner, PE_NAME); } 413 "/" { BEGIN(config); return '/'; } 414 , { BEGIN(event); return ','; } 415 : { return ':'; } 416 "{" { BEGIN(event); return '{'; } 417 "}" { return '}'; } 418 = { return '='; } 419 \n { } 420 . { } 421 422 %% 423 424 int parse_events_wrap(void *scanner __maybe_unused) 425 { 426 return 1; 427 } 428