pmu.c 13 KB

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