parse-events.c 21.8 KB
Newer Older
1
#include "../../../include/linux/hw_breakpoint.h"
2
#include "util.h"
3
#include "../perf.h"
4
#include "evlist.h"
5
#include "evsel.h"
6 7 8
#include "parse-options.h"
#include "parse-events.h"
#include "exec_cmd.h"
9
#include "string.h"
10
#include "symbol.h"
11
#include "cache.h"
12
#include "header.h"
13
#include "debugfs.h"
14 15

struct event_symbol {
16 17 18 19
	u8		type;
	u64		config;
	const char	*symbol;
	const char	*alias;
20 21
};

22 23 24 25 26 27
enum event_result {
	EVT_FAILED,
	EVT_HANDLED,
	EVT_HANDLED_ALL
};

28 29
char debugfs_path[MAXPATHLEN];

30 31
#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
32

33
static struct event_symbol event_symbols[] = {
34 35 36 37 38 39 40 41 42 43
  { CHW(CPU_CYCLES),		"cpu-cycles",		"cycles"	},
  { CHW(INSTRUCTIONS),		"instructions",		""		},
  { CHW(CACHE_REFERENCES),	"cache-references",	""		},
  { CHW(CACHE_MISSES),		"cache-misses",		""		},
  { CHW(BRANCH_INSTRUCTIONS),	"branch-instructions",	"branches"	},
  { CHW(BRANCH_MISSES),		"branch-misses",	""		},
  { CHW(BUS_CYCLES),		"bus-cycles",		""		},

  { CSW(CPU_CLOCK),		"cpu-clock",		""		},
  { CSW(TASK_CLOCK),		"task-clock",		""		},
44
  { CSW(PAGE_FAULTS),		"page-faults",		"faults"	},
45 46 47 48
  { CSW(PAGE_FAULTS_MIN),	"minor-faults",		""		},
  { CSW(PAGE_FAULTS_MAJ),	"major-faults",		""		},
  { CSW(CONTEXT_SWITCHES),	"context-switches",	"cs"		},
  { CSW(CPU_MIGRATIONS),	"cpu-migrations",	"migrations"	},
49 50
  { CSW(ALIGNMENT_FAULTS),	"alignment-faults",	""		},
  { CSW(EMULATION_FAULTS),	"emulation-faults",	""		},
51 52
};

53 54
#define __PERF_EVENT_FIELD(config, name) \
	((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT)
55

56 57 58 59
#define PERF_EVENT_RAW(config)	__PERF_EVENT_FIELD(config, RAW)
#define PERF_EVENT_CONFIG(config)	__PERF_EVENT_FIELD(config, CONFIG)
#define PERF_EVENT_TYPE(config)	__PERF_EVENT_FIELD(config, TYPE)
#define PERF_EVENT_ID(config)		__PERF_EVENT_FIELD(config, EVENT)
60

61
static const char *hw_event_names[] = {
62
	"cycles",
63
	"instructions",
64 65
	"cache-references",
	"cache-misses",
66
	"branches",
67 68
	"branch-misses",
	"bus-cycles",
69 70
};

71
static const char *sw_event_names[] = {
I
Ingo Molnar 已提交
72 73
	"cpu-clock-msecs",
	"task-clock-msecs",
74 75 76 77 78
	"page-faults",
	"context-switches",
	"CPU-migrations",
	"minor-faults",
	"major-faults",
79 80
	"alignment-faults",
	"emulation-faults",
81 82
};

83 84
#define MAX_ALIASES 8

85
static const char *hw_cache[][MAX_ALIASES] = {
86 87
 { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		},
 { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	},
88 89 90 91
 { "LLC",	"L2"							},
 { "dTLB",	"d-tlb",	"Data-TLB",				},
 { "iTLB",	"i-tlb",	"Instruction-TLB",			},
 { "branch",	"branches",	"bpu",		"btb",		"bpc",	},
92 93
};

94
static const char *hw_cache_op[][MAX_ALIASES] = {
95 96 97
 { "load",	"loads",	"read",					},
 { "store",	"stores",	"write",				},
 { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	},
98 99
};

100
static const char *hw_cache_result[][MAX_ALIASES] = {
101 102
 { "refs",	"Reference",	"ops",		"access",		},
 { "misses",	"miss",							},
103 104
};

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
#define C(x)		PERF_COUNT_HW_CACHE_##x
#define CACHE_READ	(1 << C(OP_READ))
#define CACHE_WRITE	(1 << C(OP_WRITE))
#define CACHE_PREFETCH	(1 << C(OP_PREFETCH))
#define COP(x)		(1 << x)

/*
 * cache operartion stat
 * L1I : Read and prefetch only
 * ITLB and BPU : Read-only
 */
static unsigned long hw_cache_stat[C(MAX)] = {
 [C(L1D)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 [C(L1I)]	= (CACHE_READ | CACHE_PREFETCH),
 [C(LL)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 [C(DTLB)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
 [C(ITLB)]	= (CACHE_READ),
 [C(BPU)]	= (CACHE_READ),
};

125
#define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
126
	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \
127
	if (sys_dirent.d_type == DT_DIR &&				       \
128 129 130
	   (strcmp(sys_dirent.d_name, ".")) &&				       \
	   (strcmp(sys_dirent.d_name, "..")))

131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
{
	char evt_path[MAXPATHLEN];
	int fd;

	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
			sys_dir->d_name, evt_dir->d_name);
	fd = open(evt_path, O_RDONLY);
	if (fd < 0)
		return -EINVAL;
	close(fd);

	return 0;
}

146
#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)	       \
147
	while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
148
	if (evt_dirent.d_type == DT_DIR &&				       \
149
	   (strcmp(evt_dirent.d_name, ".")) &&				       \
150 151
	   (strcmp(evt_dirent.d_name, "..")) &&				       \
	   (!tp_event_has_id(&sys_dirent, &evt_dirent)))
152

L
Li Zefan 已提交
153
#define MAX_EVENT_LENGTH 512
154 155


156
struct tracepoint_path *tracepoint_id_to_path(u64 config)
157
{
158
	struct tracepoint_path *path = NULL;
159 160 161
	DIR *sys_dir, *evt_dir;
	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
	char id_buf[4];
E
Eric Dumazet 已提交
162
	int fd;
163 164
	u64 id;
	char evt_path[MAXPATHLEN];
E
Eric Dumazet 已提交
165
	char dir_path[MAXPATHLEN];
166

167
	if (debugfs_valid_mountpoint(debugfs_path))
168
		return NULL;
169

170
	sys_dir = opendir(debugfs_path);
171
	if (!sys_dir)
E
Eric Dumazet 已提交
172
		return NULL;
173 174

	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
E
Eric Dumazet 已提交
175 176 177 178 179

		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
			 sys_dirent.d_name);
		evt_dir = opendir(dir_path);
		if (!evt_dir)
180
			continue;
E
Eric Dumazet 已提交
181

182
		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
E
Eric Dumazet 已提交
183 184

			snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
185
				 evt_dirent.d_name);
E
Eric Dumazet 已提交
186
			fd = open(evt_path, O_RDONLY);
187 188 189 190 191 192 193 194 195 196 197
			if (fd < 0)
				continue;
			if (read(fd, id_buf, sizeof(id_buf)) < 0) {
				close(fd);
				continue;
			}
			close(fd);
			id = atoll(id_buf);
			if (id == config) {
				closedir(evt_dir);
				closedir(sys_dir);
198
				path = zalloc(sizeof(*path));
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
				path->system = malloc(MAX_EVENT_LENGTH);
				if (!path->system) {
					free(path);
					return NULL;
				}
				path->name = malloc(MAX_EVENT_LENGTH);
				if (!path->name) {
					free(path->system);
					free(path);
					return NULL;
				}
				strncpy(path->system, sys_dirent.d_name,
					MAX_EVENT_LENGTH);
				strncpy(path->name, evt_dirent.d_name,
					MAX_EVENT_LENGTH);
				return path;
215 216 217 218 219 220
			}
		}
		closedir(evt_dir);
	}

	closedir(sys_dir);
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
	return NULL;
}

#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
static const char *tracepoint_id_to_name(u64 config)
{
	static char buf[TP_PATH_LEN];
	struct tracepoint_path *path;

	path = tracepoint_id_to_path(config);
	if (path) {
		snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
		free(path->name);
		free(path->system);
		free(path);
	} else
		snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");

	return buf;
240 241
}

242 243 244 245 246 247 248 249
static int is_cache_op_valid(u8 cache_type, u8 cache_op)
{
	if (hw_cache_stat[cache_type] & COP(cache_op))
		return 1;	/* valid */
	else
		return 0;	/* invalid */
}

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
{
	static char name[50];

	if (cache_result) {
		sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
			hw_cache_op[cache_op][0],
			hw_cache_result[cache_result][0]);
	} else {
		sprintf(name, "%s-%s", hw_cache[cache_type][0],
			hw_cache_op[cache_op][1]);
	}

	return name;
}

266
const char *event_name(struct perf_evsel *evsel)
267
{
268 269
	u64 config = evsel->attr.config;
	int type = evsel->attr.type;
270 271 272 273

	return __event_name(type, config);
}

274
const char *__event_name(int type, u64 config)
275
{
276 277
	static char buf[32];

278
	if (type == PERF_TYPE_RAW) {
279
		sprintf(buf, "raw 0x%" PRIx64, config);
280 281 282 283 284
		return buf;
	}

	switch (type) {
	case PERF_TYPE_HARDWARE:
285
		if (config < PERF_COUNT_HW_MAX)
286
			return hw_event_names[config];
287 288
		return "unknown-hardware";

289
	case PERF_TYPE_HW_CACHE: {
290
		u8 cache_type, cache_op, cache_result;
291 292 293 294 295 296

		cache_type   = (config >>  0) & 0xff;
		if (cache_type > PERF_COUNT_HW_CACHE_MAX)
			return "unknown-ext-hardware-cache-type";

		cache_op     = (config >>  8) & 0xff;
297 298
		if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
			return "unknown-ext-hardware-cache-op";
299 300

		cache_result = (config >> 16) & 0xff;
301 302
		if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
			return "unknown-ext-hardware-cache-result";
303

304 305
		if (!is_cache_op_valid(cache_type, cache_op))
			return "invalid-cache";
306

307
		return event_cache_name(cache_type, cache_op, cache_result);
308 309
	}

310
	case PERF_TYPE_SOFTWARE:
311
		if (config < PERF_COUNT_SW_MAX)
312
			return sw_event_names[config];
313 314
		return "unknown-software";

315 316 317
	case PERF_TYPE_TRACEPOINT:
		return tracepoint_id_to_name(config);

318 319 320 321 322 323 324
	default:
		break;
	}

	return "unknown";
}

325
static int parse_aliases(const char **str, const char *names[][MAX_ALIASES], int size)
326 327
{
	int i, j;
328
	int n, longest = -1;
329 330

	for (i = 0; i < size; i++) {
331 332 333 334 335 336 337 338
		for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
			n = strlen(names[i][j]);
			if (n > longest && !strncasecmp(*str, names[i][j], n))
				longest = n;
		}
		if (longest > 0) {
			*str += longest;
			return i;
339 340 341
		}
	}

342
	return -1;
343 344
}

345
static enum event_result
346
parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
347
{
348 349
	const char *s = *str;
	int cache_type = -1, cache_op = -1, cache_result = -1;
350

351
	cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
352 353 354 355 356
	/*
	 * No fallback - if we cannot get a clear cache type
	 * then bail out:
	 */
	if (cache_type == -1)
357
		return EVT_FAILED;
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385

	while ((cache_op == -1 || cache_result == -1) && *s == '-') {
		++s;

		if (cache_op == -1) {
			cache_op = parse_aliases(&s, hw_cache_op,
						PERF_COUNT_HW_CACHE_OP_MAX);
			if (cache_op >= 0) {
				if (!is_cache_op_valid(cache_type, cache_op))
					return 0;
				continue;
			}
		}

		if (cache_result == -1) {
			cache_result = parse_aliases(&s, hw_cache_result,
						PERF_COUNT_HW_CACHE_RESULT_MAX);
			if (cache_result >= 0)
				continue;
		}

		/*
		 * Can't parse this as a cache op or result, so back up
		 * to the '-'.
		 */
		--s;
		break;
	}
386 387 388 389

	/*
	 * Fall back to reads:
	 */
390 391
	if (cache_op == -1)
		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
392 393 394 395 396 397 398 399 400 401

	/*
	 * Fall back to accesses:
	 */
	if (cache_result == -1)
		cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;

	attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
	attr->type = PERF_TYPE_HW_CACHE;

402
	*str = s;
403 404 405 406 407 408 409
	return EVT_HANDLED;
}

static enum event_result
parse_single_tracepoint_event(char *sys_name,
			      const char *evt_name,
			      unsigned int evt_length,
410
			      struct perf_event_attr *attr,
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
			      const char **strp)
{
	char evt_path[MAXPATHLEN];
	char id_buf[4];
	u64 id;
	int fd;

	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
		 sys_name, evt_name);

	fd = open(evt_path, O_RDONLY);
	if (fd < 0)
		return EVT_FAILED;

	if (read(fd, id_buf, sizeof(id_buf)) < 0) {
		close(fd);
		return EVT_FAILED;
	}

	close(fd);
	id = atoll(id_buf);
	attr->config = id;
	attr->type = PERF_TYPE_TRACEPOINT;
434
	*strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
435

436 437 438 439 440 441 442
	attr->sample_type |= PERF_SAMPLE_RAW;
	attr->sample_type |= PERF_SAMPLE_TIME;
	attr->sample_type |= PERF_SAMPLE_CPU;

	attr->sample_period = 1;


443
	return EVT_HANDLED;
444 445
}

446 447 448
/* sys + ':' + event + ':' + flags*/
#define MAX_EVOPT_LEN	(MAX_EVENT_LENGTH * 2 + 2 + 128)
static enum event_result
449 450
parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
				char *flags)
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
{
	char evt_path[MAXPATHLEN];
	struct dirent *evt_ent;
	DIR *evt_dir;

	snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name);
	evt_dir = opendir(evt_path);

	if (!evt_dir) {
		perror("Can't open event dir");
		return EVT_FAILED;
	}

	while ((evt_ent = readdir(evt_dir))) {
		char event_opt[MAX_EVOPT_LEN + 1];
		int len;

		if (!strcmp(evt_ent->d_name, ".")
		    || !strcmp(evt_ent->d_name, "..")
		    || !strcmp(evt_ent->d_name, "enable")
		    || !strcmp(evt_ent->d_name, "filter"))
			continue;

474 475 476
		if (!strglobmatch(evt_ent->d_name, evt_exp))
			continue;

477 478 479
		len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name,
			       evt_ent->d_name, flags ? ":" : "",
			       flags ?: "");
480 481 482 483 484 485 486 487 488 489 490
		if (len < 0)
			return EVT_FAILED;

		if (parse_events(NULL, event_opt, 0))
			return EVT_FAILED;
	}

	return EVT_HANDLED_ALL;
}

static enum event_result parse_tracepoint_event(const char **strp,
491
				    struct perf_event_attr *attr)
492 493
{
	const char *evt_name;
494
	char *flags = NULL, *comma_loc;
495 496 497
	char sys_name[MAX_EVENT_LENGTH];
	unsigned int sys_length, evt_length;

498
	if (debugfs_valid_mountpoint(debugfs_path))
499 500 501 502
		return 0;

	evt_name = strchr(*strp, ':');
	if (!evt_name)
503
		return EVT_FAILED;
504 505 506 507 508 509 510 511

	sys_length = evt_name - *strp;
	if (sys_length >= MAX_EVENT_LENGTH)
		return 0;

	strncpy(sys_name, *strp, sys_length);
	sys_name[sys_length] = '\0';
	evt_name = evt_name + 1;
512

513 514 515 516 517
	comma_loc = strchr(evt_name, ',');
	if (comma_loc) {
		/* take the event name up to the comma */
		evt_name = strndup(evt_name, comma_loc - evt_name);
	}
518 519
	flags = strchr(evt_name, ':');
	if (flags) {
520 521
		/* split it out: */
		evt_name = strndup(evt_name, flags - evt_name);
522 523 524
		flags++;
	}

525 526
	evt_length = strlen(evt_name);
	if (evt_length >= MAX_EVENT_LENGTH)
527
		return EVT_FAILED;
528
	if (strpbrk(evt_name, "*?")) {
529
		*strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
530 531
		return parse_multiple_tracepoint_event(sys_name, evt_name,
						       flags);
532
	} else {
533
		return parse_single_tracepoint_event(sys_name, evt_name,
534
						     evt_length, attr, strp);
535
	}
536 537
}

538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
static enum event_result
parse_breakpoint_type(const char *type, const char **strp,
		      struct perf_event_attr *attr)
{
	int i;

	for (i = 0; i < 3; i++) {
		if (!type[i])
			break;

		switch (type[i]) {
		case 'r':
			attr->bp_type |= HW_BREAKPOINT_R;
			break;
		case 'w':
			attr->bp_type |= HW_BREAKPOINT_W;
			break;
		case 'x':
			attr->bp_type |= HW_BREAKPOINT_X;
			break;
		default:
			return EVT_FAILED;
		}
	}
	if (!attr->bp_type) /* Default */
		attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;

	*strp = type + i;

	return EVT_HANDLED;
}

static enum event_result
parse_breakpoint_event(const char **strp, struct perf_event_attr *attr)
{
	const char *target;
	const char *type;
	char *endaddr;
	u64 addr;
	enum event_result err;

	target = strchr(*strp, ':');
	if (!target)
		return EVT_FAILED;

	if (strncmp(*strp, "mem", target - *strp) != 0)
		return EVT_FAILED;

	target++;

	addr = strtoull(target, &endaddr, 0);
	if (target == endaddr)
		return EVT_FAILED;

	attr->bp_addr = addr;
	*strp = endaddr;

	type = strchr(target, ':');

	/* If no type is defined, just rw as default */
	if (!type) {
		attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
	} else {
		err = parse_breakpoint_type(++type, strp, attr);
		if (err == EVT_FAILED)
			return EVT_FAILED;
	}

606 607 608 609 610 611 612 613 614
	/*
	 * We should find a nice way to override the access length
	 * Provide some defaults for now
	 */
	if (attr->bp_type == HW_BREAKPOINT_X)
		attr->bp_len = sizeof(long);
	else
		attr->bp_len = HW_BREAKPOINT_LEN_4;

615 616 617 618 619
	attr->type = PERF_TYPE_BREAKPOINT;

	return EVT_HANDLED;
}

620 621
static int check_events(const char *str, unsigned int i)
{
622
	int n;
623

624 625 626 627 628 629 630 631
	n = strlen(event_symbols[i].symbol);
	if (!strncmp(str, event_symbols[i].symbol, n))
		return n;

	n = strlen(event_symbols[i].alias);
	if (n)
		if (!strncmp(str, event_symbols[i].alias, n))
			return n;
632 633 634
	return 0;
}

635
static enum event_result
636
parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
637
{
638
	const char *str = *strp;
639
	unsigned int i;
640
	int n;
641

642 643 644 645 646 647
	for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
		n = check_events(str, i);
		if (n > 0) {
			attr->type = event_symbols[i].type;
			attr->config = event_symbols[i].config;
			*strp = str + n;
648
			return EVT_HANDLED;
649 650
		}
	}
651
	return EVT_FAILED;
652 653
}

654
static enum event_result
655
parse_raw_event(const char **strp, struct perf_event_attr *attr)
656 657 658 659
{
	const char *str = *strp;
	u64 config;
	int n;
660

661
	if (*str != 'r')
662
		return EVT_FAILED;
663 664 665 666 667
	n = hex2u64(str + 1, &config);
	if (n > 0) {
		*strp = str + n + 1;
		attr->type = PERF_TYPE_RAW;
		attr->config = config;
668
		return EVT_HANDLED;
669
	}
670
	return EVT_FAILED;
671
}
672

673
static enum event_result
674
parse_numeric_event(const char **strp, struct perf_event_attr *attr)
675 676 677 678 679 680 681 682 683 684 685 686 687 688
{
	const char *str = *strp;
	char *endp;
	unsigned long type;
	u64 config;

	type = strtoul(str, &endp, 0);
	if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
		str = endp + 1;
		config = strtoul(str, &endp, 0);
		if (endp > str) {
			attr->type = type;
			attr->config = config;
			*strp = endp;
689
			return EVT_HANDLED;
690
		}
691
	}
692
	return EVT_FAILED;
693 694
}

695
static enum event_result
696
parse_event_modifier(const char **strp, struct perf_event_attr *attr)
697 698
{
	const char *str = *strp;
P
Peter Zijlstra 已提交
699 700
	int exclude = 0;
	int eu = 0, ek = 0, eh = 0, precise = 0;
701

702
	if (*str++ != ':')
703
		return 0;
704
	while (*str) {
P
Peter Zijlstra 已提交
705 706 707
		if (*str == 'u') {
			if (!exclude)
				exclude = eu = ek = eh = 1;
708
			eu = 0;
P
Peter Zijlstra 已提交
709 710 711
		} else if (*str == 'k') {
			if (!exclude)
				exclude = eu = ek = eh = 1;
712
			ek = 0;
P
Peter Zijlstra 已提交
713 714 715
		} else if (*str == 'h') {
			if (!exclude)
				exclude = eu = ek = eh = 1;
716
			eh = 0;
P
Peter Zijlstra 已提交
717 718 719
		} else if (*str == 'p') {
			precise++;
		} else
720
			break;
P
Peter Zijlstra 已提交
721

722
		++str;
723
	}
724 725 726 727 728
	if (str >= *strp + 2) {
		*strp = str;
		attr->exclude_user   = eu;
		attr->exclude_kernel = ek;
		attr->exclude_hv     = eh;
P
Peter Zijlstra 已提交
729
		attr->precise_ip     = precise;
730 731 732 733
		return 1;
	}
	return 0;
}
734

735 736 737 738
/*
 * Each event can have multiple symbolic names.
 * Symbolic names are (almost) exactly matched.
 */
739
static enum event_result
740
parse_event_symbols(const char **str, struct perf_event_attr *attr)
741
{
742 743 744 745 746 747 748 749 750
	enum event_result ret;

	ret = parse_tracepoint_event(str, attr);
	if (ret != EVT_FAILED)
		goto modifier;

	ret = parse_raw_event(str, attr);
	if (ret != EVT_FAILED)
		goto modifier;
751

752 753 754 755 756 757 758 759 760 761 762 763
	ret = parse_numeric_event(str, attr);
	if (ret != EVT_FAILED)
		goto modifier;

	ret = parse_symbolic_event(str, attr);
	if (ret != EVT_FAILED)
		goto modifier;

	ret = parse_generic_hw_event(str, attr);
	if (ret != EVT_FAILED)
		goto modifier;

764 765 766 767
	ret = parse_breakpoint_event(str, attr);
	if (ret != EVT_FAILED)
		goto modifier;

768 769
	fprintf(stderr, "invalid or unsupported event: '%s'\n", *str);
	fprintf(stderr, "Run 'perf list' for a list of valid events\n");
770 771 772
	return EVT_FAILED;

modifier:
773
	parse_event_modifier(str, attr);
774

775
	return ret;
776 777
}

778
int parse_events(const struct option *opt, const char *str, int unset __used)
779
{
780
	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
781
	struct perf_event_attr attr;
782
	enum event_result ret;
783

784 785
	for (;;) {
		memset(&attr, 0, sizeof(attr));
786 787
		ret = parse_event_symbols(&str, &attr);
		if (ret == EVT_FAILED)
788
			return -1;
789

790 791
		if (!(*str == 0 || *str == ',' || isspace(*str)))
			return -1;
792

793
		if (ret != EVT_HANDLED_ALL) {
794
			struct perf_evsel *evsel;
795
			evsel = perf_evsel__new(&attr, evlist->nr_entries);
796 797
			if (evsel == NULL)
				return -1;
798
			perf_evlist__add(evlist, evsel);
799
		}
800

801 802 803 804 805 806
		if (*str == 0)
			break;
		if (*str == ',')
			++str;
		while (isspace(*str))
			++str;
807 808 809 810 811
	}

	return 0;
}

812
int parse_filter(const struct option *opt, const char *str,
L
Li Zefan 已提交
813 814
		 int unset __used)
{
815
	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
816
	struct perf_evsel *last = NULL;
L
Li Zefan 已提交
817

818 819
	if (evlist->nr_entries > 0)
		last = list_entry(evlist->entries.prev, struct perf_evsel, node);
820 821

	if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
L
Li Zefan 已提交
822 823 824 825 826
		fprintf(stderr,
			"-F option should follow a -e tracepoint option\n");
		return -1;
	}

827 828
	last->filter = strdup(str);
	if (last->filter == NULL) {
L
Li Zefan 已提交
829 830 831 832 833 834 835
		fprintf(stderr, "not enough memory to hold filter string\n");
		return -1;
	}

	return 0;
}

836 837 838 839 840
static const char * const event_type_descriptors[] = {
	"Hardware event",
	"Software event",
	"Tracepoint event",
	"Hardware cache event",
841 842
	"Raw hardware event descriptor",
	"Hardware breakpoint",
843 844
};

845 846 847 848 849 850 851 852 853
/*
 * Print the events from <debugfs_mount_point>/tracing/events
 */

static void print_tracepoint_events(void)
{
	DIR *sys_dir, *evt_dir;
	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
	char evt_path[MAXPATHLEN];
E
Eric Dumazet 已提交
854
	char dir_path[MAXPATHLEN];
855

856
	if (debugfs_valid_mountpoint(debugfs_path))
857 858
		return;

859
	sys_dir = opendir(debugfs_path);
860
	if (!sys_dir)
E
Eric Dumazet 已提交
861
		return;
862 863

	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
E
Eric Dumazet 已提交
864 865 866 867 868

		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
			 sys_dirent.d_name);
		evt_dir = opendir(dir_path);
		if (!evt_dir)
869
			continue;
E
Eric Dumazet 已提交
870

871
		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
872 873
			snprintf(evt_path, MAXPATHLEN, "%s:%s",
				 sys_dirent.d_name, evt_dirent.d_name);
874
			printf("  %-42s [%s]\n", evt_path,
875
				event_type_descriptors[PERF_TYPE_TRACEPOINT]);
876 877 878 879 880 881
		}
		closedir(evt_dir);
	}
	closedir(sys_dir);
}

882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
/*
 * Check whether event is in <debugfs_mount_point>/tracing/events
 */

int is_valid_tracepoint(const char *event_string)
{
	DIR *sys_dir, *evt_dir;
	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
	char evt_path[MAXPATHLEN];
	char dir_path[MAXPATHLEN];

	if (debugfs_valid_mountpoint(debugfs_path))
		return 0;

	sys_dir = opendir(debugfs_path);
	if (!sys_dir)
		return 0;

	for_each_subsystem(sys_dir, sys_dirent, sys_next) {

		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
			 sys_dirent.d_name);
		evt_dir = opendir(dir_path);
		if (!evt_dir)
			continue;

		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
			snprintf(evt_path, MAXPATHLEN, "%s:%s",
				 sys_dirent.d_name, evt_dirent.d_name);
			if (!strcmp(evt_path, event_string)) {
				closedir(evt_dir);
				closedir(sys_dir);
				return 1;
			}
		}
		closedir(evt_dir);
	}
	closedir(sys_dir);
	return 0;
}

923
/*
924
 * Print the help text for the event symbols:
925
 */
926
void print_events(void)
927
{
928
	struct event_symbol *syms = event_symbols;
929
	unsigned int i, type, op, prev_type = -1;
930
	char name[40];
931

932 933
	printf("\n");
	printf("List of pre-defined events (to be used in -e):\n");
934

935
	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
936
		type = syms->type;
937

938
		if (type != prev_type)
939
			printf("\n");
940

941 942 943 944
		if (strlen(syms->alias))
			sprintf(name, "%s OR %s", syms->symbol, syms->alias);
		else
			strcpy(name, syms->symbol);
945
		printf("  %-42s [%s]\n", name,
946
			event_type_descriptors[type]);
947

948
		prev_type = type;
949 950
	}

951
	printf("\n");
952 953 954 955 956 957 958
	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
			/* skip invalid cache type */
			if (!is_cache_op_valid(type, op))
				continue;

			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
959
				printf("  %-42s [%s]\n",
960
					event_cache_name(type, op, i),
961
					event_type_descriptors[PERF_TYPE_HW_CACHE]);
962 963 964 965
			}
		}
	}

966
	printf("\n");
967
	printf("  %-42s [%s]\n",
968 969
		"rNNN (see 'perf list --help' on how to encode it)",
	       event_type_descriptors[PERF_TYPE_RAW]);
970
	printf("\n");
971

972 973 974
	printf("  %-42s [%s]\n",
			"mem:<addr>[:access]",
			event_type_descriptors[PERF_TYPE_BREAKPOINT]);
975 976
	printf("\n");

977 978
	print_tracepoint_events();

979
	exit(129);
980
}