pmu.c 31.0 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2
#include <linux/list.h>
3
#include <linux/compiler.h>
4
#include <sys/types.h>
5
#include <errno.h>
6
#include <fcntl.h>
7
#include <sys/stat.h>
8 9
#include <unistd.h>
#include <stdio.h>
10
#include <stdbool.h>
11
#include <stdarg.h>
12
#include <dirent.h>
13
#include <api/fs/fs.h>
14
#include <locale.h>
15
#include <regex.h>
16 17 18
#include "util.h"
#include "pmu.h"
#include "parse-events.h"
Y
Yan, Zheng 已提交
19
#include "cpumap.h"
20 21
#include "header.h"
#include "pmu-events/pmu-events.h"
22
#include "cache.h"
23
#include "string2.h"
24

25 26 27 28 29 30 31
struct perf_pmu_format {
	char *name;
	int value;
	DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
	struct list_head list;
};

32 33
#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"

34 35 36 37 38 39 40 41 42
int perf_pmu_parse(struct list_head *list, char *name);
extern FILE *perf_pmu_in;

static LIST_HEAD(pmus);

/*
 * Parse & process all the sysfs attributes located under
 * the directory specified in 'dir' parameter.
 */
43
int perf_pmu__format_parse(char *dir, struct list_head *head)
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
{
	struct dirent *evt_ent;
	DIR *format_dir;
	int ret = 0;

	format_dir = opendir(dir);
	if (!format_dir)
		return -EINVAL;

	while (!ret && (evt_ent = readdir(format_dir))) {
		char path[PATH_MAX];
		char *name = evt_ent->d_name;
		FILE *file;

		if (!strcmp(name, ".") || !strcmp(name, ".."))
			continue;

		snprintf(path, PATH_MAX, "%s/%s", dir, name);

		ret = -EINVAL;
		file = fopen(path, "r");
		if (!file)
			break;

		perf_pmu_in = file;
		ret = perf_pmu_parse(head, name);
		fclose(file);
	}

	closedir(format_dir);
	return ret;
}

/*
 * Reading/parsing the default pmu format definition, which should be
 * located at:
 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
 */
82
static int pmu_format(const char *name, struct list_head *format)
83 84 85
{
	struct stat st;
	char path[PATH_MAX];
86
	const char *sysfs = sysfs__mountpoint();
87 88 89 90 91

	if (!sysfs)
		return -1;

	snprintf(path, PATH_MAX,
92
		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
93 94

	if (stat(path, &st) < 0)
95
		return 0;	/* no error if format does not exist */
96

97
	if (perf_pmu__format_parse(path, format))
98 99 100 101 102
		return -1;

	return 0;
}

103
static int convert_scale(const char *scale, char **end, double *sval)
104
{
105
	char *lc;
106
	int ret = 0;
107

108 109 110 111 112
	/*
	 * save current locale
	 */
	lc = setlocale(LC_NUMERIC, NULL);

113 114 115 116 117 118 119 120
	/*
	 * The lc string may be allocated in static storage,
	 * so get a dynamic copy to make it survive setlocale
	 * call below.
	 */
	lc = strdup(lc);
	if (!lc) {
		ret = -ENOMEM;
121
		goto out;
122 123
	}

124 125 126 127 128 129 130
	/*
	 * force to C locale to ensure kernel
	 * scale string is converted correctly.
	 * kernel uses default C locale.
	 */
	setlocale(LC_NUMERIC, "C");

131
	*sval = strtod(scale, end);
132

133
out:
134 135
	/* restore locale */
	setlocale(LC_NUMERIC, lc);
136
	free(lc);
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
	return ret;
}

static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
{
	struct stat st;
	ssize_t sret;
	char scale[128];
	int fd, ret = -1;
	char path[PATH_MAX];

	snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);

	fd = open(path, O_RDONLY);
	if (fd == -1)
		return -1;

	if (fstat(fd, &st) < 0)
		goto error;

	sret = read(fd, scale, sizeof(scale)-1);
	if (sret < 0)
		goto error;

	if (scale[sret - 1] == '\n')
		scale[sret - 1] = '\0';
	else
		scale[sret] = '\0';
165

166
	ret = convert_scale(scale, NULL, &alias->scale);
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
error:
	close(fd);
	return ret;
}

static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
{
	char path[PATH_MAX];
	ssize_t sret;
	int fd;

	snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);

	fd = open(path, O_RDONLY);
	if (fd == -1)
		return -1;

184
	sret = read(fd, alias->unit, UNIT_MAX_LEN);
185 186 187 188 189
	if (sret < 0)
		goto error;

	close(fd);

190 191 192 193
	if (alias->unit[sret - 1] == '\n')
		alias->unit[sret - 1] = '\0';
	else
		alias->unit[sret] = '\0';
194 195 196 197 198 199 200 201

	return 0;
error:
	close(fd);
	alias->unit[0] = '\0';
	return -1;
}

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
static int
perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
{
	char path[PATH_MAX];
	int fd;

	snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);

	fd = open(path, O_RDONLY);
	if (fd == -1)
		return -1;

	close(fd);

	alias->per_pkg = true;
	return 0;
}

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
				    char *dir, char *name)
{
	char path[PATH_MAX];
	int fd;

	snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);

	fd = open(path, O_RDONLY);
	if (fd == -1)
		return -1;

	alias->snapshot = true;
	close(fd);
	return 0;
}

237
static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
238 239
				 char *desc, char *val,
				 char *long_desc, char *topic,
240
				 char *unit, char *perpkg,
241 242
				 char *metric_expr,
				 char *metric_name)
243
{
244
	struct parse_events_term *term;
245
	struct perf_pmu_alias *alias;
246
	int ret;
247
	int num;
248
	char newval[256];
249 250 251 252 253 254

	alias = malloc(sizeof(*alias));
	if (!alias)
		return -ENOMEM;

	INIT_LIST_HEAD(&alias->terms);
255 256
	alias->scale = 1.0;
	alias->unit[0] = '\0';
257
	alias->per_pkg = false;
258
	alias->snapshot = false;
259

260
	ret = parse_events_terms(&alias->terms, val);
261
	if (ret) {
262
		pr_err("Cannot parse alias %s: %d\n", val, ret);
263 264 265 266
		free(alias);
		return ret;
	}

267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
	/* Scan event and remove leading zeroes, spaces, newlines, some
	 * platforms have terms specified as
	 * event=0x0091 (read from files ../<PMU>/events/<FILE>
	 * and terms specified as event=0x91 (read from JSON files).
	 *
	 * Rebuild string to make alias->str member comparable.
	 */
	memset(newval, 0, sizeof(newval));
	ret = 0;
	list_for_each_entry(term, &alias->terms, list) {
		if (ret)
			ret += scnprintf(newval + ret, sizeof(newval) - ret,
					 ",");
		if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
			ret += scnprintf(newval + ret, sizeof(newval) - ret,
					 "%s=%#x", term->config, term->val.num);
		else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
			ret += scnprintf(newval + ret, sizeof(newval) - ret,
					 "%s=%s", term->config, term->val.str);
	}

288
	alias->name = strdup(name);
289 290 291 292 293 294 295 296 297
	if (dir) {
		/*
		 * load unit name and scale if available
		 */
		perf_pmu__parse_unit(alias, dir, name);
		perf_pmu__parse_scale(alias, dir, name);
		perf_pmu__parse_per_pkg(alias, dir, name);
		perf_pmu__parse_snapshot(alias, dir, name);
	}
298

299
	alias->metric_expr = metric_expr ? strdup(metric_expr) : NULL;
300
	alias->metric_name = metric_name ? strdup(metric_name): NULL;
A
Andi Kleen 已提交
301
	alias->desc = desc ? strdup(desc) : NULL;
302 303
	alias->long_desc = long_desc ? strdup(long_desc) :
				desc ? strdup(desc) : NULL;
304
	alias->topic = topic ? strdup(topic) : NULL;
305 306 307 308 309 310
	if (unit) {
		if (convert_scale(unit, &unit, &alias->scale) < 0)
			return -1;
		snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
	}
	alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1;
311
	alias->str = strdup(newval);
312

313
	list_add_tail(&alias->list, list);
314

315 316 317
	return 0;
}

318 319 320 321 322 323 324 325 326 327 328
static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
{
	char buf[256];
	int ret;

	ret = fread(buf, 1, sizeof(buf), file);
	if (ret == 0)
		return -EINVAL;

	buf[ret] = 0;

329 330 331
	/* Remove trailing newline from sysfs file */
	rtrim(buf);

332
	return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
333
				     NULL, NULL, NULL);
334 335
}

336 337 338 339 340 341 342 343 344
static inline bool pmu_alias_info_file(char *name)
{
	size_t len;

	len = strlen(name);
	if (len > 5 && !strcmp(name + len - 5, ".unit"))
		return true;
	if (len > 6 && !strcmp(name + len - 6, ".scale"))
		return true;
345 346
	if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
		return true;
347 348
	if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
		return true;
349 350 351 352

	return false;
}

353 354 355 356 357 358 359 360 361 362 363 364 365
/*
 * Process all the sysfs attributes located under the directory
 * specified in 'dir' parameter.
 */
static int pmu_aliases_parse(char *dir, struct list_head *head)
{
	struct dirent *evt_ent;
	DIR *event_dir;

	event_dir = opendir(dir);
	if (!event_dir)
		return -EINVAL;

366
	while ((evt_ent = readdir(event_dir))) {
367 368 369 370 371 372 373
		char path[PATH_MAX];
		char *name = evt_ent->d_name;
		FILE *file;

		if (!strcmp(name, ".") || !strcmp(name, ".."))
			continue;

374
		/*
375
		 * skip info files parsed in perf_pmu__new_alias()
376
		 */
377
		if (pmu_alias_info_file(name))
378 379
			continue;

380
		scnprintf(path, PATH_MAX, "%s/%s", dir, name);
381 382

		file = fopen(path, "r");
383 384 385 386
		if (!file) {
			pr_debug("Cannot open %s\n", path);
			continue;
		}
387

388 389
		if (perf_pmu__new_alias(head, dir, name, file) < 0)
			pr_debug("Cannot set up %s\n", name);
390 391 392 393
		fclose(file);
	}

	closedir(event_dir);
394
	return 0;
395 396 397 398 399 400
}

/*
 * Reading the pmu event aliases definition, which should be located at:
 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
 */
401
static int pmu_aliases(const char *name, struct list_head *head)
402 403 404
{
	struct stat st;
	char path[PATH_MAX];
405
	const char *sysfs = sysfs__mountpoint();
406 407 408 409 410 411 412 413

	if (!sysfs)
		return -1;

	snprintf(path, PATH_MAX,
		 "%s/bus/event_source/devices/%s/events", sysfs, name);

	if (stat(path, &st) < 0)
414
		return 0;	 /* no error if 'events' does not exist */
415 416 417 418 419 420 421

	if (pmu_aliases_parse(path, head))
		return -1;

	return 0;
}

422
static int pmu_alias_terms(struct perf_pmu_alias *alias,
423 424
			   struct list_head *terms)
{
425
	struct parse_events_term *term, *cloned;
426 427 428 429
	LIST_HEAD(list);
	int ret;

	list_for_each_entry(term, &alias->terms, list) {
430
		ret = parse_events_term__clone(&cloned, term);
431
		if (ret) {
432
			parse_events_terms__purge(&list);
433 434
			return ret;
		}
435 436 437 438 439
		/*
		 * Weak terms don't override command line options,
		 * which we don't want for implicit terms in aliases.
		 */
		cloned->weak = true;
440
		list_add_tail(&cloned->list, &list);
441 442 443 444 445
	}
	list_splice(&list, terms);
	return 0;
}

446 447 448 449 450
/*
 * Reading/parsing the default pmu type value, which should be
 * located at:
 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
 */
451
static int pmu_type(const char *name, __u32 *type)
452 453 454 455 456
{
	struct stat st;
	char path[PATH_MAX];
	FILE *file;
	int ret = 0;
457
	const char *sysfs = sysfs__mountpoint();
458 459 460 461 462

	if (!sysfs)
		return -1;

	snprintf(path, PATH_MAX,
463
		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478

	if (stat(path, &st) < 0)
		return -1;

	file = fopen(path, "r");
	if (!file)
		return -EINVAL;

	if (1 != fscanf(file, "%u", type))
		ret = -1;

	fclose(file);
	return ret;
}

479 480 481 482 483 484
/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void)
{
	char path[PATH_MAX];
	DIR *dir;
	struct dirent *dent;
485
	const char *sysfs = sysfs__mountpoint();
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506

	if (!sysfs)
		return;

	snprintf(path, PATH_MAX,
		 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);

	dir = opendir(path);
	if (!dir)
		return;

	while ((dent = readdir(dir))) {
		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
			continue;
		/* add to static LIST_HEAD(pmus): */
		perf_pmu__find(dent->d_name);
	}

	closedir(dir);
}

507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
static struct cpu_map *__pmu_cpumask(const char *path)
{
	FILE *file;
	struct cpu_map *cpus;

	file = fopen(path, "r");
	if (!file)
		return NULL;

	cpus = cpu_map__read(file);
	fclose(file);
	return cpus;
}

/*
 * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64)
 * may have a "cpus" file.
 */
#define CPUS_TEMPLATE_UNCORE	"%s/bus/event_source/devices/%s/cpumask"
#define CPUS_TEMPLATE_CPU	"%s/bus/event_source/devices/%s/cpus"

528
static struct cpu_map *pmu_cpumask(const char *name)
Y
Yan, Zheng 已提交
529 530 531
{
	char path[PATH_MAX];
	struct cpu_map *cpus;
532
	const char *sysfs = sysfs__mountpoint();
533
	const char *templates[] = {
534 535 536
		CPUS_TEMPLATE_UNCORE,
		CPUS_TEMPLATE_CPU,
		NULL
537 538
	};
	const char **template;
Y
Yan, Zheng 已提交
539 540 541 542

	if (!sysfs)
		return NULL;

543 544
	for (template = templates; *template; template++) {
		snprintf(path, PATH_MAX, *template, sysfs, name);
545 546 547
		cpus = __pmu_cpumask(path);
		if (cpus)
			return cpus;
548
	}
Y
Yan, Zheng 已提交
549

550 551
	return NULL;
}
Y
Yan, Zheng 已提交
552

553 554 555 556 557
static bool pmu_is_uncore(const char *name)
{
	char path[PATH_MAX];
	struct cpu_map *cpus;
	const char *sysfs = sysfs__mountpoint();
Y
Yan, Zheng 已提交
558

559 560 561 562 563
	snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
	cpus = __pmu_cpumask(path);
	cpu_map__put(cpus);

	return !!cpus;
Y
Yan, Zheng 已提交
564 565
}

566 567
/*
 *  PMU CORE devices have different name other than cpu in sysfs on some
568 569
 *  platforms.
 *  Looking for possible sysfs files to identify the arm core device.
570
 */
571
static int is_arm_pmu_core(const char *name)
572 573 574 575 576 577 578 579 580 581 582 583 584 585
{
	struct stat st;
	char path[PATH_MAX];
	const char *sysfs = sysfs__mountpoint();

	if (!sysfs)
		return 0;

	/* Look for cpu sysfs (specific to arm) */
	scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus",
				sysfs, name);
	if (stat(path, &st) == 0)
		return 1;

586 587 588 589 590 591
	/* Look for cpu sysfs (specific to s390) */
	scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s",
		  sysfs, name);
	if (stat(path, &st) == 0 && !strncmp(name, "cpum_", 5))
		return 1;

592 593 594
	return 0;
}

595 596 597 598 599 600
/*
 * Return the CPU id as a raw string.
 *
 * Each architecture should provide a more precise id string that
 * can be use to match the architecture's "mapfile".
 */
601
char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
602 603 604 605
{
	return NULL;
}

606 607 608 609
/* Return zero when the cpuid from the mapfile.csv matches the
 * cpuid string generated on this platform.
 * Otherwise return non-zero.
 */
610
int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
{
	regex_t re;
	regmatch_t pmatch[1];
	int match;

	if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
		/* Warn unable to generate match particular string. */
		pr_info("Invalid regular expression %s\n", mapcpuid);
		return 1;
	}

	match = !regexec(&re, cpuid, 1, pmatch, 0);
	regfree(&re);
	if (match) {
		size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);

		/* Verify the entire string matched. */
		if (match_len == strlen(cpuid))
			return 0;
	}
	return 1;
}

634
static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
635 636
{
	char *cpuid;
637
	static bool printed;
638

639 640 641 642
	cpuid = getenv("PERF_CPUID");
	if (cpuid)
		cpuid = strdup(cpuid);
	if (!cpuid)
643
		cpuid = get_cpuid_str(pmu);
644
	if (!cpuid)
645
		return NULL;
646

647 648 649 650
	if (!printed) {
		pr_debug("Using CPUID %s\n", cpuid);
		printed = true;
	}
651 652 653
	return cpuid;
}

654
struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
655 656
{
	struct pmu_events_map *map;
657
	char *cpuid = perf_pmu__getcpuid(pmu);
658
	int i;
659

660 661 662 663 664 665
	/* on some platforms which uses cpus map, cpuid can be NULL for
	 * PMUs other than CORE PMUs.
	 */
	if (!cpuid)
		return NULL;

666
	i = 0;
667
	for (;;) {
668
		map = &pmu_events_map[i++];
669 670 671 672
		if (!map->table) {
			map = NULL;
			break;
		}
673

674
		if (!strcmp_cpuid_str(map->cpuid, cpuid))
675 676
			break;
	}
677 678 679 680 681 682 683 684 685
	free(cpuid);
	return map;
}

/*
 * From the pmu_events_map, find the table of PMU events that corresponds
 * to the current running CPU. Then, add all PMU events from that table
 * as aliases.
 */
686
static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
687 688 689 690
{
	int i;
	struct pmu_events_map *map;
	struct pmu_event *pe;
691
	const char *name = pmu->name;
692
	const char *pname;
693

694
	map = perf_pmu__find_map(pmu);
695 696
	if (!map)
		return;
697 698 699 700 701 702

	/*
	 * Found a matching PMU events table. Create aliases
	 */
	i = 0;
	while (1) {
703

704
		pe = &map->table[i++];
705 706 707
		if (!pe->name) {
			if (pe->metric_group || pe->metric_name)
				continue;
708
			break;
709
		}
710

711 712 713
		if (!is_arm_pmu_core(name)) {
			pname = pe->pmu ? pe->pmu : "cpu";
			if (strncmp(pname, name, strlen(pname)))
714 715
				continue;
		}
716

717 718
		/* need type casts to override 'const' */
		__perf_pmu__new_alias(head, NULL, (char *)pe->name,
719
				(char *)pe->desc, (char *)pe->event,
720
				(char *)pe->long_desc, (char *)pe->topic,
721
				(char *)pe->unit, (char *)pe->perpkg,
722 723
				(char *)pe->metric_expr,
				(char *)pe->metric_name);
724 725 726
	}
}

727
struct perf_event_attr * __weak
728 729 730 731 732
perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
{
	return NULL;
}

733
static struct perf_pmu *pmu_lookup(const char *name)
734 735 736
{
	struct perf_pmu *pmu;
	LIST_HEAD(format);
737
	LIST_HEAD(aliases);
738 739 740 741 742 743 744 745 746 747
	__u32 type;

	/*
	 * The pmu data we store & need consists of the pmu
	 * type value and format definitions. Load both right
	 * now.
	 */
	if (pmu_format(name, &format))
		return NULL;

748 749 750 751
	/*
	 * Check the type first to avoid unnecessary work.
	 */
	if (pmu_type(name, &type))
752 753
		return NULL;

754
	if (pmu_aliases(name, &aliases))
755 756 757 758 759 760
		return NULL;

	pmu = zalloc(sizeof(*pmu));
	if (!pmu)
		return NULL;

Y
Yan, Zheng 已提交
761
	pmu->cpus = pmu_cpumask(name);
762 763
	pmu->name = strdup(name);
	pmu->type = type;
764
	pmu->is_uncore = pmu_is_uncore(name);
765
	pmu_add_cpu_aliases(&aliases, pmu);
766

767
	INIT_LIST_HEAD(&pmu->format);
768
	INIT_LIST_HEAD(&pmu->aliases);
769
	list_splice(&format, &pmu->format);
770
	list_splice(&aliases, &pmu->aliases);
771
	list_add_tail(&pmu->list, &pmus);
772 773 774

	pmu->default_config = perf_pmu__get_default_config(pmu);

775 776 777
	return pmu;
}

778
static struct perf_pmu *pmu_find(const char *name)
779 780 781 782 783 784 785 786 787 788
{
	struct perf_pmu *pmu;

	list_for_each_entry(pmu, &pmus, list)
		if (!strcmp(pmu->name, name))
			return pmu;

	return NULL;
}

789 790 791 792 793 794 795 796 797 798 799 800 801 802 803
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
{
	/*
	 * pmu iterator: If pmu is NULL, we start at the begin,
	 * otherwise return the next pmu. Returns NULL on end.
	 */
	if (!pmu) {
		pmu_read_sysfs();
		pmu = list_prepare_entry(pmu, &pmus, list);
	}
	list_for_each_entry_continue(pmu, &pmus, list)
		return pmu;
	return NULL;
}

804
struct perf_pmu *perf_pmu__find(const char *name)
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
{
	struct perf_pmu *pmu;

	/*
	 * Once PMU is loaded it stays in the list,
	 * so we keep us from multiple reading/parsing
	 * the pmu format definitions.
	 */
	pmu = pmu_find(name);
	if (pmu)
		return pmu;

	return pmu_lookup(name);
}

820
static struct perf_pmu_format *
821
pmu_find_format(struct list_head *formats, const char *name)
822
{
823
	struct perf_pmu_format *format;
824 825 826 827 828 829 830 831

	list_for_each_entry(format, formats, list)
		if (!strcmp(format->name, name))
			return format;

	return NULL;
}

832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
__u64 perf_pmu__format_bits(struct list_head *formats, const char *name)
{
	struct perf_pmu_format *format = pmu_find_format(formats, name);
	__u64 bits = 0;
	int fbit;

	if (!format)
		return 0;

	for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS)
		bits |= 1ULL << fbit;

	return bits;
}

847
/*
848
 * Sets value based on the format definition (format parameter)
849 850
 * and unformated value (value parameter).
 */
851 852
static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
			     bool zero)
853 854 855 856 857 858 859 860
{
	unsigned long fbit, vbit;

	for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {

		if (!test_bit(fbit, format))
			continue;

861 862 863 864
		if (value & (1llu << vbit++))
			*v |= (1llu << fbit);
		else if (zero)
			*v &= ~(1llu << fbit);
865 866 867
	}
}

868 869
static __u64 pmu_format_max_value(const unsigned long *format)
{
870 871
	__u64 w = 0;
	int fbit;
872

873 874 875 876
	for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS)
		w |= (1ULL << fbit);

	return w;
877 878
}

879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
/*
 * Term is a string term, and might be a param-term. Try to look up it's value
 * in the remaining terms.
 * - We have a term like "base-or-format-term=param-term",
 * - We need to find the value supplied for "param-term" (with param-term named
 *   in a config string) later on in the term list.
 */
static int pmu_resolve_param_term(struct parse_events_term *term,
				  struct list_head *head_terms,
				  __u64 *value)
{
	struct parse_events_term *t;

	list_for_each_entry(t, head_terms, list) {
		if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
			if (!strcmp(t->config, term->config)) {
				t->used = true;
				*value = t->val.num;
				return 0;
			}
		}
	}

902
	if (verbose > 0)
903 904 905 906 907
		printf("Required parameter '%s' not specified\n", term->config);

	return -1;
}

908
static char *pmu_formats_string(struct list_head *formats)
909 910
{
	struct perf_pmu_format *format;
911 912
	char *str = NULL;
	struct strbuf buf = STRBUF_INIT;
913 914
	unsigned i = 0;

915
	if (!formats)
916 917 918
		return NULL;

	/* sysfs exported terms */
919
	list_for_each_entry(format, formats, list)
920 921
		if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0)
			goto error;
922

923
	str = strbuf_detach(&buf, NULL);
924
error:
925
	strbuf_release(&buf);
926 927 928 929

	return str;
}

930 931
/*
 * Setup one of config[12] attr members based on the
C
Cody P Schafer 已提交
932
 * user input data - term parameter.
933 934 935
 */
static int pmu_config_term(struct list_head *formats,
			   struct perf_event_attr *attr,
936
			   struct parse_events_term *term,
937
			   struct list_head *head_terms,
938
			   bool zero, struct parse_events_error *err)
939
{
940
	struct perf_pmu_format *format;
941
	__u64 *vp;
942
	__u64 val, max_val;
943 944 945 946 947 948 949

	/*
	 * If this is a parameter we've already used for parameterized-eval,
	 * skip it in normal eval.
	 */
	if (term->used)
		return 0;
950 951 952 953 954 955 956 957 958

	/*
	 * Hardcoded terms should be already in, so nothing
	 * to be done for them.
	 */
	if (parse_events__is_hardcoded_term(term))
		return 0;

	format = pmu_find_format(formats, term->config);
959
	if (!format) {
960
		if (verbose > 0)
961
			printf("Invalid event/parameter '%s'\n", term->config);
962
		if (err) {
963 964
			char *pmu_term = pmu_formats_string(formats);

965 966
			err->idx  = term->err_term;
			err->str  = strdup("unknown term");
967 968
			err->help = parse_events_formats_error_string(pmu_term);
			free(pmu_term);
969
		}
970
		return -EINVAL;
971
	}
972 973 974 975 976 977 978 979 980 981 982 983 984 985 986

	switch (format->value) {
	case PERF_PMU_FORMAT_VALUE_CONFIG:
		vp = &attr->config;
		break;
	case PERF_PMU_FORMAT_VALUE_CONFIG1:
		vp = &attr->config1;
		break;
	case PERF_PMU_FORMAT_VALUE_CONFIG2:
		vp = &attr->config2;
		break;
	default:
		return -EINVAL;
	}

987
	/*
988 989
	 * Either directly use a numeric term, or try to translate string terms
	 * using event parameters.
990
	 */
991 992 993 994 995 996 997 998 999 1000
	if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
		if (term->no_value &&
		    bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) {
			if (err) {
				err->idx = term->err_val;
				err->str = strdup("no value assigned for term");
			}
			return -EINVAL;
		}

1001
		val = term->val.num;
1002
	} else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
1003
		if (strcmp(term->val.str, "?")) {
1004
			if (verbose > 0) {
1005 1006
				pr_info("Invalid sysfs entry %s=%s\n",
						term->config, term->val.str);
1007 1008 1009 1010 1011
			}
			if (err) {
				err->idx = term->err_val;
				err->str = strdup("expected numeric value");
			}
1012 1013 1014 1015 1016 1017 1018 1019
			return -EINVAL;
		}

		if (pmu_resolve_param_term(term, head_terms, &val))
			return -EINVAL;
	} else
		return -EINVAL;

1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
	max_val = pmu_format_max_value(format->bits);
	if (val > max_val) {
		if (err) {
			err->idx = term->err_val;
			if (asprintf(&err->str,
				     "value too big for format, maximum is %llu",
				     (unsigned long long)max_val) < 0)
				err->str = strdup("value too big for format");
			return -EINVAL;
		}
		/*
		 * Assume we don't care if !err, in which case the value will be
		 * silently truncated.
		 */
	}

1036
	pmu_format_value(format->bits, val, vp, zero);
1037 1038 1039
	return 0;
}

1040 1041
int perf_pmu__config_terms(struct list_head *formats,
			   struct perf_event_attr *attr,
1042
			   struct list_head *head_terms,
1043
			   bool zero, struct parse_events_error *err)
1044
{
1045
	struct parse_events_term *term;
1046

1047
	list_for_each_entry(term, head_terms, list) {
1048 1049
		if (pmu_config_term(formats, attr, term, head_terms,
				    zero, err))
1050
			return -EINVAL;
1051
	}
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061

	return 0;
}

/*
 * Configures event's 'attr' parameter based on the:
 * 1) users input - specified in terms parameter
 * 2) pmu format definitions - specified by pmu parameter
 */
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
1062 1063
		     struct list_head *head_terms,
		     struct parse_events_error *err)
1064
{
1065 1066
	bool zero = !!pmu->default_config;

1067
	attr->type = pmu->type;
1068 1069
	return perf_pmu__config_terms(&pmu->format, attr, head_terms,
				      zero, err);
1070 1071
}

1072 1073
static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
					     struct parse_events_term *term)
1074
{
1075
	struct perf_pmu_alias *alias;
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
	char *name;

	if (parse_events__is_hardcoded_term(term))
		return NULL;

	if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
		if (term->val.num != 1)
			return NULL;
		if (pmu_find_format(&pmu->format, term->config))
			return NULL;
		name = term->config;
	} else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
		if (strcasecmp(term->config, "event"))
			return NULL;
		name = term->val.str;
	} else {
		return NULL;
	}

	list_for_each_entry(alias, &pmu->aliases, list) {
		if (!strcasecmp(alias->name, name))
			return alias;
	}
	return NULL;
}

1102

1103 1104
static int check_info_data(struct perf_pmu_alias *alias,
			   struct perf_pmu_info *info)
1105 1106 1107
{
	/*
	 * Only one term in event definition can
1108 1109
	 * define unit, scale and snapshot, fail
	 * if there's more than one.
1110
	 */
1111
	if ((info->unit && alias->unit[0]) ||
1112 1113
	    (info->scale && alias->scale) ||
	    (info->snapshot && alias->snapshot))
1114 1115
		return -EINVAL;

1116
	if (alias->unit[0])
1117
		info->unit = alias->unit;
1118 1119

	if (alias->scale)
1120 1121 1122 1123
		info->scale = alias->scale;

	if (alias->snapshot)
		info->snapshot = alias->snapshot;
1124 1125 1126 1127

	return 0;
}

1128 1129 1130 1131
/*
 * Find alias in the terms list and replace it with the terms
 * defined for the alias
 */
1132
int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
1133
			  struct perf_pmu_info *info)
1134
{
1135
	struct parse_events_term *term, *h;
1136
	struct perf_pmu_alias *alias;
1137 1138
	int ret;

1139 1140
	info->per_pkg = false;

1141 1142 1143 1144
	/*
	 * Mark unit and scale as not set
	 * (different from default values, see below)
	 */
1145 1146 1147
	info->unit     = NULL;
	info->scale    = 0.0;
	info->snapshot = false;
1148
	info->metric_expr = NULL;
1149
	info->metric_name = NULL;
1150

1151 1152 1153 1154 1155 1156 1157
	list_for_each_entry_safe(term, h, head_terms, list) {
		alias = pmu_find_alias(pmu, term);
		if (!alias)
			continue;
		ret = pmu_alias_terms(alias, &term->list);
		if (ret)
			return ret;
1158

1159
		ret = check_info_data(alias, info);
1160 1161 1162
		if (ret)
			return ret;

1163 1164
		if (alias->per_pkg)
			info->per_pkg = true;
1165
		info->metric_expr = alias->metric_expr;
1166
		info->metric_name = alias->metric_name;
1167

1168 1169 1170
		list_del(&term->list);
		free(term);
	}
1171 1172 1173 1174 1175 1176

	/*
	 * if no unit or scale foundin aliases, then
	 * set defaults as for evsel
	 * unit cannot left to NULL
	 */
1177 1178
	if (info->unit == NULL)
		info->unit   = "";
1179

1180 1181
	if (info->scale == 0.0)
		info->scale  = 1.0;
1182

1183 1184 1185
	return 0;
}

1186 1187 1188
int perf_pmu__new_format(struct list_head *list, char *name,
			 int config, unsigned long *bits)
{
1189
	struct perf_pmu_format *format;
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209

	format = zalloc(sizeof(*format));
	if (!format)
		return -ENOMEM;

	format->name = strdup(name);
	format->value = config;
	memcpy(format->bits, bits, sizeof(format->bits));

	list_add_tail(&format->list, list);
	return 0;
}

void perf_pmu__set_format(unsigned long *bits, long from, long to)
{
	long b;

	if (!to)
		to = from;

1210
	memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
1211 1212 1213
	for (b = from; b <= to; b++)
		set_bit(b, bits);
}
1214

1215 1216 1217 1218 1219 1220 1221
static int sub_non_neg(int a, int b)
{
	if (b > a)
		return 0;
	return a - b;
}

1222 1223 1224
static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
			  struct perf_pmu_alias *alias)
{
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
	struct parse_events_term *term;
	int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);

	list_for_each_entry(term, &alias->terms, list) {
		if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
			used += snprintf(buf + used, sub_non_neg(len, used),
					",%s=%s", term->config,
					term->val.str);
	}

	if (sub_non_neg(len, used) > 0) {
		buf[used] = '/';
		used++;
	}
	if (sub_non_neg(len, used) > 0) {
		buf[used] = '\0';
		used++;
	} else
		buf[len - 1] = '\0';

1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
	return buf;
}

static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
			     struct perf_pmu_alias *alias)
{
	snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
	return buf;
}

1255
struct sevent {
A
Andi Kleen 已提交
1256 1257
	char *name;
	char *desc;
1258
	char *topic;
1259 1260
	char *str;
	char *pmu;
1261
	char *metric_expr;
1262
	char *metric_name;
A
Andi Kleen 已提交
1263 1264
};

1265
static int cmp_sevent(const void *a, const void *b)
A
Andi Kleen 已提交
1266
{
1267 1268
	const struct sevent *as = a;
	const struct sevent *bs = b;
A
Andi Kleen 已提交
1269 1270 1271 1272

	/* Put extra events last */
	if (!!as->desc != !!bs->desc)
		return !!as->desc - !!bs->desc;
1273 1274 1275 1276 1277 1278
	if (as->topic && bs->topic) {
		int n = strcmp(as->topic, bs->topic);

		if (n)
			return n;
	}
A
Andi Kleen 已提交
1279 1280 1281 1282
	return strcmp(as->name, bs->name);
}

static void wordwrap(char *s, int start, int max, int corr)
1283
{
A
Andi Kleen 已提交
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
	int column = start;
	int n;

	while (*s) {
		int wlen = strcspn(s, " \t");

		if (column + wlen >= max && column > start) {
			printf("\n%*s", start, "");
			column = start + corr;
		}
		n = printf("%s%.*s", column > start ? " " : "", wlen, s);
		if (n <= 0)
			break;
		s += wlen;
		column += n;
1299
		s = ltrim(s);
A
Andi Kleen 已提交
1300
	}
1301 1302
}

1303
void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1304
			bool long_desc, bool details_flag)
1305 1306 1307 1308 1309 1310
{
	struct perf_pmu *pmu;
	struct perf_pmu_alias *alias;
	char buf[1024];
	int printed = 0;
	int len, j;
1311
	struct sevent *aliases;
A
Andi Kleen 已提交
1312
	int numdesc = 0;
1313
	int columns = pager_get_columns();
1314
	char *topic = NULL;
1315 1316 1317

	pmu = NULL;
	len = 0;
1318
	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1319 1320
		list_for_each_entry(alias, &pmu->aliases, list)
			len++;
1321 1322 1323
		if (pmu->selectable)
			len++;
	}
1324
	aliases = zalloc(sizeof(struct sevent) * len);
1325
	if (!aliases)
1326
		goto out_enomem;
1327 1328
	pmu = NULL;
	j = 0;
1329
	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1330
		list_for_each_entry(alias, &pmu->aliases, list) {
A
Andi Kleen 已提交
1331 1332
			char *name = alias->desc ? alias->name :
				format_alias(buf, sizeof(buf), pmu, alias);
1333 1334 1335
			bool is_cpu = !strcmp(pmu->name, "cpu");

			if (event_glob != NULL &&
1336 1337
			    !(strglobmatch_nocase(name, event_glob) ||
			      (!is_cpu && strglobmatch_nocase(alias->name,
A
Andi Kleen 已提交
1338 1339 1340
						       event_glob)) ||
			      (alias->topic &&
			       strglobmatch_nocase(alias->topic, event_glob))))
1341
				continue;
1342

A
Andi Kleen 已提交
1343
			if (is_cpu && !name_only && !alias->desc)
1344 1345
				name = format_alias_or(buf, sizeof(buf), pmu, alias);

A
Andi Kleen 已提交
1346 1347 1348 1349 1350 1351 1352
			aliases[j].name = name;
			if (is_cpu && !name_only && !alias->desc)
				aliases[j].name = format_alias_or(buf,
								  sizeof(buf),
								  pmu, alias);
			aliases[j].name = strdup(aliases[j].name);
			if (!aliases[j].name)
1353
				goto out_enomem;
A
Andi Kleen 已提交
1354

1355 1356
			aliases[j].desc = long_desc ? alias->long_desc :
						alias->desc;
1357
			aliases[j].topic = alias->topic;
1358 1359
			aliases[j].str = alias->str;
			aliases[j].pmu = pmu->name;
1360
			aliases[j].metric_expr = alias->metric_expr;
1361
			aliases[j].metric_name = alias->metric_name;
1362 1363
			j++;
		}
1364 1365
		if (pmu->selectable &&
		    (event_glob == NULL || strglobmatch(pmu->name, event_glob))) {
1366 1367 1368
			char *s;
			if (asprintf(&s, "%s//", pmu->name) < 0)
				goto out_enomem;
A
Andi Kleen 已提交
1369
			aliases[j].name = s;
1370 1371 1372
			j++;
		}
	}
1373
	len = j;
1374
	qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
1375
	for (j = 0; j < len; j++) {
1376 1377 1378
		/* Skip duplicates */
		if (j > 0 && !strcmp(aliases[j].name, aliases[j - 1].name))
			continue;
1379
		if (name_only) {
A
Andi Kleen 已提交
1380
			printf("%s ", aliases[j].name);
1381 1382
			continue;
		}
A
Andi Kleen 已提交
1383
		if (aliases[j].desc && !quiet_flag) {
A
Andi Kleen 已提交
1384 1385
			if (numdesc++ == 0)
				printf("\n");
1386 1387 1388 1389 1390 1391
			if (aliases[j].topic && (!topic ||
					strcmp(topic, aliases[j].topic))) {
				printf("%s%s:\n", topic ? "\n" : "",
						aliases[j].topic);
				topic = aliases[j].topic;
			}
A
Andi Kleen 已提交
1392 1393 1394 1395
			printf("  %-50s\n", aliases[j].name);
			printf("%*s", 8, "[");
			wordwrap(aliases[j].desc, 8, columns, 0);
			printf("]\n");
1396
			if (details_flag) {
1397
				printf("%*s%s/%s/ ", 8, "", aliases[j].pmu, aliases[j].str);
1398 1399
				if (aliases[j].metric_name)
					printf(" MetricName: %s", aliases[j].metric_name);
1400 1401 1402 1403
				if (aliases[j].metric_expr)
					printf(" MetricExpr: %s", aliases[j].metric_expr);
				putchar('\n');
			}
A
Andi Kleen 已提交
1404 1405
		} else
			printf("  %-50s [Kernel PMU event]\n", aliases[j].name);
1406 1407
		printed++;
	}
1408
	if (printed && pager_in_use())
1409
		printf("\n");
1410 1411
out_free:
	for (j = 0; j < len; j++)
A
Andi Kleen 已提交
1412
		zfree(&aliases[j].name);
1413 1414 1415 1416 1417 1418 1419
	zfree(&aliases);
	return;

out_enomem:
	printf("FATAL: not enough memory to print PMU events\n");
	if (aliases)
		goto out_free;
1420
}
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436

bool pmu_have_event(const char *pname, const char *name)
{
	struct perf_pmu *pmu;
	struct perf_pmu_alias *alias;

	pmu = NULL;
	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
		if (strcmp(pname, pmu->name))
			continue;
		list_for_each_entry(alias, &pmu->aliases, list)
			if (!strcmp(alias->name, name))
				return true;
	}
	return false;
}
1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472

static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
{
	struct stat st;
	char path[PATH_MAX];
	const char *sysfs;

	sysfs = sysfs__mountpoint();
	if (!sysfs)
		return NULL;

	snprintf(path, PATH_MAX,
		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);

	if (stat(path, &st) < 0)
		return NULL;

	return fopen(path, "r");
}

int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
			...)
{
	va_list args;
	FILE *file;
	int ret = EOF;

	va_start(args, fmt);
	file = perf_pmu__open_file(pmu, name);
	if (file) {
		ret = vfscanf(file, fmt, args);
		fclose(file);
	}
	va_end(args);
	return ret;
}