parse-events.c 24.2 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
#include "parse-events-flex.h"
15
#include "pmu.h"
16 17

#define MAX_NAME_LEN 100
18 19

struct event_symbol {
20 21 22 23
	u8		type;
	u64		config;
	const char	*symbol;
	const char	*alias;
24 25
};

26
int parse_events_parse(struct list_head *list, int *idx);
27

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

31
static struct event_symbol event_symbols[] = {
32 33 34 35 36 37 38 39 40
  { CHW(CPU_CYCLES),			"cpu-cycles",			"cycles"		},
  { CHW(STALLED_CYCLES_FRONTEND),	"stalled-cycles-frontend",	"idle-cycles-frontend"	},
  { CHW(STALLED_CYCLES_BACKEND),	"stalled-cycles-backend",	"idle-cycles-backend"	},
  { 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",			""			},
41
  { CHW(REF_CPU_CYCLES),		"ref-cycles",			""			},
42 43 44 45 46 47 48 49 50 51

  { CSW(CPU_CLOCK),			"cpu-clock",			""			},
  { CSW(TASK_CLOCK),			"task-clock",			""			},
  { CSW(PAGE_FAULTS),			"page-faults",			"faults"		},
  { CSW(PAGE_FAULTS_MIN),		"minor-faults",			""			},
  { CSW(PAGE_FAULTS_MAJ),		"major-faults",			""			},
  { CSW(CONTEXT_SWITCHES),		"context-switches",		"cs"			},
  { CSW(CPU_MIGRATIONS),		"cpu-migrations",		"migrations"		},
  { CSW(ALIGNMENT_FAULTS),		"alignment-faults",		""			},
  { CSW(EMULATION_FAULTS),		"emulation-faults",		""			},
52 53
};

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

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

62
static const char *hw_event_names[PERF_COUNT_HW_MAX] = {
63
	"cycles",
64
	"instructions",
65 66
	"cache-references",
	"cache-misses",
67
	"branches",
68 69
	"branch-misses",
	"bus-cycles",
70 71
	"stalled-cycles-frontend",
	"stalled-cycles-backend",
72
	"ref-cycles",
73 74
};

75
static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
76 77
	"cpu-clock",
	"task-clock",
78 79 80 81 82
	"page-faults",
	"context-switches",
	"CPU-migrations",
	"minor-faults",
	"major-faults",
83 84
	"alignment-faults",
	"emulation-faults",
85 86
};

87 88
#define MAX_ALIASES 8

89
static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
90 91
 { "L1-dcache",	"l1-d",		"l1d",		"L1-data",		},
 { "L1-icache",	"l1-i",		"l1i",		"L1-instruction",	},
92
 { "LLC",	"L2",							},
93 94 95
 { "dTLB",	"d-tlb",	"Data-TLB",				},
 { "iTLB",	"i-tlb",	"Instruction-TLB",			},
 { "branch",	"branches",	"bpu",		"btb",		"bpc",	},
96
 { "node",								},
97 98
};

99
static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
100 101 102
 { "load",	"loads",	"read",					},
 { "store",	"stores",	"write",				},
 { "prefetch",	"prefetches",	"speculative-read", "speculative-load",	},
103 104
};

105 106
static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
				  [MAX_ALIASES] = {
107 108
 { "refs",	"Reference",	"ops",		"access",		},
 { "misses",	"miss",							},
109 110
};

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
#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),
129
 [C(NODE)]	= (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
130 131
};

132
#define for_each_subsystem(sys_dir, sys_dirent, sys_next)	       \
133
	while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)	       \
134
	if (sys_dirent.d_type == DT_DIR &&				       \
135 136 137
	   (strcmp(sys_dirent.d_name, ".")) &&				       \
	   (strcmp(sys_dirent.d_name, "..")))

138 139 140 141 142
static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
{
	char evt_path[MAXPATHLEN];
	int fd;

143
	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
144 145 146 147 148 149 150 151 152
			sys_dir->d_name, evt_dir->d_name);
	fd = open(evt_path, O_RDONLY);
	if (fd < 0)
		return -EINVAL;
	close(fd);

	return 0;
}

153
#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next)	       \
154
	while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
155
	if (evt_dirent.d_type == DT_DIR &&				       \
156
	   (strcmp(evt_dirent.d_name, ".")) &&				       \
157 158
	   (strcmp(evt_dirent.d_name, "..")) &&				       \
	   (!tp_event_has_id(&sys_dirent, &evt_dirent)))
159

L
Li Zefan 已提交
160
#define MAX_EVENT_LENGTH 512
161 162


163
struct tracepoint_path *tracepoint_id_to_path(u64 config)
164
{
165
	struct tracepoint_path *path = NULL;
166 167
	DIR *sys_dir, *evt_dir;
	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
168
	char id_buf[24];
E
Eric Dumazet 已提交
169
	int fd;
170 171
	u64 id;
	char evt_path[MAXPATHLEN];
E
Eric Dumazet 已提交
172
	char dir_path[MAXPATHLEN];
173

174
	if (debugfs_valid_mountpoint(tracing_events_path))
175
		return NULL;
176

177
	sys_dir = opendir(tracing_events_path);
178
	if (!sys_dir)
E
Eric Dumazet 已提交
179
		return NULL;
180 181

	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
E
Eric Dumazet 已提交
182

183
		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
E
Eric Dumazet 已提交
184 185 186
			 sys_dirent.d_name);
		evt_dir = opendir(dir_path);
		if (!evt_dir)
187
			continue;
E
Eric Dumazet 已提交
188

189
		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
E
Eric Dumazet 已提交
190 191

			snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
192
				 evt_dirent.d_name);
E
Eric Dumazet 已提交
193
			fd = open(evt_path, O_RDONLY);
194 195 196 197 198 199 200 201 202 203 204
			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);
205
				path = zalloc(sizeof(*path));
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
				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;
222 223 224 225 226 227
			}
		}
		closedir(evt_dir);
	}

	closedir(sys_dir);
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
	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;
247 248
}

249 250 251 252 253 254 255 256
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 */
}

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
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;
}

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
const char *event_type(int type)
{
	switch (type) {
	case PERF_TYPE_HARDWARE:
		return "hardware";

	case PERF_TYPE_SOFTWARE:
		return "software";

	case PERF_TYPE_TRACEPOINT:
		return "tracepoint";

	case PERF_TYPE_HW_CACHE:
		return "hardware-cache";

	default:
		break;
	}

	return "unknown";
}

295
const char *event_name(struct perf_evsel *evsel)
296
{
297 298
	u64 config = evsel->attr.config;
	int type = evsel->attr.type;
299

300 301 302
	if (evsel->name)
		return evsel->name;

303 304 305
	return __event_name(type, config);
}

306
const char *__event_name(int type, u64 config)
307
{
308 309
	static char buf[32];

310
	if (type == PERF_TYPE_RAW) {
311
		sprintf(buf, "raw 0x%" PRIx64, config);
312 313 314 315 316
		return buf;
	}

	switch (type) {
	case PERF_TYPE_HARDWARE:
317
		if (config < PERF_COUNT_HW_MAX && hw_event_names[config])
318
			return hw_event_names[config];
319 320
		return "unknown-hardware";

321
	case PERF_TYPE_HW_CACHE: {
322
		u8 cache_type, cache_op, cache_result;
323 324 325 326 327 328

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

		cache_op     = (config >>  8) & 0xff;
329 330
		if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
			return "unknown-ext-hardware-cache-op";
331 332

		cache_result = (config >> 16) & 0xff;
333 334
		if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
			return "unknown-ext-hardware-cache-result";
335

336 337
		if (!is_cache_op_valid(cache_type, cache_op))
			return "invalid-cache";
338

339
		return event_cache_name(cache_type, cache_op, cache_result);
340 341
	}

342
	case PERF_TYPE_SOFTWARE:
343
		if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
344
			return sw_event_names[config];
345 346
		return "unknown-software";

347 348 349
	case PERF_TYPE_TRACEPOINT:
		return tracepoint_id_to_name(config);

350 351 352 353 354 355 356
	default:
		break;
	}

	return "unknown";
}

357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
static int add_event(struct list_head *list, int *idx,
		     struct perf_event_attr *attr, char *name)
{
	struct perf_evsel *evsel;

	event_attr_init(attr);

	evsel = perf_evsel__new(attr, (*idx)++);
	if (!evsel)
		return -ENOMEM;

	list_add_tail(&evsel->node, list);

	evsel->name = strdup(name);
	return 0;
}

static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size)
375 376
{
	int i, j;
377
	int n, longest = -1;
378 379

	for (i = 0; i < size; i++) {
380 381
		for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
			n = strlen(names[i][j]);
382
			if (n > longest && !strncasecmp(str, names[i][j], n))
383 384
				longest = n;
		}
385
		if (longest > 0)
386
			return i;
387 388
	}

389
	return -1;
390 391
}

392 393
int parse_events_add_cache(struct list_head *list, int *idx,
			   char *type, char *op_result1, char *op_result2)
394
{
395 396
	struct perf_event_attr attr;
	char name[MAX_NAME_LEN];
397
	int cache_type = -1, cache_op = -1, cache_result = -1;
398 399
	char *op_result[2] = { op_result1, op_result2 };
	int i, n;
400 401 402 403 404

	/*
	 * No fallback - if we cannot get a clear cache type
	 * then bail out:
	 */
405 406
	cache_type = parse_aliases(type, hw_cache,
				   PERF_COUNT_HW_CACHE_MAX);
407
	if (cache_type == -1)
408 409 410
		return -EINVAL;

	n = snprintf(name, MAX_NAME_LEN, "%s", type);
411

412 413 414 415
	for (i = 0; (i < 2) && (op_result[i]); i++) {
		char *str = op_result[i];

		snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);
416 417

		if (cache_op == -1) {
418 419
			cache_op = parse_aliases(str, hw_cache_op,
						 PERF_COUNT_HW_CACHE_OP_MAX);
420 421
			if (cache_op >= 0) {
				if (!is_cache_op_valid(cache_type, cache_op))
422
					return -EINVAL;
423 424 425 426 427
				continue;
			}
		}

		if (cache_result == -1) {
428
			cache_result = parse_aliases(str, hw_cache_result,
429 430 431 432 433
						PERF_COUNT_HW_CACHE_RESULT_MAX);
			if (cache_result >= 0)
				continue;
		}
	}
434 435 436 437

	/*
	 * Fall back to reads:
	 */
438 439
	if (cache_op == -1)
		cache_op = PERF_COUNT_HW_CACHE_OP_READ;
440 441 442 443 444 445 446

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

447 448 449 450
	memset(&attr, 0, sizeof(attr));
	attr.config = cache_type | (cache_op << 8) | (cache_result << 16);
	attr.type = PERF_TYPE_HW_CACHE;
	return add_event(list, idx, &attr, name);
451 452
}

453 454
static int add_tracepoint(struct list_head *list, int *idx,
			  char *sys_name, char *evt_name)
455
{
456 457
	struct perf_event_attr attr;
	char name[MAX_NAME_LEN];
458 459 460 461 462
	char evt_path[MAXPATHLEN];
	char id_buf[4];
	u64 id;
	int fd;

463
	snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
464 465 466 467
		 sys_name, evt_name);

	fd = open(evt_path, O_RDONLY);
	if (fd < 0)
468
		return -1;
469 470 471

	if (read(fd, id_buf, sizeof(id_buf)) < 0) {
		close(fd);
472
		return -1;
473 474 475 476 477
	}

	close(fd);
	id = atoll(id_buf);

478 479 480 481 482 483 484
	memset(&attr, 0, sizeof(attr));
	attr.config = id;
	attr.type = PERF_TYPE_TRACEPOINT;
	attr.sample_type |= PERF_SAMPLE_RAW;
	attr.sample_type |= PERF_SAMPLE_TIME;
	attr.sample_type |= PERF_SAMPLE_CPU;
	attr.sample_period = 1;
485

486 487
	snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name);
	return add_event(list, idx, &attr, name);
488 489
}

490 491
static int add_tracepoint_multi(struct list_head *list, int *idx,
				char *sys_name, char *evt_name)
492 493 494 495
{
	char evt_path[MAXPATHLEN];
	struct dirent *evt_ent;
	DIR *evt_dir;
496
	int ret = 0;
497

498
	snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
499 500 501
	evt_dir = opendir(evt_path);
	if (!evt_dir) {
		perror("Can't open event dir");
502
		return -1;
503 504
	}

505
	while (!ret && (evt_ent = readdir(evt_dir))) {
506 507 508 509 510 511
		if (!strcmp(evt_ent->d_name, ".")
		    || !strcmp(evt_ent->d_name, "..")
		    || !strcmp(evt_ent->d_name, "enable")
		    || !strcmp(evt_ent->d_name, "filter"))
			continue;

512
		if (!strglobmatch(evt_ent->d_name, evt_name))
513 514
			continue;

515
		ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name);
516 517
	}

518
	return ret;
519 520
}

521 522
int parse_events_add_tracepoint(struct list_head *list, int *idx,
				char *sys, char *event)
523
{
524
	int ret;
525

526 527 528
	ret = debugfs_valid_mountpoint(tracing_events_path);
	if (ret)
		return ret;
529

530 531 532
	return strpbrk(event, "*?") ?
	       add_tracepoint_multi(list, idx, sys, event) :
	       add_tracepoint(list, idx, sys, event);
533 534
}

535 536
static int
parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
537 538 539 540
{
	int i;

	for (i = 0; i < 3; i++) {
541
		if (!type || !type[i])
542 543 544 545 546 547 548 549 550 551 552 553 554
			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:
555
			return -EINVAL;
556 557
		}
	}
558

559 560 561
	if (!attr->bp_type) /* Default */
		attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;

562
	return 0;
563 564
}

565 566
int parse_events_add_breakpoint(struct list_head *list, int *idx,
				void *ptr, char *type)
567
{
568 569
	struct perf_event_attr attr;
	char name[MAX_NAME_LEN];
570

571 572
	memset(&attr, 0, sizeof(attr));
	attr.bp_addr = (u64) ptr;
573

574 575
	if (parse_breakpoint_type(type, &attr))
		return -EINVAL;
576

577 578 579 580
	/*
	 * We should find a nice way to override the access length
	 * Provide some defaults for now
	 */
581 582
	if (attr.bp_type == HW_BREAKPOINT_X)
		attr.bp_len = sizeof(long);
583
	else
584
		attr.bp_len = HW_BREAKPOINT_LEN_4;
585

586
	attr.type = PERF_TYPE_BREAKPOINT;
587

588 589
	snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw");
	return add_event(list, idx, &attr, name);
590 591
}

592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
static int config_term(struct perf_event_attr *attr,
		       struct parse_events__term *term)
{
	switch (term->type) {
	case PARSE_EVENTS__TERM_TYPE_CONFIG:
		attr->config = term->val.num;
		break;
	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
		attr->config1 = term->val.num;
		break;
	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
		attr->config2 = term->val.num;
		break;
	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
		attr->sample_period = term->val.num;
		break;
	case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
		/*
		 * TODO uncomment when the field is available
		 * attr->branch_sample_type = term->val.num;
		 */
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

static int config_attr(struct perf_event_attr *attr,
		       struct list_head *head, int fail)
{
	struct parse_events__term *term;

	list_for_each_entry(term, head, list)
		if (config_term(attr, term) && fail)
			return -EINVAL;

	return 0;
}

int parse_events_add_numeric(struct list_head *list, int *idx,
			     unsigned long type, unsigned long config,
			     struct list_head *head_config)
635
{
636
	struct perf_event_attr attr;
637

638 639 640
	memset(&attr, 0, sizeof(attr));
	attr.type = type;
	attr.config = config;
641 642 643 644 645

	if (head_config &&
	    config_attr(&attr, head_config, 1))
		return -EINVAL;

646 647
	return add_event(list, idx, &attr,
			 (char *) __event_name(type, config));
648
}
649

650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
int parse_events_add_pmu(struct list_head *list, int *idx,
			 char *name, struct list_head *head_config)
{
	struct perf_event_attr attr;
	struct perf_pmu *pmu;

	pmu = perf_pmu__find(name);
	if (!pmu)
		return -EINVAL;

	memset(&attr, 0, sizeof(attr));

	/*
	 * Configure hardcoded terms first, no need to check
	 * return value when called with fail == 0 ;)
	 */
	config_attr(&attr, head_config, 0);

	if (perf_pmu__config(pmu, &attr, head_config))
		return -EINVAL;

	return add_event(list, idx, &attr, (char *) "pmu");
}

674
int parse_events_modifier(struct list_head *list, char *str)
675
{
676
	struct perf_evsel *evsel;
677 678
	int exclude = 0, exclude_GH = 0;
	int eu = 0, ek = 0, eh = 0, eH = 0, eG = 0, precise = 0;
679

680
	if (str == NULL)
681
		return 0;
682

683
	while (*str) {
P
Peter Zijlstra 已提交
684 685 686
		if (*str == 'u') {
			if (!exclude)
				exclude = eu = ek = eh = 1;
687
			eu = 0;
P
Peter Zijlstra 已提交
688 689 690
		} else if (*str == 'k') {
			if (!exclude)
				exclude = eu = ek = eh = 1;
691
			ek = 0;
P
Peter Zijlstra 已提交
692 693 694
		} else if (*str == 'h') {
			if (!exclude)
				exclude = eu = ek = eh = 1;
695
			eh = 0;
696 697 698 699 700 701 702 703
		} else if (*str == 'G') {
			if (!exclude_GH)
				exclude_GH = eG = eH = 1;
			eG = 0;
		} else if (*str == 'H') {
			if (!exclude_GH)
				exclude_GH = eG = eH = 1;
			eH = 0;
P
Peter Zijlstra 已提交
704 705 706
		} else if (*str == 'p') {
			precise++;
		} else
707
			break;
P
Peter Zijlstra 已提交
708

709
		++str;
710
	}
711

712 713 714 715 716 717 718 719 720 721 722 723
	/*
	 * precise ip:
	 *
	 *  0 - SAMPLE_IP can have arbitrary skid
	 *  1 - SAMPLE_IP must have constant skid
	 *  2 - SAMPLE_IP requested to have 0 skid
	 *  3 - SAMPLE_IP must have 0 skid
	 *
	 *  See also PERF_RECORD_MISC_EXACT_IP
	 */
	if (precise > 3)
		return -EINVAL;
724

725 726 727 728 729 730 731 732
	list_for_each_entry(evsel, list, node) {
		evsel->attr.exclude_user   = eu;
		evsel->attr.exclude_kernel = ek;
		evsel->attr.exclude_hv     = eh;
		evsel->attr.precise_ip     = precise;
		evsel->attr.exclude_host   = eH;
		evsel->attr.exclude_guest  = eG;
	}
733

734 735
	return 0;
}
736

737
int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
738
{
739 740 741 742
	struct perf_evsel *evsel, *h;
	LIST_HEAD(list);
	YY_BUFFER_STATE buffer;
	int ret, idx = evlist->nr_entries;
743

744
	buffer = parse_events__scan_string(str);
745

746
	ret = parse_events_parse(&list, &idx);
747

748 749
	parse_events__flush_buffer(buffer);
	parse_events__delete_buffer(buffer);
750

751 752 753 754 755
	if (!ret) {
		int entries = idx - evlist->nr_entries;
		perf_evlist__splice_list_tail(evlist, &list, entries);
		return 0;
	}
756

757 758
	list_for_each_entry_safe(evsel, h, &list, node)
		perf_evsel__delete(evsel);
759

760
	fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
761
	fprintf(stderr, "Run 'perf list' for a list of valid events\n");
762
	return ret;
763 764
}

765 766 767 768 769 770 771
int parse_events_option(const struct option *opt, const char *str,
			int unset __used)
{
	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
	return parse_events(evlist, str, unset);
}

772
int parse_filter(const struct option *opt, const char *str,
L
Li Zefan 已提交
773 774
		 int unset __used)
{
775
	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
776
	struct perf_evsel *last = NULL;
L
Li Zefan 已提交
777

778 779
	if (evlist->nr_entries > 0)
		last = list_entry(evlist->entries.prev, struct perf_evsel, node);
780 781

	if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
L
Li Zefan 已提交
782 783 784 785 786
		fprintf(stderr,
			"-F option should follow a -e tracepoint option\n");
		return -1;
	}

787 788
	last->filter = strdup(str);
	if (last->filter == NULL) {
L
Li Zefan 已提交
789 790 791 792 793 794 795
		fprintf(stderr, "not enough memory to hold filter string\n");
		return -1;
	}

	return 0;
}

796 797 798 799 800
static const char * const event_type_descriptors[] = {
	"Hardware event",
	"Software event",
	"Tracepoint event",
	"Hardware cache event",
801 802
	"Raw hardware event descriptor",
	"Hardware breakpoint",
803 804
};

805 806 807 808
/*
 * Print the events from <debugfs_mount_point>/tracing/events
 */

809
void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
810 811 812 813
{
	DIR *sys_dir, *evt_dir;
	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
	char evt_path[MAXPATHLEN];
E
Eric Dumazet 已提交
814
	char dir_path[MAXPATHLEN];
815

816
	if (debugfs_valid_mountpoint(tracing_events_path))
817 818
		return;

819
	sys_dir = opendir(tracing_events_path);
820
	if (!sys_dir)
E
Eric Dumazet 已提交
821
		return;
822 823

	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
824 825 826
		if (subsys_glob != NULL && 
		    !strglobmatch(sys_dirent.d_name, subsys_glob))
			continue;
E
Eric Dumazet 已提交
827

828
		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
E
Eric Dumazet 已提交
829 830 831
			 sys_dirent.d_name);
		evt_dir = opendir(dir_path);
		if (!evt_dir)
832
			continue;
E
Eric Dumazet 已提交
833

834
		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
835 836 837 838
			if (event_glob != NULL && 
			    !strglobmatch(evt_dirent.d_name, event_glob))
				continue;

839 840
			snprintf(evt_path, MAXPATHLEN, "%s:%s",
				 sys_dirent.d_name, evt_dirent.d_name);
841
			printf("  %-50s [%s]\n", evt_path,
842
				event_type_descriptors[PERF_TYPE_TRACEPOINT]);
843 844 845 846 847 848
		}
		closedir(evt_dir);
	}
	closedir(sys_dir);
}

849 850 851 852 853 854 855 856 857 858 859
/*
 * 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];

860
	if (debugfs_valid_mountpoint(tracing_events_path))
861 862
		return 0;

863
	sys_dir = opendir(tracing_events_path);
864 865 866 867 868
	if (!sys_dir)
		return 0;

	for_each_subsystem(sys_dir, sys_dirent, sys_next) {

869
		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
			 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;
}

890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
void print_events_type(u8 type)
{
	struct event_symbol *syms = event_symbols;
	unsigned int i;
	char name[64];

	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
		if (type != syms->type)
			continue;

		if (strlen(syms->alias))
			snprintf(name, sizeof(name),  "%s OR %s",
				 syms->symbol, syms->alias);
		else
			snprintf(name, sizeof(name), "%s", syms->symbol);

906
		printf("  %-50s [%s]\n", name,
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
			event_type_descriptors[type]);
	}
}

int print_hwcache_events(const char *event_glob)
{
	unsigned int type, op, i, printed = 0;

	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++) {
				char *name = event_cache_name(type, op, i);

924
				if (event_glob != NULL && !strglobmatch(name, event_glob))
925 926
					continue;

927
				printf("  %-50s [%s]\n", name,
928 929 930 931 932 933 934 935 936
					event_type_descriptors[PERF_TYPE_HW_CACHE]);
				++printed;
			}
		}
	}

	return printed;
}

937
/*
938
 * Print the help text for the event symbols:
939
 */
940
void print_events(const char *event_glob)
941
{
942
	unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
943 944
	struct event_symbol *syms = event_symbols;
	char name[MAX_NAME_LEN];
945

946 947
	printf("\n");
	printf("List of pre-defined events (to be used in -e):\n");
948

949
	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
950
		type = syms->type;
951

952
		if (type != prev_type && printed) {
953
			printf("\n");
954 955 956 957 958 959 960 961
			printed = 0;
			ntypes_printed++;
		}

		if (event_glob != NULL && 
		    !(strglobmatch(syms->symbol, event_glob) ||
		      (syms->alias && strglobmatch(syms->alias, event_glob))))
			continue;
962

963
		if (strlen(syms->alias))
964
			snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
965
		else
966 967
			strncpy(name, syms->symbol, MAX_NAME_LEN);
		printf("  %-50s [%s]\n", name,
968
			event_type_descriptors[type]);
969

970
		prev_type = type;
971
		++printed;
972 973
	}

974 975 976
	if (ntypes_printed) {
		printed = 0;
		printf("\n");
977
	}
978 979 980 981
	print_hwcache_events(event_glob);

	if (event_glob != NULL)
		return;
982

983
	printf("\n");
984
	printf("  %-50s [%s]\n",
985 986 987 988
	       "rNNN",
	       event_type_descriptors[PERF_TYPE_RAW]);
	printf("  %-50s [%s]\n",
	       "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
989
	       event_type_descriptors[PERF_TYPE_RAW]);
990
	printf("   (see 'perf list --help' on how to encode it)\n");
991
	printf("\n");
992

993
	printf("  %-50s [%s]\n",
994 995
			"mem:<addr>[:access]",
			event_type_descriptors[PERF_TYPE_BREAKPOINT]);
996 997
	printf("\n");

998
	print_tracepoint_events(NULL, NULL);
999
}
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047

int parse_events__is_hardcoded_term(struct parse_events__term *term)
{
	return term->type <= PARSE_EVENTS__TERM_TYPE_HARDCODED_MAX;
}

int parse_events__new_term(struct parse_events__term **_term, int type,
			   char *config, char *str, long num)
{
	struct parse_events__term *term;

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

	INIT_LIST_HEAD(&term->list);
	term->type = type;
	term->config = config;

	switch (type) {
	case PARSE_EVENTS__TERM_TYPE_CONFIG:
	case PARSE_EVENTS__TERM_TYPE_CONFIG1:
	case PARSE_EVENTS__TERM_TYPE_CONFIG2:
	case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
	case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE:
	case PARSE_EVENTS__TERM_TYPE_NUM:
		term->val.num = num;
		break;
	case PARSE_EVENTS__TERM_TYPE_STR:
		term->val.str = str;
		break;
	default:
		return -EINVAL;
	}

	*_term = term;
	return 0;
}

void parse_events__free_terms(struct list_head *terms)
{
	struct parse_events__term *term, *h;

	list_for_each_entry_safe(term, h, terms, list)
		free(term);

	free(terms);
}