1 #include <linux/list.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <unistd.h> 5 #include <stdio.h> 6 #include <dirent.h> 7 #include "fs.h" 8 #include "util.h" 9 #include "pmu.h" 10 #include "parse-events.h" 11 #include "cpumap.h" 12 13 struct perf_pmu_alias { 14 char *name; 15 struct list_head terms; 16 struct list_head list; 17 }; 18 19 struct perf_pmu_format { 20 char *name; 21 int value; 22 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 23 struct list_head list; 24 }; 25 26 #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" 27 28 int perf_pmu_parse(struct list_head *list, char *name); 29 extern FILE *perf_pmu_in; 30 31 static LIST_HEAD(pmus); 32 33 /* 34 * Parse & process all the sysfs attributes located under 35 * the directory specified in 'dir' parameter. 36 */ 37 int perf_pmu__format_parse(char *dir, struct list_head *head) 38 { 39 struct dirent *evt_ent; 40 DIR *format_dir; 41 int ret = 0; 42 43 format_dir = opendir(dir); 44 if (!format_dir) 45 return -EINVAL; 46 47 while (!ret && (evt_ent = readdir(format_dir))) { 48 char path[PATH_MAX]; 49 char *name = evt_ent->d_name; 50 FILE *file; 51 52 if (!strcmp(name, ".") || !strcmp(name, "..")) 53 continue; 54 55 snprintf(path, PATH_MAX, "%s/%s", dir, name); 56 57 ret = -EINVAL; 58 file = fopen(path, "r"); 59 if (!file) 60 break; 61 62 perf_pmu_in = file; 63 ret = perf_pmu_parse(head, name); 64 fclose(file); 65 } 66 67 closedir(format_dir); 68 return ret; 69 } 70 71 /* 72 * Reading/parsing the default pmu format definition, which should be 73 * located at: 74 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 75 */ 76 static int pmu_format(const char *name, struct list_head *format) 77 { 78 struct stat st; 79 char path[PATH_MAX]; 80 const char *sysfs = sysfs__mountpoint(); 81 82 if (!sysfs) 83 return -1; 84 85 snprintf(path, PATH_MAX, 86 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name); 87 88 if (stat(path, &st) < 0) 89 return 0; /* no error if format does not exist */ 90 91 if (perf_pmu__format_parse(path, format)) 92 return -1; 93 94 return 0; 95 } 96 97 static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) 98 { 99 struct perf_pmu_alias *alias; 100 char buf[256]; 101 int ret; 102 103 ret = fread(buf, 1, sizeof(buf), file); 104 if (ret == 0) 105 return -EINVAL; 106 buf[ret] = 0; 107 108 alias = malloc(sizeof(*alias)); 109 if (!alias) 110 return -ENOMEM; 111 112 INIT_LIST_HEAD(&alias->terms); 113 ret = parse_events_terms(&alias->terms, buf); 114 if (ret) { 115 free(alias); 116 return ret; 117 } 118 119 alias->name = strdup(name); 120 list_add_tail(&alias->list, list); 121 return 0; 122 } 123 124 /* 125 * Process all the sysfs attributes located under the directory 126 * specified in 'dir' parameter. 127 */ 128 static int pmu_aliases_parse(char *dir, struct list_head *head) 129 { 130 struct dirent *evt_ent; 131 DIR *event_dir; 132 int ret = 0; 133 134 event_dir = opendir(dir); 135 if (!event_dir) 136 return -EINVAL; 137 138 while (!ret && (evt_ent = readdir(event_dir))) { 139 char path[PATH_MAX]; 140 char *name = evt_ent->d_name; 141 FILE *file; 142 143 if (!strcmp(name, ".") || !strcmp(name, "..")) 144 continue; 145 146 snprintf(path, PATH_MAX, "%s/%s", dir, name); 147 148 ret = -EINVAL; 149 file = fopen(path, "r"); 150 if (!file) 151 break; 152 ret = perf_pmu__new_alias(head, name, file); 153 fclose(file); 154 } 155 156 closedir(event_dir); 157 return ret; 158 } 159 160 /* 161 * Reading the pmu event aliases definition, which should be located at: 162 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 163 */ 164 static int pmu_aliases(const char *name, struct list_head *head) 165 { 166 struct stat st; 167 char path[PATH_MAX]; 168 const char *sysfs = sysfs__mountpoint(); 169 170 if (!sysfs) 171 return -1; 172 173 snprintf(path, PATH_MAX, 174 "%s/bus/event_source/devices/%s/events", sysfs, name); 175 176 if (stat(path, &st) < 0) 177 return 0; /* no error if 'events' does not exist */ 178 179 if (pmu_aliases_parse(path, head)) 180 return -1; 181 182 return 0; 183 } 184 185 static int pmu_alias_terms(struct perf_pmu_alias *alias, 186 struct list_head *terms) 187 { 188 struct parse_events_term *term, *clone; 189 LIST_HEAD(list); 190 int ret; 191 192 list_for_each_entry(term, &alias->terms, list) { 193 ret = parse_events_term__clone(&clone, term); 194 if (ret) { 195 parse_events__free_terms(&list); 196 return ret; 197 } 198 list_add_tail(&clone->list, &list); 199 } 200 list_splice(&list, terms); 201 return 0; 202 } 203 204 /* 205 * Reading/parsing the default pmu type value, which should be 206 * located at: 207 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute. 208 */ 209 static int pmu_type(const char *name, __u32 *type) 210 { 211 struct stat st; 212 char path[PATH_MAX]; 213 FILE *file; 214 int ret = 0; 215 const char *sysfs = sysfs__mountpoint(); 216 217 if (!sysfs) 218 return -1; 219 220 snprintf(path, PATH_MAX, 221 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name); 222 223 if (stat(path, &st) < 0) 224 return -1; 225 226 file = fopen(path, "r"); 227 if (!file) 228 return -EINVAL; 229 230 if (1 != fscanf(file, "%u", type)) 231 ret = -1; 232 233 fclose(file); 234 return ret; 235 } 236 237 /* Add all pmus in sysfs to pmu list: */ 238 static void pmu_read_sysfs(void) 239 { 240 char path[PATH_MAX]; 241 DIR *dir; 242 struct dirent *dent; 243 const char *sysfs = sysfs__mountpoint(); 244 245 if (!sysfs) 246 return; 247 248 snprintf(path, PATH_MAX, 249 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs); 250 251 dir = opendir(path); 252 if (!dir) 253 return; 254 255 while ((dent = readdir(dir))) { 256 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) 257 continue; 258 /* add to static LIST_HEAD(pmus): */ 259 perf_pmu__find(dent->d_name); 260 } 261 262 closedir(dir); 263 } 264 265 static struct cpu_map *pmu_cpumask(const char *name) 266 { 267 struct stat st; 268 char path[PATH_MAX]; 269 FILE *file; 270 struct cpu_map *cpus; 271 const char *sysfs = sysfs__mountpoint(); 272 273 if (!sysfs) 274 return NULL; 275 276 snprintf(path, PATH_MAX, 277 "%s/bus/event_source/devices/%s/cpumask", sysfs, name); 278 279 if (stat(path, &st) < 0) 280 return NULL; 281 282 file = fopen(path, "r"); 283 if (!file) 284 return NULL; 285 286 cpus = cpu_map__read(file); 287 fclose(file); 288 return cpus; 289 } 290 291 static struct perf_pmu *pmu_lookup(const char *name) 292 { 293 struct perf_pmu *pmu; 294 LIST_HEAD(format); 295 LIST_HEAD(aliases); 296 __u32 type; 297 298 /* 299 * The pmu data we store & need consists of the pmu 300 * type value and format definitions. Load both right 301 * now. 302 */ 303 if (pmu_format(name, &format)) 304 return NULL; 305 306 if (pmu_aliases(name, &aliases)) 307 return NULL; 308 309 if (pmu_type(name, &type)) 310 return NULL; 311 312 pmu = zalloc(sizeof(*pmu)); 313 if (!pmu) 314 return NULL; 315 316 pmu->cpus = pmu_cpumask(name); 317 318 INIT_LIST_HEAD(&pmu->format); 319 INIT_LIST_HEAD(&pmu->aliases); 320 list_splice(&format, &pmu->format); 321 list_splice(&aliases, &pmu->aliases); 322 pmu->name = strdup(name); 323 pmu->type = type; 324 list_add_tail(&pmu->list, &pmus); 325 return pmu; 326 } 327 328 static struct perf_pmu *pmu_find(const char *name) 329 { 330 struct perf_pmu *pmu; 331 332 list_for_each_entry(pmu, &pmus, list) 333 if (!strcmp(pmu->name, name)) 334 return pmu; 335 336 return NULL; 337 } 338 339 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) 340 { 341 /* 342 * pmu iterator: If pmu is NULL, we start at the begin, 343 * otherwise return the next pmu. Returns NULL on end. 344 */ 345 if (!pmu) { 346 pmu_read_sysfs(); 347 pmu = list_prepare_entry(pmu, &pmus, list); 348 } 349 list_for_each_entry_continue(pmu, &pmus, list) 350 return pmu; 351 return NULL; 352 } 353 354 struct perf_pmu *perf_pmu__find(const char *name) 355 { 356 struct perf_pmu *pmu; 357 358 /* 359 * Once PMU is loaded it stays in the list, 360 * so we keep us from multiple reading/parsing 361 * the pmu format definitions. 362 */ 363 pmu = pmu_find(name); 364 if (pmu) 365 return pmu; 366 367 return pmu_lookup(name); 368 } 369 370 static struct perf_pmu_format * 371 pmu_find_format(struct list_head *formats, char *name) 372 { 373 struct perf_pmu_format *format; 374 375 list_for_each_entry(format, formats, list) 376 if (!strcmp(format->name, name)) 377 return format; 378 379 return NULL; 380 } 381 382 /* 383 * Returns value based on the format definition (format parameter) 384 * and unformated value (value parameter). 385 * 386 * TODO maybe optimize a little ;) 387 */ 388 static __u64 pmu_format_value(unsigned long *format, __u64 value) 389 { 390 unsigned long fbit, vbit; 391 __u64 v = 0; 392 393 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 394 395 if (!test_bit(fbit, format)) 396 continue; 397 398 if (!(value & (1llu << vbit++))) 399 continue; 400 401 v |= (1llu << fbit); 402 } 403 404 return v; 405 } 406 407 /* 408 * Setup one of config[12] attr members based on the 409 * user input data - temr parameter. 410 */ 411 static int pmu_config_term(struct list_head *formats, 412 struct perf_event_attr *attr, 413 struct parse_events_term *term) 414 { 415 struct perf_pmu_format *format; 416 __u64 *vp; 417 418 /* 419 * Support only for hardcoded and numnerial terms. 420 * Hardcoded terms should be already in, so nothing 421 * to be done for them. 422 */ 423 if (parse_events__is_hardcoded_term(term)) 424 return 0; 425 426 if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) 427 return -EINVAL; 428 429 format = pmu_find_format(formats, term->config); 430 if (!format) 431 return -EINVAL; 432 433 switch (format->value) { 434 case PERF_PMU_FORMAT_VALUE_CONFIG: 435 vp = &attr->config; 436 break; 437 case PERF_PMU_FORMAT_VALUE_CONFIG1: 438 vp = &attr->config1; 439 break; 440 case PERF_PMU_FORMAT_VALUE_CONFIG2: 441 vp = &attr->config2; 442 break; 443 default: 444 return -EINVAL; 445 } 446 447 /* 448 * XXX If we ever decide to go with string values for 449 * non-hardcoded terms, here's the place to translate 450 * them into value. 451 */ 452 *vp |= pmu_format_value(format->bits, term->val.num); 453 return 0; 454 } 455 456 int perf_pmu__config_terms(struct list_head *formats, 457 struct perf_event_attr *attr, 458 struct list_head *head_terms) 459 { 460 struct parse_events_term *term; 461 462 list_for_each_entry(term, head_terms, list) 463 if (pmu_config_term(formats, attr, term)) 464 return -EINVAL; 465 466 return 0; 467 } 468 469 /* 470 * Configures event's 'attr' parameter based on the: 471 * 1) users input - specified in terms parameter 472 * 2) pmu format definitions - specified by pmu parameter 473 */ 474 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 475 struct list_head *head_terms) 476 { 477 attr->type = pmu->type; 478 return perf_pmu__config_terms(&pmu->format, attr, head_terms); 479 } 480 481 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 482 struct parse_events_term *term) 483 { 484 struct perf_pmu_alias *alias; 485 char *name; 486 487 if (parse_events__is_hardcoded_term(term)) 488 return NULL; 489 490 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 491 if (term->val.num != 1) 492 return NULL; 493 if (pmu_find_format(&pmu->format, term->config)) 494 return NULL; 495 name = term->config; 496 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 497 if (strcasecmp(term->config, "event")) 498 return NULL; 499 name = term->val.str; 500 } else { 501 return NULL; 502 } 503 504 list_for_each_entry(alias, &pmu->aliases, list) { 505 if (!strcasecmp(alias->name, name)) 506 return alias; 507 } 508 return NULL; 509 } 510 511 /* 512 * Find alias in the terms list and replace it with the terms 513 * defined for the alias 514 */ 515 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) 516 { 517 struct parse_events_term *term, *h; 518 struct perf_pmu_alias *alias; 519 int ret; 520 521 list_for_each_entry_safe(term, h, head_terms, list) { 522 alias = pmu_find_alias(pmu, term); 523 if (!alias) 524 continue; 525 ret = pmu_alias_terms(alias, &term->list); 526 if (ret) 527 return ret; 528 list_del(&term->list); 529 free(term); 530 } 531 return 0; 532 } 533 534 int perf_pmu__new_format(struct list_head *list, char *name, 535 int config, unsigned long *bits) 536 { 537 struct perf_pmu_format *format; 538 539 format = zalloc(sizeof(*format)); 540 if (!format) 541 return -ENOMEM; 542 543 format->name = strdup(name); 544 format->value = config; 545 memcpy(format->bits, bits, sizeof(format->bits)); 546 547 list_add_tail(&format->list, list); 548 return 0; 549 } 550 551 void perf_pmu__set_format(unsigned long *bits, long from, long to) 552 { 553 long b; 554 555 if (!to) 556 to = from; 557 558 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS)); 559 for (b = from; b <= to; b++) 560 set_bit(b, bits); 561 } 562 563 static char *format_alias(char *buf, int len, struct perf_pmu *pmu, 564 struct perf_pmu_alias *alias) 565 { 566 snprintf(buf, len, "%s/%s/", pmu->name, alias->name); 567 return buf; 568 } 569 570 static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu, 571 struct perf_pmu_alias *alias) 572 { 573 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name); 574 return buf; 575 } 576 577 static int cmp_string(const void *a, const void *b) 578 { 579 const char * const *as = a; 580 const char * const *bs = b; 581 return strcmp(*as, *bs); 582 } 583 584 void print_pmu_events(const char *event_glob, bool name_only) 585 { 586 struct perf_pmu *pmu; 587 struct perf_pmu_alias *alias; 588 char buf[1024]; 589 int printed = 0; 590 int len, j; 591 char **aliases; 592 593 pmu = NULL; 594 len = 0; 595 while ((pmu = perf_pmu__scan(pmu)) != NULL) 596 list_for_each_entry(alias, &pmu->aliases, list) 597 len++; 598 aliases = malloc(sizeof(char *) * len); 599 if (!aliases) 600 return; 601 pmu = NULL; 602 j = 0; 603 while ((pmu = perf_pmu__scan(pmu)) != NULL) 604 list_for_each_entry(alias, &pmu->aliases, list) { 605 char *name = format_alias(buf, sizeof(buf), pmu, alias); 606 bool is_cpu = !strcmp(pmu->name, "cpu"); 607 608 if (event_glob != NULL && 609 !(strglobmatch(name, event_glob) || 610 (!is_cpu && strglobmatch(alias->name, 611 event_glob)))) 612 continue; 613 aliases[j] = name; 614 if (is_cpu && !name_only) 615 aliases[j] = format_alias_or(buf, sizeof(buf), 616 pmu, alias); 617 aliases[j] = strdup(aliases[j]); 618 j++; 619 } 620 len = j; 621 qsort(aliases, len, sizeof(char *), cmp_string); 622 for (j = 0; j < len; j++) { 623 if (name_only) { 624 printf("%s ", aliases[j]); 625 continue; 626 } 627 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 628 free(aliases[j]); 629 printed++; 630 } 631 if (printed) 632 printf("\n"); 633 free(aliases); 634 } 635 636 bool pmu_have_event(const char *pname, const char *name) 637 { 638 struct perf_pmu *pmu; 639 struct perf_pmu_alias *alias; 640 641 pmu = NULL; 642 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 643 if (strcmp(pname, pmu->name)) 644 continue; 645 list_for_each_entry(alias, &pmu->aliases, list) 646 if (!strcmp(alias->name, name)) 647 return true; 648 } 649 return false; 650 } 651