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