parse-events.c 21.9 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(const struct option *opt, 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
		if (len < 0)
			return EVT_FAILED;

483
		if (parse_events(opt, event_opt, 0))
484 485 486 487 488 489
			return EVT_FAILED;
	}

	return EVT_HANDLED_ALL;
}

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

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

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

	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;
513

514 515 516 517 518
	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);
	}
519 520
	flags = strchr(evt_name, ':');
	if (flags) {
521 522
		/* split it out: */
		evt_name = strndup(evt_name, flags - evt_name);
523 524 525
		flags++;
	}

526 527
	evt_length = strlen(evt_name);
	if (evt_length >= MAX_EVENT_LENGTH)
528
		return EVT_FAILED;
529
	if (strpbrk(evt_name, "*?")) {
530
		*strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
531
		return parse_multiple_tracepoint_event(opt, sys_name, evt_name,
532
						       flags);
533
	} else {
534
		return parse_single_tracepoint_event(sys_name, evt_name,
535
						     evt_length, attr, strp);
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 606
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;
	}

607 608 609 610 611 612 613 614 615
	/*
	 * 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;

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

	return EVT_HANDLED;
}

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

625 626 627 628 629 630 631 632
	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;
633 634 635
	return 0;
}

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

643 644 645 646 647 648
	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;
649
			return EVT_HANDLED;
650 651
		}
	}
652
	return EVT_FAILED;
653 654
}

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

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

674
static enum event_result
675
parse_numeric_event(const char **strp, struct perf_event_attr *attr)
676 677 678 679 680 681 682 683 684 685 686 687 688 689
{
	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;
690
			return EVT_HANDLED;
691
		}
692
	}
693
	return EVT_FAILED;
694 695
}

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

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

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

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

746
	ret = parse_tracepoint_event(opt, str, attr);
747 748 749 750 751 752
	if (ret != EVT_FAILED)
		goto modifier;

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

754 755 756 757 758 759 760 761 762 763 764 765
	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;

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

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

modifier:
775
	parse_event_modifier(str, attr);
776

777
	return ret;
778 779
}

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

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

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

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

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

	return 0;
}

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

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

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

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

	return 0;
}

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

847 848 849 850 851 852 853 854 855
/*
 * 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 已提交
856
	char dir_path[MAXPATHLEN];
857

858
	if (debugfs_valid_mountpoint(debugfs_path))
859 860
		return;

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

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

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

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

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 923 924
/*
 * 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;
}

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

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

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

940
		if (type != prev_type)
941
			printf("\n");
942

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

950
		prev_type = type;
951 952
	}

953
	printf("\n");
954 955 956 957 958 959 960
	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++) {
961
				printf("  %-42s [%s]\n",
962
					event_cache_name(type, op, i),
963
					event_type_descriptors[PERF_TYPE_HW_CACHE]);
964 965 966 967
			}
		}
	}

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

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

979 980
	print_tracepoint_events();

981
	exit(129);
982
}