pmu.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. #include <linux/list.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. #include <stdio.h>
  5. #include <stdbool.h>
  6. #include <stdarg.h>
  7. #include <dirent.h>
  8. #include <api/fs/fs.h>
  9. #include <locale.h>
  10. #include "util.h"
  11. #include "pmu.h"
  12. #include "parse-events.h"
  13. #include "cpumap.h"
  14. struct perf_pmu_format {
  15. char *name;
  16. int value;
  17. DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
  18. struct list_head list;
  19. };
  20. #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
  21. int perf_pmu_parse(struct list_head *list, char *name);
  22. extern FILE *perf_pmu_in;
  23. static LIST_HEAD(pmus);
  24. /*
  25. * Parse & process all the sysfs attributes located under
  26. * the directory specified in 'dir' parameter.
  27. */
  28. int perf_pmu__format_parse(char *dir, struct list_head *head)
  29. {
  30. struct dirent *evt_ent;
  31. DIR *format_dir;
  32. int ret = 0;
  33. format_dir = opendir(dir);
  34. if (!format_dir)
  35. return -EINVAL;
  36. while (!ret && (evt_ent = readdir(format_dir))) {
  37. char path[PATH_MAX];
  38. char *name = evt_ent->d_name;
  39. FILE *file;
  40. if (!strcmp(name, ".") || !strcmp(name, ".."))
  41. continue;
  42. snprintf(path, PATH_MAX, "%s/%s", dir, name);
  43. ret = -EINVAL;
  44. file = fopen(path, "r");
  45. if (!file)
  46. break;
  47. perf_pmu_in = file;
  48. ret = perf_pmu_parse(head, name);
  49. fclose(file);
  50. }
  51. closedir(format_dir);
  52. return ret;
  53. }
  54. /*
  55. * Reading/parsing the default pmu format definition, which should be
  56. * located at:
  57. * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
  58. */
  59. static int pmu_format(const char *name, struct list_head *format)
  60. {
  61. struct stat st;
  62. char path[PATH_MAX];
  63. const char *sysfs = sysfs__mountpoint();
  64. if (!sysfs)
  65. return -1;
  66. snprintf(path, PATH_MAX,
  67. "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
  68. if (stat(path, &st) < 0)
  69. return 0; /* no error if format does not exist */
  70. if (perf_pmu__format_parse(path, format))
  71. return -1;
  72. return 0;
  73. }
  74. static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
  75. {
  76. struct stat st;
  77. ssize_t sret;
  78. char scale[128];
  79. int fd, ret = -1;
  80. char path[PATH_MAX];
  81. const char *lc;
  82. snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
  83. fd = open(path, O_RDONLY);
  84. if (fd == -1)
  85. return -1;
  86. if (fstat(fd, &st) < 0)
  87. goto error;
  88. sret = read(fd, scale, sizeof(scale)-1);
  89. if (sret < 0)
  90. goto error;
  91. scale[sret] = '\0';
  92. /*
  93. * save current locale
  94. */
  95. lc = setlocale(LC_NUMERIC, NULL);
  96. /*
  97. * force to C locale to ensure kernel
  98. * scale string is converted correctly.
  99. * kernel uses default C locale.
  100. */
  101. setlocale(LC_NUMERIC, "C");
  102. alias->scale = strtod(scale, NULL);
  103. /* restore locale */
  104. setlocale(LC_NUMERIC, lc);
  105. ret = 0;
  106. error:
  107. close(fd);
  108. return ret;
  109. }
  110. static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
  111. {
  112. char path[PATH_MAX];
  113. ssize_t sret;
  114. int fd;
  115. snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
  116. fd = open(path, O_RDONLY);
  117. if (fd == -1)
  118. return -1;
  119. sret = read(fd, alias->unit, UNIT_MAX_LEN);
  120. if (sret < 0)
  121. goto error;
  122. close(fd);
  123. alias->unit[sret] = '\0';
  124. return 0;
  125. error:
  126. close(fd);
  127. alias->unit[0] = '\0';
  128. return -1;
  129. }
  130. static int
  131. perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
  132. {
  133. char path[PATH_MAX];
  134. int fd;
  135. snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
  136. fd = open(path, O_RDONLY);
  137. if (fd == -1)
  138. return -1;
  139. close(fd);
  140. alias->per_pkg = true;
  141. return 0;
  142. }
  143. static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
  144. char *dir, char *name)
  145. {
  146. char path[PATH_MAX];
  147. int fd;
  148. snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
  149. fd = open(path, O_RDONLY);
  150. if (fd == -1)
  151. return -1;
  152. alias->snapshot = true;
  153. close(fd);
  154. return 0;
  155. }
  156. static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
  157. {
  158. struct perf_pmu_alias *alias;
  159. char buf[256];
  160. int ret;
  161. ret = fread(buf, 1, sizeof(buf), file);
  162. if (ret == 0)
  163. return -EINVAL;
  164. buf[ret] = 0;
  165. alias = malloc(sizeof(*alias));
  166. if (!alias)
  167. return -ENOMEM;
  168. INIT_LIST_HEAD(&alias->terms);
  169. alias->scale = 1.0;
  170. alias->unit[0] = '\0';
  171. alias->per_pkg = false;
  172. ret = parse_events_terms(&alias->terms, buf);
  173. if (ret) {
  174. free(alias);
  175. return ret;
  176. }
  177. alias->name = strdup(name);
  178. /*
  179. * load unit name and scale if available
  180. */
  181. perf_pmu__parse_unit(alias, dir, name);
  182. perf_pmu__parse_scale(alias, dir, name);
  183. perf_pmu__parse_per_pkg(alias, dir, name);
  184. perf_pmu__parse_snapshot(alias, dir, name);
  185. list_add_tail(&alias->list, list);
  186. return 0;
  187. }
  188. static inline bool pmu_alias_info_file(char *name)
  189. {
  190. size_t len;
  191. len = strlen(name);
  192. if (len > 5 && !strcmp(name + len - 5, ".unit"))
  193. return true;
  194. if (len > 6 && !strcmp(name + len - 6, ".scale"))
  195. return true;
  196. if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
  197. return true;
  198. if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
  199. return true;
  200. return false;
  201. }
  202. /*
  203. * Process all the sysfs attributes located under the directory
  204. * specified in 'dir' parameter.
  205. */
  206. static int pmu_aliases_parse(char *dir, struct list_head *head)
  207. {
  208. struct dirent *evt_ent;
  209. DIR *event_dir;
  210. int ret = 0;
  211. event_dir = opendir(dir);
  212. if (!event_dir)
  213. return -EINVAL;
  214. while (!ret && (evt_ent = readdir(event_dir))) {
  215. char path[PATH_MAX];
  216. char *name = evt_ent->d_name;
  217. FILE *file;
  218. if (!strcmp(name, ".") || !strcmp(name, ".."))
  219. continue;
  220. /*
  221. * skip info files parsed in perf_pmu__new_alias()
  222. */
  223. if (pmu_alias_info_file(name))
  224. continue;
  225. snprintf(path, PATH_MAX, "%s/%s", dir, name);
  226. ret = -EINVAL;
  227. file = fopen(path, "r");
  228. if (!file)
  229. break;
  230. ret = perf_pmu__new_alias(head, dir, name, file);
  231. fclose(file);
  232. }
  233. closedir(event_dir);
  234. return ret;
  235. }
  236. /*
  237. * Reading the pmu event aliases definition, which should be located at:
  238. * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
  239. */
  240. static int pmu_aliases(const char *name, struct list_head *head)
  241. {
  242. struct stat st;
  243. char path[PATH_MAX];
  244. const char *sysfs = sysfs__mountpoint();
  245. if (!sysfs)
  246. return -1;
  247. snprintf(path, PATH_MAX,
  248. "%s/bus/event_source/devices/%s/events", sysfs, name);
  249. if (stat(path, &st) < 0)
  250. return 0; /* no error if 'events' does not exist */
  251. if (pmu_aliases_parse(path, head))
  252. return -1;
  253. return 0;
  254. }
  255. static int pmu_alias_terms(struct perf_pmu_alias *alias,
  256. struct list_head *terms)
  257. {
  258. struct parse_events_term *term, *cloned;
  259. LIST_HEAD(list);
  260. int ret;
  261. list_for_each_entry(term, &alias->terms, list) {
  262. ret = parse_events_term__clone(&cloned, term);
  263. if (ret) {
  264. parse_events__free_terms(&list);
  265. return ret;
  266. }
  267. list_add_tail(&cloned->list, &list);
  268. }
  269. list_splice(&list, terms);
  270. return 0;
  271. }
  272. /*
  273. * Reading/parsing the default pmu type value, which should be
  274. * located at:
  275. * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
  276. */
  277. static int pmu_type(const char *name, __u32 *type)
  278. {
  279. struct stat st;
  280. char path[PATH_MAX];
  281. FILE *file;
  282. int ret = 0;
  283. const char *sysfs = sysfs__mountpoint();
  284. if (!sysfs)
  285. return -1;
  286. snprintf(path, PATH_MAX,
  287. "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
  288. if (stat(path, &st) < 0)
  289. return -1;
  290. file = fopen(path, "r");
  291. if (!file)
  292. return -EINVAL;
  293. if (1 != fscanf(file, "%u", type))
  294. ret = -1;
  295. fclose(file);
  296. return ret;
  297. }
  298. /* Add all pmus in sysfs to pmu list: */
  299. static void pmu_read_sysfs(void)
  300. {
  301. char path[PATH_MAX];
  302. DIR *dir;
  303. struct dirent *dent;
  304. const char *sysfs = sysfs__mountpoint();
  305. if (!sysfs)
  306. return;
  307. snprintf(path, PATH_MAX,
  308. "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
  309. dir = opendir(path);
  310. if (!dir)
  311. return;
  312. while ((dent = readdir(dir))) {
  313. if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
  314. continue;
  315. /* add to static LIST_HEAD(pmus): */
  316. perf_pmu__find(dent->d_name);
  317. }
  318. closedir(dir);
  319. }
  320. static struct cpu_map *pmu_cpumask(const char *name)
  321. {
  322. struct stat st;
  323. char path[PATH_MAX];
  324. FILE *file;
  325. struct cpu_map *cpus;
  326. const char *sysfs = sysfs__mountpoint();
  327. if (!sysfs)
  328. return NULL;
  329. snprintf(path, PATH_MAX,
  330. "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
  331. if (stat(path, &st) < 0)
  332. return NULL;
  333. file = fopen(path, "r");
  334. if (!file)
  335. return NULL;
  336. cpus = cpu_map__read(file);
  337. fclose(file);
  338. return cpus;
  339. }
  340. struct perf_event_attr *__attribute__((weak))
  341. perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
  342. {
  343. return NULL;
  344. }
  345. static struct perf_pmu *pmu_lookup(const char *name)
  346. {
  347. struct perf_pmu *pmu;
  348. LIST_HEAD(format);
  349. LIST_HEAD(aliases);
  350. __u32 type;
  351. /*
  352. * The pmu data we store & need consists of the pmu
  353. * type value and format definitions. Load both right
  354. * now.
  355. */
  356. if (pmu_format(name, &format))
  357. return NULL;
  358. if (pmu_aliases(name, &aliases))
  359. return NULL;
  360. if (pmu_type(name, &type))
  361. return NULL;
  362. pmu = zalloc(sizeof(*pmu));
  363. if (!pmu)
  364. return NULL;
  365. pmu->cpus = pmu_cpumask(name);
  366. INIT_LIST_HEAD(&pmu->format);
  367. INIT_LIST_HEAD(&pmu->aliases);
  368. list_splice(&format, &pmu->format);
  369. list_splice(&aliases, &pmu->aliases);
  370. pmu->name = strdup(name);
  371. pmu->type = type;
  372. list_add_tail(&pmu->list, &pmus);
  373. pmu->default_config = perf_pmu__get_default_config(pmu);
  374. return pmu;
  375. }
  376. static struct perf_pmu *pmu_find(const char *name)
  377. {
  378. struct perf_pmu *pmu;
  379. list_for_each_entry(pmu, &pmus, list)
  380. if (!strcmp(pmu->name, name))
  381. return pmu;
  382. return NULL;
  383. }
  384. struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
  385. {
  386. /*
  387. * pmu iterator: If pmu is NULL, we start at the begin,
  388. * otherwise return the next pmu. Returns NULL on end.
  389. */
  390. if (!pmu) {
  391. pmu_read_sysfs();
  392. pmu = list_prepare_entry(pmu, &pmus, list);
  393. }
  394. list_for_each_entry_continue(pmu, &pmus, list)
  395. return pmu;
  396. return NULL;
  397. }
  398. struct perf_pmu *perf_pmu__find(const char *name)
  399. {
  400. struct perf_pmu *pmu;
  401. /*
  402. * Once PMU is loaded it stays in the list,
  403. * so we keep us from multiple reading/parsing
  404. * the pmu format definitions.
  405. */
  406. pmu = pmu_find(name);
  407. if (pmu)
  408. return pmu;
  409. return pmu_lookup(name);
  410. }
  411. static struct perf_pmu_format *
  412. pmu_find_format(struct list_head *formats, char *name)
  413. {
  414. struct perf_pmu_format *format;
  415. list_for_each_entry(format, formats, list)
  416. if (!strcmp(format->name, name))
  417. return format;
  418. return NULL;
  419. }
  420. /*
  421. * Sets value based on the format definition (format parameter)
  422. * and unformated value (value parameter).
  423. */
  424. static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
  425. bool zero)
  426. {
  427. unsigned long fbit, vbit;
  428. for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
  429. if (!test_bit(fbit, format))
  430. continue;
  431. if (value & (1llu << vbit++))
  432. *v |= (1llu << fbit);
  433. else if (zero)
  434. *v &= ~(1llu << fbit);
  435. }
  436. }
  437. /*
  438. * Term is a string term, and might be a param-term. Try to look up it's value
  439. * in the remaining terms.
  440. * - We have a term like "base-or-format-term=param-term",
  441. * - We need to find the value supplied for "param-term" (with param-term named
  442. * in a config string) later on in the term list.
  443. */
  444. static int pmu_resolve_param_term(struct parse_events_term *term,
  445. struct list_head *head_terms,
  446. __u64 *value)
  447. {
  448. struct parse_events_term *t;
  449. list_for_each_entry(t, head_terms, list) {
  450. if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
  451. if (!strcmp(t->config, term->config)) {
  452. t->used = true;
  453. *value = t->val.num;
  454. return 0;
  455. }
  456. }
  457. }
  458. if (verbose)
  459. printf("Required parameter '%s' not specified\n", term->config);
  460. return -1;
  461. }
  462. /*
  463. * Setup one of config[12] attr members based on the
  464. * user input data - term parameter.
  465. */
  466. static int pmu_config_term(struct list_head *formats,
  467. struct perf_event_attr *attr,
  468. struct parse_events_term *term,
  469. struct list_head *head_terms,
  470. bool zero)
  471. {
  472. struct perf_pmu_format *format;
  473. __u64 *vp;
  474. __u64 val;
  475. /*
  476. * If this is a parameter we've already used for parameterized-eval,
  477. * skip it in normal eval.
  478. */
  479. if (term->used)
  480. return 0;
  481. /*
  482. * Hardcoded terms should be already in, so nothing
  483. * to be done for them.
  484. */
  485. if (parse_events__is_hardcoded_term(term))
  486. return 0;
  487. format = pmu_find_format(formats, term->config);
  488. if (!format) {
  489. if (verbose)
  490. printf("Invalid event/parameter '%s'\n", term->config);
  491. return -EINVAL;
  492. }
  493. switch (format->value) {
  494. case PERF_PMU_FORMAT_VALUE_CONFIG:
  495. vp = &attr->config;
  496. break;
  497. case PERF_PMU_FORMAT_VALUE_CONFIG1:
  498. vp = &attr->config1;
  499. break;
  500. case PERF_PMU_FORMAT_VALUE_CONFIG2:
  501. vp = &attr->config2;
  502. break;
  503. default:
  504. return -EINVAL;
  505. }
  506. /*
  507. * Either directly use a numeric term, or try to translate string terms
  508. * using event parameters.
  509. */
  510. if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
  511. val = term->val.num;
  512. else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
  513. if (strcmp(term->val.str, "?")) {
  514. if (verbose)
  515. pr_info("Invalid sysfs entry %s=%s\n",
  516. term->config, term->val.str);
  517. return -EINVAL;
  518. }
  519. if (pmu_resolve_param_term(term, head_terms, &val))
  520. return -EINVAL;
  521. } else
  522. return -EINVAL;
  523. pmu_format_value(format->bits, val, vp, zero);
  524. return 0;
  525. }
  526. int perf_pmu__config_terms(struct list_head *formats,
  527. struct perf_event_attr *attr,
  528. struct list_head *head_terms,
  529. bool zero)
  530. {
  531. struct parse_events_term *term;
  532. list_for_each_entry(term, head_terms, list) {
  533. if (pmu_config_term(formats, attr, term, head_terms, zero))
  534. return -EINVAL;
  535. }
  536. return 0;
  537. }
  538. /*
  539. * Configures event's 'attr' parameter based on the:
  540. * 1) users input - specified in terms parameter
  541. * 2) pmu format definitions - specified by pmu parameter
  542. */
  543. int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
  544. struct list_head *head_terms)
  545. {
  546. bool zero = !!pmu->default_config;
  547. attr->type = pmu->type;
  548. return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
  549. }
  550. static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
  551. struct parse_events_term *term)
  552. {
  553. struct perf_pmu_alias *alias;
  554. char *name;
  555. if (parse_events__is_hardcoded_term(term))
  556. return NULL;
  557. if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
  558. if (term->val.num != 1)
  559. return NULL;
  560. if (pmu_find_format(&pmu->format, term->config))
  561. return NULL;
  562. name = term->config;
  563. } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
  564. if (strcasecmp(term->config, "event"))
  565. return NULL;
  566. name = term->val.str;
  567. } else {
  568. return NULL;
  569. }
  570. list_for_each_entry(alias, &pmu->aliases, list) {
  571. if (!strcasecmp(alias->name, name))
  572. return alias;
  573. }
  574. return NULL;
  575. }
  576. static int check_info_data(struct perf_pmu_alias *alias,
  577. struct perf_pmu_info *info)
  578. {
  579. /*
  580. * Only one term in event definition can
  581. * define unit, scale and snapshot, fail
  582. * if there's more than one.
  583. */
  584. if ((info->unit && alias->unit) ||
  585. (info->scale && alias->scale) ||
  586. (info->snapshot && alias->snapshot))
  587. return -EINVAL;
  588. if (alias->unit)
  589. info->unit = alias->unit;
  590. if (alias->scale)
  591. info->scale = alias->scale;
  592. if (alias->snapshot)
  593. info->snapshot = alias->snapshot;
  594. return 0;
  595. }
  596. /*
  597. * Find alias in the terms list and replace it with the terms
  598. * defined for the alias
  599. */
  600. int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
  601. struct perf_pmu_info *info)
  602. {
  603. struct parse_events_term *term, *h;
  604. struct perf_pmu_alias *alias;
  605. int ret;
  606. info->per_pkg = false;
  607. /*
  608. * Mark unit and scale as not set
  609. * (different from default values, see below)
  610. */
  611. info->unit = NULL;
  612. info->scale = 0.0;
  613. info->snapshot = false;
  614. list_for_each_entry_safe(term, h, head_terms, list) {
  615. alias = pmu_find_alias(pmu, term);
  616. if (!alias)
  617. continue;
  618. ret = pmu_alias_terms(alias, &term->list);
  619. if (ret)
  620. return ret;
  621. ret = check_info_data(alias, info);
  622. if (ret)
  623. return ret;
  624. if (alias->per_pkg)
  625. info->per_pkg = true;
  626. list_del(&term->list);
  627. free(term);
  628. }
  629. /*
  630. * if no unit or scale foundin aliases, then
  631. * set defaults as for evsel
  632. * unit cannot left to NULL
  633. */
  634. if (info->unit == NULL)
  635. info->unit = "";
  636. if (info->scale == 0.0)
  637. info->scale = 1.0;
  638. return 0;
  639. }
  640. int perf_pmu__new_format(struct list_head *list, char *name,
  641. int config, unsigned long *bits)
  642. {
  643. struct perf_pmu_format *format;
  644. format = zalloc(sizeof(*format));
  645. if (!format)
  646. return -ENOMEM;
  647. format->name = strdup(name);
  648. format->value = config;
  649. memcpy(format->bits, bits, sizeof(format->bits));
  650. list_add_tail(&format->list, list);
  651. return 0;
  652. }
  653. void perf_pmu__set_format(unsigned long *bits, long from, long to)
  654. {
  655. long b;
  656. if (!to)
  657. to = from;
  658. memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
  659. for (b = from; b <= to; b++)
  660. set_bit(b, bits);
  661. }
  662. static int sub_non_neg(int a, int b)
  663. {
  664. if (b > a)
  665. return 0;
  666. return a - b;
  667. }
  668. static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
  669. struct perf_pmu_alias *alias)
  670. {
  671. struct parse_events_term *term;
  672. int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
  673. list_for_each_entry(term, &alias->terms, list) {
  674. if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
  675. used += snprintf(buf + used, sub_non_neg(len, used),
  676. ",%s=%s", term->config,
  677. term->val.str);
  678. }
  679. if (sub_non_neg(len, used) > 0) {
  680. buf[used] = '/';
  681. used++;
  682. }
  683. if (sub_non_neg(len, used) > 0) {
  684. buf[used] = '\0';
  685. used++;
  686. } else
  687. buf[len - 1] = '\0';
  688. return buf;
  689. }
  690. static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
  691. struct perf_pmu_alias *alias)
  692. {
  693. snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
  694. return buf;
  695. }
  696. static int cmp_string(const void *a, const void *b)
  697. {
  698. const char * const *as = a;
  699. const char * const *bs = b;
  700. return strcmp(*as, *bs);
  701. }
  702. void print_pmu_events(const char *event_glob, bool name_only)
  703. {
  704. struct perf_pmu *pmu;
  705. struct perf_pmu_alias *alias;
  706. char buf[1024];
  707. int printed = 0;
  708. int len, j;
  709. char **aliases;
  710. pmu = NULL;
  711. len = 0;
  712. while ((pmu = perf_pmu__scan(pmu)) != NULL) {
  713. list_for_each_entry(alias, &pmu->aliases, list)
  714. len++;
  715. if (pmu->selectable)
  716. len++;
  717. }
  718. aliases = zalloc(sizeof(char *) * len);
  719. if (!aliases)
  720. goto out_enomem;
  721. pmu = NULL;
  722. j = 0;
  723. while ((pmu = perf_pmu__scan(pmu)) != NULL) {
  724. list_for_each_entry(alias, &pmu->aliases, list) {
  725. char *name = format_alias(buf, sizeof(buf), pmu, alias);
  726. bool is_cpu = !strcmp(pmu->name, "cpu");
  727. if (event_glob != NULL &&
  728. !(strglobmatch(name, event_glob) ||
  729. (!is_cpu && strglobmatch(alias->name,
  730. event_glob))))
  731. continue;
  732. if (is_cpu && !name_only)
  733. name = format_alias_or(buf, sizeof(buf), pmu, alias);
  734. aliases[j] = strdup(name);
  735. if (aliases[j] == NULL)
  736. goto out_enomem;
  737. j++;
  738. }
  739. if (pmu->selectable) {
  740. char *s;
  741. if (asprintf(&s, "%s//", pmu->name) < 0)
  742. goto out_enomem;
  743. aliases[j] = s;
  744. j++;
  745. }
  746. }
  747. len = j;
  748. qsort(aliases, len, sizeof(char *), cmp_string);
  749. for (j = 0; j < len; j++) {
  750. if (name_only) {
  751. printf("%s ", aliases[j]);
  752. continue;
  753. }
  754. printf(" %-50s [Kernel PMU event]\n", aliases[j]);
  755. printed++;
  756. }
  757. if (printed)
  758. printf("\n");
  759. out_free:
  760. for (j = 0; j < len; j++)
  761. zfree(&aliases[j]);
  762. zfree(&aliases);
  763. return;
  764. out_enomem:
  765. printf("FATAL: not enough memory to print PMU events\n");
  766. if (aliases)
  767. goto out_free;
  768. }
  769. bool pmu_have_event(const char *pname, const char *name)
  770. {
  771. struct perf_pmu *pmu;
  772. struct perf_pmu_alias *alias;
  773. pmu = NULL;
  774. while ((pmu = perf_pmu__scan(pmu)) != NULL) {
  775. if (strcmp(pname, pmu->name))
  776. continue;
  777. list_for_each_entry(alias, &pmu->aliases, list)
  778. if (!strcmp(alias->name, name))
  779. return true;
  780. }
  781. return false;
  782. }
  783. static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
  784. {
  785. struct stat st;
  786. char path[PATH_MAX];
  787. const char *sysfs;
  788. sysfs = sysfs__mountpoint();
  789. if (!sysfs)
  790. return NULL;
  791. snprintf(path, PATH_MAX,
  792. "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
  793. if (stat(path, &st) < 0)
  794. return NULL;
  795. return fopen(path, "r");
  796. }
  797. int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
  798. ...)
  799. {
  800. va_list args;
  801. FILE *file;
  802. int ret = EOF;
  803. va_start(args, fmt);
  804. file = perf_pmu__open_file(pmu, name);
  805. if (file) {
  806. ret = vfscanf(file, fmt, args);
  807. fclose(file);
  808. }
  809. va_end(args);
  810. return ret;
  811. }