• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file op_events.c
3  * Details of PMC profiling events
4  *
5  * You can have silliness here.
6  *
7  * @remark Copyright 2002 OProfile authors
8  * @remark Read the file COPYING
9  *
10  * @author John Levon
11  * @author Philippe Elie
12  */
13 
14 #include "op_events.h"
15 #include "op_libiberty.h"
16 #include "op_fileio.h"
17 #include "op_string.h"
18 #include "op_cpufreq.h"
19 #include "op_hw_specific.h"
20 
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 
25 static LIST_HEAD(events_list);
26 static LIST_HEAD(um_list);
27 
28 static char const * filename;
29 static unsigned int line_nr;
30 
31 static void delete_event(struct op_event * event);
32 static void read_events(char const * file);
33 static void read_unit_masks(char const * file);
34 static void free_unit_mask(struct op_unit_mask * um);
35 
build_fn(const char * cpu_name,const char * fn)36 static char *build_fn(const char *cpu_name, const char *fn)
37 {
38 	char *s;
39 	static const char *dir;
40 	if (dir == NULL)
41 		dir = getenv("OPROFILE_EVENTS_DIR");
42 	if (dir == NULL)
43 		dir = OP_DATADIR;
44 	s = xmalloc(strlen(dir) + strlen(cpu_name) + strlen(fn) + 5);
45 	sprintf(s, "%s/%s/%s", dir, cpu_name, fn);
46 	return s;
47 }
48 
parse_error(char const * context)49 static void parse_error(char const * context)
50 {
51 	fprintf(stderr, "oprofile: parse error in %s, line %u\n",
52 		filename, line_nr);
53 	fprintf(stderr, "%s\n", context);
54 	exit(EXIT_FAILURE);
55 }
56 
57 
parse_int(char const * str)58 static int parse_int(char const * str)
59 {
60 	int value;
61 	if (sscanf(str, "%d", &value) != 1)
62 		parse_error("expected decimal value");
63 
64 	return value;
65 }
66 
67 
parse_hex(char const * str)68 static int parse_hex(char const * str)
69 {
70 	int value;
71 	/* 0x/0X to force the use of hexa notation for field intended to
72 	   be in hexadecimal */
73 	if (sscanf(str, "0x%x", &value) != 1 &&
74 	    sscanf(str, "0X%x", &value) != 1)
75 		parse_error("expected hexadecimal value");
76 
77 	return value;
78 }
79 
80 
parse_long_hex(char const * str)81 static u64 parse_long_hex(char const * str)
82 {
83 	u64 value;
84 	if (sscanf(str, "%Lx", &value) != 1)
85 		parse_error("expected long hexadecimal value");
86 
87 	fflush(stderr);
88 	return value;
89 }
90 
include_um(const char * start,const char * end)91 static void include_um(const char *start, const char *end)
92 {
93 	char *s;
94 	char cpu[end - start + 1];
95 	int old_line_nr;
96 	const char *old_filename;
97 
98 	strncpy(cpu, start, end - start);
99 	cpu[end - start] = 0;
100 	s = build_fn(cpu, "unit_masks");
101 	old_line_nr = line_nr;
102 	old_filename = filename;
103 	read_unit_masks(s);
104 	line_nr = old_line_nr;
105 	filename = old_filename;
106 	free(s);
107 }
108 
109 /* name:MESI type:bitmask default:0x0f */
parse_um(struct op_unit_mask * um,char const * line)110 static void parse_um(struct op_unit_mask * um, char const * line)
111 {
112 	int seen_name = 0;
113 	int seen_type = 0;
114        	int seen_default = 0;
115 	char const * valueend = line + 1;
116        	char const * tagend = line + 1;
117 	char const * start = line;
118 
119 	while (*valueend) {
120 		valueend = skip_nonws(valueend);
121 
122 		while (*tagend != ':' && *tagend)
123 			++tagend;
124 
125 		if (valueend == tagend)
126 			break;
127 
128 		if (!*tagend)
129 			parse_error("parse_um() expected :value");
130 
131 		++tagend;
132 
133 		if (strisprefix(start, "include")) {
134 			if (seen_name + seen_type + seen_default > 0)
135 				parse_error("include must be on its own");
136 			free_unit_mask(um);
137 			include_um(tagend, valueend);
138 			return;
139 		}
140 
141 		if (strisprefix(start, "name")) {
142 			if (seen_name)
143 				parse_error("duplicate name: tag");
144 			seen_name = 1;
145 			um->name = op_xstrndup(tagend, valueend - tagend);
146 		} else if (strisprefix(start, "type")) {
147 			if (seen_type)
148 				parse_error("duplicate type: tag");
149 			seen_type = 1;
150 			if (strisprefix(tagend, "mandatory")) {
151 				um->unit_type_mask = utm_mandatory;
152 			} else if (strisprefix(tagend, "bitmask")) {
153 				um->unit_type_mask = utm_bitmask;
154 			} else if (strisprefix(tagend, "exclusive")) {
155 				um->unit_type_mask = utm_exclusive;
156 			} else {
157 				parse_error("invalid unit mask type");
158 			}
159 		} else if (strisprefix(start, "default")) {
160 			if (seen_default)
161 				parse_error("duplicate default: tag");
162 			seen_default = 1;
163 			um->default_mask = parse_hex(tagend);
164 		} else {
165 			parse_error("invalid unit mask tag");
166 		}
167 
168 		valueend = skip_ws(valueend);
169 		tagend = valueend;
170 		start = valueend;
171 	}
172 
173 	if (!um->name)
174 		parse_error("Missing name for unit mask");
175 	if (!seen_type)
176 		parse_error("Missing type for unit mask");
177 }
178 
179 
180 /* \t0x08 (M)odified cache state */
parse_um_entry(struct op_described_um * entry,char const * line)181 static void parse_um_entry(struct op_described_um * entry, char const * line)
182 {
183 	char const * c = line;
184 
185 	c = skip_ws(c);
186 	entry->value = parse_hex(c);
187 	c = skip_nonws(c);
188 
189 	if (!*c)
190 		parse_error("invalid unit mask entry");
191 
192 	c = skip_ws(c);
193 
194 	if (!*c)
195 		parse_error("invalid unit mask entry");
196 
197 	entry->desc = xstrdup(c);
198 }
199 
200 
new_unit_mask(void)201 static struct op_unit_mask * new_unit_mask(void)
202 {
203 	struct op_unit_mask * um = xmalloc(sizeof(struct op_unit_mask));
204 	memset(um, '\0', sizeof(struct op_unit_mask));
205 	list_add_tail(&um->um_next, &um_list);
206 
207 	return um;
208 }
209 
free_unit_mask(struct op_unit_mask * um)210 static void free_unit_mask(struct op_unit_mask * um)
211 {
212 	list_del(&um->um_next);
213 	free(um);
214 }
215 
216 /*
217  * name:zero type:mandatory default:0x0
218  * \t0x0 No unit mask
219  */
read_unit_masks(char const * file)220 static void read_unit_masks(char const * file)
221 {
222 	struct op_unit_mask * um = NULL;
223 	char * line;
224 	FILE * fp = fopen(file, "r");
225 
226 	if (!fp) {
227 		fprintf(stderr,
228 			"oprofile: could not open unit mask description file %s\n", file);
229 		exit(EXIT_FAILURE);
230 	}
231 
232 	filename = file;
233 	line_nr = 1;
234 
235 	line = op_get_line(fp);
236 
237 	while (line) {
238 		if (empty_line(line) || comment_line(line))
239 			goto next;
240 
241 		if (line[0] != '\t') {
242 			um = new_unit_mask();
243 			parse_um(um, line);
244 		} else {
245 			if (!um)
246 				parse_error("no unit mask name line");
247 			if (um->num >= MAX_UNIT_MASK)
248 				parse_error("oprofile: maximum unit mask entries exceeded");
249 
250 			parse_um_entry(&um->um[um->num], line);
251 			++(um->num);
252 		}
253 
254 next:
255 		free(line);
256 		line = op_get_line(fp);
257 		++line_nr;
258 	}
259 
260 	fclose(fp);
261 }
262 
263 
parse_counter_mask(char const * str)264 static u32 parse_counter_mask(char const * str)
265 {
266 	u32 mask = 0;
267 	char const * numstart = str;
268 
269 	while (*numstart) {
270 		mask |= 1 << parse_int(numstart);
271 
272 		while (*numstart && *numstart != ',')
273 			++numstart;
274 		/* skip , unless we reach eos */
275 		if (*numstart)
276 			++numstart;
277 
278 		numstart = skip_ws(numstart);
279 	}
280 
281 	return mask;
282 }
283 
try_find_um(char const * value)284 static struct op_unit_mask * try_find_um(char const * value)
285 {
286 	struct list_head * pos;
287 
288 	list_for_each(pos, &um_list) {
289 		struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next);
290 		if (strcmp(value, um->name) == 0) {
291 			um->used = 1;
292 			return um;
293 		}
294 	}
295 	return NULL;
296 }
297 
find_um(char const * value)298 static struct op_unit_mask * find_um(char const * value)
299 {
300 	struct op_unit_mask * um = try_find_um(value);
301 	if (um)
302 		return um;
303 	fprintf(stderr, "oprofile: could not find unit mask %s\n", value);
304 	exit(EXIT_FAILURE);
305 }
306 
307 /* um:a,b,c,d merge multiple unit masks */
merge_um(char * value)308 static struct op_unit_mask * merge_um(char * value)
309 {
310 	int num;
311 	char *s;
312 	struct op_unit_mask *new, *um;
313 	enum unit_mask_type type = -1U;
314 
315 	um = try_find_um(value);
316 	if (um)
317 		return um;
318 
319 	new = new_unit_mask();
320 	new->name = xstrdup(value);
321 	new->used = 1;
322 	num = 0;
323 	while ((s = strsep(&value, ",")) != NULL) {
324 		unsigned c;
325 		um = find_um(s);
326 		if (type == -1U)
327 			type = um->unit_type_mask;
328 		if (um->unit_type_mask != type)
329 			parse_error("combined unit mask must be all the same types");
330 		if (type != utm_bitmask && type != utm_exclusive)
331 			parse_error("combined unit mask must be all bitmasks or exclusive");
332 		new->default_mask |= um->default_mask;
333 		new->num += um->num;
334 		if (new->num > MAX_UNIT_MASK)
335 			parse_error("too many members in combined unit mask");
336 		for (c = 0; c < um->num; c++, num++) {
337 			new->um[num] = um->um[c];
338 			new->um[num].desc = xstrdup(new->um[num].desc);
339 		}
340 	}
341 	if (type == -1U)
342 		parse_error("Empty unit mask");
343 	new->unit_type_mask = type;
344 	return new;
345 }
346 
347 /* parse either a "tag:value" or a ": trailing description string" */
next_token(char const ** cp,char ** name,char ** value)348 static int next_token(char const ** cp, char ** name, char ** value)
349 {
350 	size_t tag_len;
351 	size_t val_len;
352 	char const * c = *cp;
353 	char const * end;
354 	char const * colon;
355 
356 	c = skip_ws(c);
357 	end = colon = c;
358 	end = skip_nonws(end);
359 
360 	colon = strchr(colon, ':');
361 
362 	if (!colon) {
363 		if (*c)
364 			parse_error("next_token(): garbage at end of line");
365 		return 0;
366 	}
367 
368 	if (colon >= end)
369 		parse_error("next_token() expected ':'");
370 
371 	tag_len = colon - c;
372 	val_len = end - (colon + 1);
373 
374 	if (!tag_len) {
375 		/* : trailing description */
376 		end = skip_ws(end);
377 		*name = xstrdup("desc");
378 		*value = xstrdup(end);
379 		end += strlen(end);
380 	} else {
381 		/* tag:value */
382 		*name = op_xstrndup(c, tag_len);
383 		*value = op_xstrndup(colon + 1, val_len);
384 		end = skip_ws(end);
385 	}
386 
387 	*cp = end;
388 	return 1;
389 }
390 
include_events(char * value)391 static void include_events (char *value)
392 {
393 	char * event_file;
394 	const char *old_filename;
395 	int old_line_nr;
396 
397 	event_file = build_fn(value, "events");
398 	old_line_nr = line_nr;
399 	old_filename = filename;
400 	read_events(event_file);
401 	line_nr = old_line_nr;
402 	filename = old_filename;
403 	free(event_file);
404 }
405 
new_event(void)406 static struct op_event * new_event(void)
407 {
408 	struct op_event * event = xmalloc(sizeof(struct op_event));
409 	memset(event, '\0', sizeof(struct op_event));
410 	list_add_tail(&event->event_next, &events_list);
411 
412 	return event;
413 }
414 
free_event(struct op_event * event)415 static void free_event(struct op_event * event)
416 {
417 	list_del(&event->event_next);
418 	free(event);
419 }
420 
421 /* event:0x00 counters:0 um:zero minimum:4096 name:ISSUES : Total issues */
422 /* event:0x00 ext:xxxxxx um:zero minimum:4096 name:ISSUES : Total issues */
read_events(char const * file)423 static void read_events(char const * file)
424 {
425 	struct op_event * event = NULL;
426 	char * line;
427 	char * name;
428 	char * value;
429 	char const * c;
430 	int seen_event, seen_counters, seen_um, seen_minimum, seen_name, seen_ext;
431 	FILE * fp = fopen(file, "r");
432 	int tags;
433 
434 	if (!fp) {
435 		fprintf(stderr, "oprofile: could not open event description file %s\n", file);
436 		exit(EXIT_FAILURE);
437 	}
438 
439 	filename = file;
440 	line_nr = 1;
441 
442 	line = op_get_line(fp);
443 
444 	while (line) {
445 		if (empty_line(line) || comment_line(line))
446 			goto next;
447 
448 		tags = 0;
449 		seen_name = 0;
450 		seen_event = 0;
451 		seen_counters = 0;
452 		seen_ext = 0;
453 		seen_um = 0;
454 		seen_minimum = 0;
455 		event = new_event();
456 		event->filter = -1;
457 		event->ext = NULL;
458 
459 		c = line;
460 		while (next_token(&c, &name, &value)) {
461 			if (strcmp(name, "name") == 0) {
462 				if (seen_name)
463 					parse_error("duplicate name: tag");
464 				seen_name = 1;
465 				if (strchr(value, '/') != NULL)
466 					parse_error("invalid event name");
467 				if (strchr(value, '.') != NULL)
468 					parse_error("invalid event name");
469 				event->name = value;
470 			} else if (strcmp(name, "event") == 0) {
471 				if (seen_event)
472 					parse_error("duplicate event: tag");
473 				seen_event = 1;
474 				event->val = parse_hex(value);
475 				free(value);
476 			} else if (strcmp(name, "counters") == 0) {
477 				if (seen_counters)
478 					parse_error("duplicate counters: tag");
479 				seen_counters = 1;
480 				if (!strcmp(value, "cpuid"))
481 					event->counter_mask = arch_get_counter_mask();
482 				else
483 					event->counter_mask = parse_counter_mask(value);
484 				free(value);
485 			} else if (strcmp(name, "ext") == 0) {
486 				if (seen_ext)
487 					parse_error("duplicate ext: tag");
488 				seen_ext = 1;
489 				event->ext = value;
490 			} else if (strcmp(name, "um") == 0) {
491 				if (seen_um)
492 					parse_error("duplicate um: tag");
493 				seen_um = 1;
494 				if (strchr(value, ','))
495 					event->unit = merge_um(value);
496 				else
497 					event->unit = find_um(value);
498 				free(value);
499 			} else if (strcmp(name, "minimum") == 0) {
500 				if (seen_minimum)
501 					parse_error("duplicate minimum: tag");
502 				seen_minimum = 1;
503 				event->min_count = parse_int(value);
504 				free(value);
505 			} else if (strcmp(name, "desc") == 0) {
506 				event->desc = value;
507 			} else if (strcmp(name, "filter") == 0) {
508 				event->filter = parse_int(value);
509 				free(value);
510 			} else if (strcmp(name, "include") == 0) {
511 				if (tags > 0)
512 					parse_error("tags before include:");
513 				free_event(event);
514 				include_events(value);
515 				free(value);
516 				c = skip_ws(c);
517 				if (*c != '\0' && *c != '#')
518 					parse_error("non whitespace after include:");
519 			} else {
520 				parse_error("unknown tag");
521 			}
522 			tags++;
523 
524 			free(name);
525 		}
526 next:
527 		free(line);
528 		line = op_get_line(fp);
529 		++line_nr;
530 	}
531 
532 	fclose(fp);
533 }
534 
535 
536 /* usefull for make check */
check_unit_mask(struct op_unit_mask const * um,char const * cpu_name)537 static int check_unit_mask(struct op_unit_mask const * um,
538 	char const * cpu_name)
539 {
540 	u32 i;
541 	int err = 0;
542 
543 	if (!um->used) {
544 		fprintf(stderr, "um %s is not used\n", um->name);
545 		err = EXIT_FAILURE;
546 	}
547 
548 	if (um->unit_type_mask == utm_mandatory && um->num != 1) {
549 		fprintf(stderr, "mandatory um %s doesn't contain exactly one "
550 			"entry (%s)\n", um->name, cpu_name);
551 		err = EXIT_FAILURE;
552 	} else if (um->unit_type_mask == utm_bitmask) {
553 		u32 default_mask = um->default_mask;
554 		for (i = 0; i < um->num; ++i)
555 			default_mask &= ~um->um[i].value;
556 
557 		if (default_mask) {
558 			fprintf(stderr, "um %s default mask is not valid "
559 				"(%s)\n", um->name, cpu_name);
560 			err = EXIT_FAILURE;
561 		}
562 	} else {
563 		for (i = 0; i < um->num; ++i) {
564 			if (um->default_mask == um->um[i].value)
565 				break;
566 		}
567 
568 		if (i == um->num) {
569 			fprintf(stderr, "exclusive um %s default value is not "
570 				"valid (%s)\n", um->name, cpu_name);
571 			err = EXIT_FAILURE;
572 		}
573 	}
574 	return err;
575 }
576 
arch_filter_events(op_cpu cpu_type)577 static void arch_filter_events(op_cpu cpu_type)
578 {
579 	struct list_head * pos, * pos2;
580 	unsigned filter = arch_get_filter(cpu_type);
581 	if (!filter)
582 		return;
583 	list_for_each_safe (pos, pos2, &events_list) {
584 		struct op_event * event = list_entry(pos, struct op_event, event_next);
585 		if (event->filter >= 0 && ((1U << event->filter) & filter))
586 			delete_event(event);
587 	}
588 }
589 
load_events_name(const char * cpu_name)590 static void load_events_name(const char *cpu_name)
591 {
592 	char * event_file;
593 	char * um_file;
594 
595 	event_file = build_fn(cpu_name, "events");
596 	um_file = build_fn(cpu_name, "unit_masks");
597 
598 	read_unit_masks(um_file);
599 	read_events(event_file);
600 
601 	free(um_file);
602 	free(event_file);
603 }
604 
load_events(op_cpu cpu_type)605 static void load_events(op_cpu cpu_type)
606 {
607 	const char * cpu_name = op_get_cpu_name(cpu_type);
608 	struct list_head * pos;
609 	int err = 0;
610 
611 	if (!list_empty(&events_list))
612 		return;
613 
614 	load_events_name(cpu_name);
615 
616 	arch_filter_events(cpu_type);
617 
618 	/* sanity check: all unit mask must be used */
619 	list_for_each(pos, &um_list) {
620 		struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next);
621 		err |= check_unit_mask(um, cpu_name);
622 	}
623 	if (err)
624 		exit(err);
625 }
626 
op_events(op_cpu cpu_type)627 struct list_head * op_events(op_cpu cpu_type)
628 {
629 	load_events(cpu_type);
630 	arch_filter_events(cpu_type);
631 	return &events_list;
632 }
633 
634 
delete_unit_mask(struct op_unit_mask * unit)635 static void delete_unit_mask(struct op_unit_mask * unit)
636 {
637 	u32 cur;
638 	for (cur = 0 ; cur < unit->num ; ++cur) {
639 		if (unit->um[cur].desc)
640 			free(unit->um[cur].desc);
641 	}
642 
643 	if (unit->name)
644 		free(unit->name);
645 
646 	list_del(&unit->um_next);
647 	free(unit);
648 }
649 
650 
delete_event(struct op_event * event)651 static void delete_event(struct op_event * event)
652 {
653 	if (event->name)
654 		free(event->name);
655 	if (event->desc)
656 		free(event->desc);
657 
658 	list_del(&event->event_next);
659 	free(event);
660 }
661 
662 
op_free_events(void)663 void op_free_events(void)
664 {
665 	struct list_head * pos, * pos2;
666 	list_for_each_safe(pos, pos2, &events_list) {
667 		struct op_event * event = list_entry(pos, struct op_event, event_next);
668 		delete_event(event);
669 	}
670 
671 	list_for_each_safe(pos, pos2, &um_list) {
672 		struct op_unit_mask * unit = list_entry(pos, struct op_unit_mask, um_next);
673 		delete_unit_mask(unit);
674 	}
675 }
676 
677 /* There can be actually multiple events here, so this is not quite correct */
find_event_any(u32 nr)678 static struct op_event * find_event_any(u32 nr)
679 {
680 	struct list_head * pos;
681 
682 	list_for_each(pos, &events_list) {
683 		struct op_event * event = list_entry(pos, struct op_event, event_next);
684 		if (event->val == nr)
685 			return event;
686 	}
687 
688 	return NULL;
689 }
690 
find_event_um(u32 nr,u32 um)691 static struct op_event * find_event_um(u32 nr, u32 um)
692 {
693 	struct list_head * pos;
694 	unsigned int i;
695 
696 	list_for_each(pos, &events_list) {
697 		struct op_event * event = list_entry(pos, struct op_event, event_next);
698 		if (event->val == nr) {
699 			for (i = 0; i < event->unit->num; i++) {
700 				if (event->unit->um[i].value == um)
701 					return event;
702 			}
703 		}
704 	}
705 
706 	return NULL;
707 }
708 
open_event_mapping_file(char const * cpu_name)709 static FILE * open_event_mapping_file(char const * cpu_name)
710 {
711 	char * ev_map_file;
712 	char * dir;
713 	dir = getenv("OPROFILE_EVENTS_DIR");
714 	if (dir == NULL)
715 		dir = OP_DATADIR;
716 
717 	ev_map_file = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) +
718 	                    strlen("/") + + strlen("event_mappings") + 1);
719 	strcpy(ev_map_file, dir);
720 	strcat(ev_map_file, "/");
721 
722 	strcat(ev_map_file, cpu_name);
723 	strcat(ev_map_file, "/");
724 	strcat(ev_map_file, "event_mappings");
725 	filename = ev_map_file;
726 	return (fopen(ev_map_file, "r"));
727 }
728 
729 
730 /**
731  *  This function is PPC64-specific.
732  */
get_mapping(u32 nr,FILE * fp)733 static char const * get_mapping(u32 nr, FILE * fp)
734 {
735 	char * line;
736 	char * name;
737 	char * value;
738 	char const * c;
739 	char * map = NULL;
740 	int seen_event = 0, seen_mmcr0 = 0, seen_mmcr1 = 0, seen_mmcra = 0;
741 	u32 mmcr0 = 0;
742 	u64 mmcr1 = 0;
743 	u32 mmcra = 0;
744 	int event_found = 0;
745 
746 	line_nr = 1;
747 	line = op_get_line(fp);
748 	while (line && !event_found) {
749 		if (empty_line(line) || comment_line(line))
750 			goto next;
751 
752 		seen_event = 0;
753 		seen_mmcr0 = 0;
754 		seen_mmcr1 = 0;
755 		seen_mmcra = 0;
756 		mmcr0 = 0;
757 		mmcr1 = 0;
758 		mmcra = 0;
759 
760 		c = line;
761 		while (next_token(&c, &name, &value)) {
762 			if (strcmp(name, "event") == 0) {
763 				u32 evt;
764 				if (seen_event)
765 					parse_error("duplicate event tag");
766 				seen_event = 1;
767 				evt = parse_hex(value);
768 				if (evt == nr)
769 					event_found = 1;
770 				free(value);
771 			} else if (strcmp(name, "mmcr0") == 0) {
772 				if (seen_mmcr0)
773 					parse_error("duplicate mmcr0 tag");
774 				seen_mmcr0 = 1;
775 				mmcr0 = parse_hex(value);
776 				free(value);
777 			} else if (strcmp(name, "mmcr1") == 0) {
778 				if (seen_mmcr1)
779 					parse_error("duplicate mmcr1: tag");
780 				seen_mmcr1 = 1;
781 				mmcr1 = parse_long_hex(value);
782 				free(value);
783 			} else if (strcmp(name, "mmcra") == 0) {
784 				if (seen_mmcra)
785 					parse_error("duplicate mmcra: tag");
786 				seen_mmcra = 1;
787 				mmcra = parse_hex(value);
788 				free(value);
789 			} else {
790 				parse_error("unknown tag");
791 			}
792 
793 			free(name);
794 		}
795 next:
796 		free(line);
797 		line = op_get_line(fp);
798 		++line_nr;
799 	}
800 	if (event_found) {
801 		if (!seen_mmcr0 || !seen_mmcr1 || !seen_mmcra) {
802 			fprintf(stderr, "Error: Missing information in line %d of event mapping file %s\n", line_nr, filename);
803 			exit(EXIT_FAILURE);
804 		}
805 		map = xmalloc(70);
806 		snprintf(map, 70, "mmcr0:%u mmcr1:%Lu mmcra:%u",
807 		         mmcr0, mmcr1, mmcra);
808 	}
809 
810 	return map;
811 }
812 
813 
find_mapping_for_event(u32 nr,op_cpu cpu_type)814 char const * find_mapping_for_event(u32 nr, op_cpu cpu_type)
815 {
816 	char const * cpu_name = op_get_cpu_name(cpu_type);
817 	FILE * fp = open_event_mapping_file(cpu_name);
818 	char const * map = NULL;
819 	switch (cpu_type) {
820 		case CPU_PPC64_PA6T:
821 		case CPU_PPC64_970:
822 		case CPU_PPC64_970MP:
823 		case CPU_PPC64_POWER4:
824 		case CPU_PPC64_POWER5:
825 		case CPU_PPC64_POWER5p:
826 		case CPU_PPC64_POWER5pp:
827 		case CPU_PPC64_POWER6:
828 		case CPU_PPC64_POWER7:
829 		case CPU_PPC64_IBM_COMPAT_V1:
830 			if (!fp) {
831 				fprintf(stderr, "oprofile: could not open event mapping file %s\n", filename);
832 				exit(EXIT_FAILURE);
833 			} else {
834 				map = get_mapping(nr, fp);
835 			}
836 			break;
837 		default:
838 			break;
839 	}
840 
841 	if (fp)
842 		fclose(fp);
843 
844 	return map;
845 }
846 
match_event(int i,struct op_event * event,unsigned um)847 static int match_event(int i, struct op_event *event, unsigned um)
848 {
849 	unsigned v = event->unit->um[i].value;
850 
851 	switch (event->unit->unit_type_mask) {
852 	case utm_exclusive:
853 	case utm_mandatory:
854 		return v == um;
855 
856 	case utm_bitmask:
857 		return (v & um) || (!v && v == 0);
858 	}
859 
860 	abort();
861 }
862 
find_event_by_name(char const * name,unsigned um,int um_valid)863 struct op_event * find_event_by_name(char const * name, unsigned um, int um_valid)
864 {
865 	struct list_head * pos;
866 
867 	list_for_each(pos, &events_list) {
868 		struct op_event * event = list_entry(pos, struct op_event, event_next);
869 		if (strcmp(event->name, name) == 0) {
870 			if (um_valid) {
871 				unsigned i;
872 
873 				for (i = 0; i < event->unit->num; i++)
874 					if (match_event(i, event, um))
875 						return event;
876 				continue;
877 			}
878 			return event;
879 		}
880 	}
881 
882 	return NULL;
883 }
884 
885 
op_find_event(op_cpu cpu_type,u32 nr,u32 um)886 struct op_event * op_find_event(op_cpu cpu_type, u32 nr, u32 um)
887 {
888 	struct op_event * event;
889 
890 	load_events(cpu_type);
891 
892 	event = find_event_um(nr, um);
893 
894 	return event;
895 }
896 
op_find_event_any(op_cpu cpu_type,u32 nr)897 struct op_event * op_find_event_any(op_cpu cpu_type, u32 nr)
898 {
899 	load_events(cpu_type);
900 
901 	return find_event_any(nr);
902 }
903 
op_check_events(int ctr,u32 nr,u32 um,op_cpu cpu_type)904 int op_check_events(int ctr, u32 nr, u32 um, op_cpu cpu_type)
905 {
906 	int ret = OP_INVALID_EVENT;
907 	size_t i;
908 	u32 ctr_mask = 1 << ctr;
909 	struct list_head * pos;
910 
911 	load_events(cpu_type);
912 
913 	list_for_each(pos, &events_list) {
914 		struct op_event * event = list_entry(pos, struct op_event, event_next);
915 		if (event->val != nr)
916 			continue;
917 
918 		ret = OP_OK_EVENT;
919 
920 		if ((event->counter_mask & ctr_mask) == 0)
921 			ret |= OP_INVALID_COUNTER;
922 
923 		if (event->unit->unit_type_mask == utm_bitmask) {
924 			for (i = 0; i < event->unit->num; ++i)
925 				um &= ~(event->unit->um[i].value);
926 
927 			if (um)
928 				ret |= OP_INVALID_UM;
929 
930 		} else {
931 			for (i = 0; i < event->unit->num; ++i) {
932 				if (event->unit->um[i].value == um)
933 					break;
934 			}
935 
936 			if (i == event->unit->num)
937 				ret |= OP_INVALID_UM;
938 
939 		}
940 
941 		if (ret == OP_OK_EVENT)
942 			return ret;
943 	}
944 
945 	return ret;
946 }
947 
948 
op_default_event(op_cpu cpu_type,struct op_default_event_descr * descr)949 void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr)
950 {
951 	descr->name = "";
952 	descr->um = 0x0;
953 	/* A fixed value of CPU cycles; this should ensure good
954 	 * granulity even on faster CPUs, though it will generate more
955 	 * interrupts.
956 	 */
957 	descr->count = 100000;
958 
959 	switch (cpu_type) {
960 		case CPU_PPRO:
961 		case CPU_PII:
962 		case CPU_PIII:
963 		case CPU_P6_MOBILE:
964 		case CPU_CORE:
965 		case CPU_CORE_2:
966 		case CPU_ATHLON:
967 		case CPU_HAMMER:
968 		case CPU_FAMILY10:
969 		case CPU_ARCH_PERFMON:
970 		case CPU_FAMILY11H:
971  		case CPU_ATOM:
972  		case CPU_CORE_I7:
973 			descr->name = "CPU_CLK_UNHALTED";
974 			break;
975 
976 		case CPU_RTC:
977 			descr->name = "RTC_INTERRUPTS";
978 			descr->count = 1024;
979 			break;
980 
981 		case CPU_P4:
982 		case CPU_P4_HT2:
983 			descr->name = "GLOBAL_POWER_EVENTS";
984 			descr->um = 0x1;
985 			break;
986 
987 		case CPU_IA64:
988 		case CPU_IA64_1:
989 		case CPU_IA64_2:
990 			descr->count = 1000000;
991 			descr->name = "CPU_CYCLES";
992 			break;
993 
994 		case CPU_AXP_EV4:
995 		case CPU_AXP_EV5:
996 		case CPU_AXP_PCA56:
997 		case CPU_AXP_EV6:
998 		case CPU_AXP_EV67:
999 			descr->name = "CYCLES";
1000 			break;
1001 
1002 		// we could possibly use the CCNT
1003 		case CPU_ARM_XSCALE1:
1004 		case CPU_ARM_XSCALE2:
1005 		case CPU_ARM_MPCORE:
1006 		case CPU_ARM_V6:
1007 		case CPU_ARM_V7:
1008 		case CPU_AVR32:
1009 			descr->name = "CPU_CYCLES";
1010 			break;
1011 
1012 		case CPU_PPC64_PA6T:
1013 		case CPU_PPC64_970:
1014 		case CPU_PPC64_970MP:
1015 		case CPU_PPC_7450:
1016 		case CPU_PPC64_POWER4:
1017 		case CPU_PPC64_POWER5:
1018 		case CPU_PPC64_POWER6:
1019 		case CPU_PPC64_POWER5p:
1020 		case CPU_PPC64_POWER5pp:
1021 		case CPU_PPC64_CELL:
1022 		case CPU_PPC64_POWER7:
1023 		case CPU_PPC64_IBM_COMPAT_V1:
1024 			descr->name = "CYCLES";
1025 			break;
1026 
1027 		case CPU_MIPS_20K:
1028 			descr->name = "CYCLES";
1029 			break;
1030 
1031 		case CPU_MIPS_24K:
1032 			descr->name = "INSTRUCTIONS";
1033 			break;
1034 
1035 		case CPU_MIPS_34K:
1036 			descr->name = "INSTRUCTIONS";
1037 			break;
1038 
1039 		case CPU_MIPS_5K:
1040 		case CPU_MIPS_25K:
1041 			descr->name = "CYCLES";
1042 			break;
1043 
1044 		case CPU_MIPS_R10000:
1045 		case CPU_MIPS_R12000:
1046 			descr->name = "INSTRUCTIONS_GRADUATED";
1047 			break;
1048 
1049 		case CPU_MIPS_RM7000:
1050 		case CPU_MIPS_RM9000:
1051 			descr->name = "INSTRUCTIONS_ISSUED";
1052 			break;
1053 
1054 		case CPU_MIPS_SB1:
1055 			descr->name = "INSN_SURVIVED_STAGE7";
1056 			break;
1057 
1058 		case CPU_MIPS_VR5432:
1059 		case CPU_MIPS_VR5500:
1060 			descr->name = "INSTRUCTIONS_EXECUTED";
1061 			break;
1062 
1063 		case CPU_PPC_E500:
1064 		case CPU_PPC_E500_2:
1065 		case CPU_PPC_E300:
1066 			descr->name = "CPU_CLK";
1067 			break;
1068 
1069 		// don't use default, if someone add a cpu he wants a compiler
1070 		// warning if he forgets to handle it here.
1071 		case CPU_TIMER_INT:
1072 		case CPU_NO_GOOD:
1073 		case MAX_CPU_TYPE:
1074 			break;
1075 	}
1076 }
1077