pmu.c 11 KB

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