pmu.c 11 KB

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