op_events.c revision 2b16b5ffd52ea5c0289e5ce794298bce5d941b2b
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
20#include <string.h>
21#include <stdlib.h>
22#include <stdio.h>
23
24static LIST_HEAD(events_list);
25static LIST_HEAD(um_list);
26
27static char const * filename;
28static unsigned int line_nr;
29
30static void parse_error(char const * context)
31{
32	fprintf(stderr, "oprofile: parse error in %s, line %u\n",
33		filename, line_nr);
34	fprintf(stderr, "%s\n", context);
35	exit(EXIT_FAILURE);
36}
37
38
39static int parse_int(char const * str)
40{
41	int value;
42	if (sscanf(str, "%d", &value) != 1)
43		parse_error("expected decimal value");
44
45	return value;
46}
47
48
49static int parse_hex(char const * str)
50{
51	int value;
52	/* 0x/0X to force the use of hexa notation for field intended to
53	   be in hexadecimal */
54	if (sscanf(str, "0x%x", &value) != 1 &&
55	    sscanf(str, "0X%x", &value) != 1)
56		parse_error("expected hexadecimal value");
57
58	return value;
59}
60
61
62static u64 parse_long_hex(char const * str)
63{
64	u64 value;
65	if (sscanf(str, "%Lx", &value) != 1)
66		parse_error("expected long hexadecimal value");
67
68	fflush(stderr);
69	return value;
70}
71
72
73/* name:MESI type:bitmask default:0x0f */
74static void parse_um(struct op_unit_mask * um, char const * line)
75{
76	int seen_name = 0;
77	int seen_type = 0;
78       	int seen_default = 0;
79	char const * valueend = line + 1;
80       	char const * tagend = line + 1;
81	char const * start = line;
82
83	while (*valueend) {
84		valueend = skip_nonws(valueend);
85
86		while (*tagend != ':' && *tagend)
87			++tagend;
88
89		if (valueend == tagend)
90			break;
91
92		if (!*tagend)
93			parse_error("parse_um() expected :value");
94
95		++tagend;
96
97		if (strisprefix(start, "name")) {
98			if (seen_name)
99				parse_error("duplicate name: tag");
100			seen_name = 1;
101			um->name = op_xstrndup(tagend, valueend - tagend);
102		} else if (strisprefix(start, "type")) {
103			if (seen_type)
104				parse_error("duplicate type: tag");
105			seen_type = 1;
106			if (strisprefix(tagend, "mandatory")) {
107				um->unit_type_mask = utm_mandatory;
108			} else if (strisprefix(tagend, "bitmask")) {
109				um->unit_type_mask = utm_bitmask;
110			} else if (strisprefix(tagend, "exclusive")) {
111				um->unit_type_mask = utm_exclusive;
112			} else {
113				parse_error("invalid unit mask type");
114			}
115		} else if (strisprefix(start, "default")) {
116			if (seen_default)
117				parse_error("duplicate default: tag");
118			seen_default = 1;
119			um->default_mask = parse_hex(tagend);
120		} else {
121			parse_error("invalid unit mask tag");
122		}
123
124		valueend = skip_ws(valueend);
125		tagend = valueend;
126		start = valueend;
127	}
128}
129
130
131/* \t0x08 (M)odified cache state */
132static void parse_um_entry(struct op_described_um * entry, char const * line)
133{
134	char const * c = line;
135
136	c = skip_ws(c);
137	entry->value = parse_hex(c);
138	c = skip_nonws(c);
139
140	if (!*c)
141		parse_error("invalid unit mask entry");
142
143	c = skip_ws(c);
144
145	if (!*c)
146		parse_error("invalid unit mask entry");
147
148	entry->desc = xstrdup(c);
149}
150
151
152static struct op_unit_mask * new_unit_mask(void)
153{
154	struct op_unit_mask * um = xmalloc(sizeof(struct op_unit_mask));
155	memset(um, '\0', sizeof(struct op_unit_mask));
156	list_add_tail(&um->um_next, &um_list);
157
158	return um;
159}
160
161
162/*
163 * name:zero type:mandatory default:0x0
164 * \t0x0 No unit mask
165 */
166static void read_unit_masks(char const * file)
167{
168	struct op_unit_mask * um = NULL;
169	char * line;
170	FILE * fp = fopen(file, "r");
171
172	if (!fp) {
173		fprintf(stderr,
174			"oprofile: could not open unit mask description file %s\n", file);
175		exit(EXIT_FAILURE);
176	}
177
178	filename = file;
179	line_nr = 1;
180
181	line = op_get_line(fp);
182
183	while (line) {
184		if (empty_line(line) || comment_line(line))
185			goto next;
186
187		if (line[0] != '\t') {
188			um = new_unit_mask();
189			parse_um(um, line);
190		} else {
191			if (!um)
192				parse_error("no unit mask name line");
193			if (um->num >= MAX_UNIT_MASK)
194				parse_error("oprofile: maximum unit mask entries exceeded");
195
196			parse_um_entry(&um->um[um->num], line);
197			++(um->num);
198		}
199
200next:
201		free(line);
202		line = op_get_line(fp);
203		++line_nr;
204	}
205
206	fclose(fp);
207}
208
209
210static u32 parse_counter_mask(char const * str)
211{
212	u32 mask = 0;
213	char const * numstart = str;
214
215	while (*numstart) {
216		mask |= 1 << parse_int(numstart);
217
218		while (*numstart && *numstart != ',')
219			++numstart;
220		/* skip , unless we reach eos */
221		if (*numstart)
222			++numstart;
223
224		numstart = skip_ws(numstart);
225	}
226
227	return mask;
228}
229
230
231static struct op_unit_mask * find_um(char const * value)
232{
233	struct list_head * pos;
234
235	list_for_each(pos, &um_list) {
236		struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next);
237		if (strcmp(value, um->name) == 0)
238			return um;
239	}
240
241	fprintf(stderr, "oprofile: could not find unit mask %s\n", value);
242	exit(EXIT_FAILURE);
243}
244
245
246/* parse either a "tag:value" or a ": trailing description string" */
247static int next_token(char const ** cp, char ** name, char ** value)
248{
249	size_t tag_len;
250	size_t val_len;
251	char const * c = *cp;
252	char const * end;
253	char const * colon;
254
255	c = skip_ws(c);
256	end = colon = c;
257	end = skip_nonws(end);
258
259	colon = strchr(colon, ':');
260
261	if (!colon) {
262		if (*c)
263			parse_error("next_token(): garbage at end of line");
264		return 0;
265	}
266
267	if (colon >= end)
268		parse_error("next_token() expected ':'");
269
270	tag_len = colon - c;
271	val_len = end - (colon + 1);
272
273	if (!tag_len) {
274		/* : trailing description */
275		end = skip_ws(end);
276		*name = xstrdup("desc");
277		*value = xstrdup(end);
278		end += strlen(end);
279	} else {
280		/* tag:value */
281		*name = op_xstrndup(c, tag_len);
282		*value = op_xstrndup(colon + 1, val_len);
283		end = skip_ws(end);
284	}
285
286	*cp = end;
287	return 1;
288}
289
290
291static struct op_event * new_event(void)
292{
293	struct op_event * event = xmalloc(sizeof(struct op_event));
294	memset(event, '\0', sizeof(struct op_event));
295	list_add_tail(&event->event_next, &events_list);
296
297	return event;
298}
299
300
301/* event:0x00 counters:0 um:zero minimum:4096 name:ISSUES : Total issues */
302static void read_events(char const * file)
303{
304	struct op_event * event = NULL;
305	char * line;
306	char * name;
307	char * value;
308	char const * c;
309	int seen_event, seen_counters, seen_um, seen_minimum, seen_name;
310	FILE * fp = fopen(file, "r");
311
312	if (!fp) {
313		fprintf(stderr, "oprofile: could not open event description file %s\n", file);
314		exit(EXIT_FAILURE);
315	}
316
317	filename = file;
318	line_nr = 1;
319
320	line = op_get_line(fp);
321
322	while (line) {
323		if (empty_line(line) || comment_line(line))
324			goto next;
325
326		seen_name = 0;
327		seen_event = 0;
328		seen_counters = 0;
329		seen_um = 0;
330		seen_minimum = 0;
331		event = new_event();
332
333		c = line;
334		while (next_token(&c, &name, &value)) {
335			if (strcmp(name, "name") == 0) {
336				if (seen_name)
337					parse_error("duplicate name: tag");
338				seen_name = 1;
339				if (strchr(value, '/') != NULL)
340					parse_error("invalid event name");
341				if (strchr(value, '.') != NULL)
342					parse_error("invalid event name");
343				event->name = value;
344			} else if (strcmp(name, "event") == 0) {
345				if (seen_event)
346					parse_error("duplicate event: tag");
347				seen_event = 1;
348				event->val = parse_hex(value);
349				free(value);
350			} else if (strcmp(name, "counters") == 0) {
351				if (seen_counters)
352					parse_error("duplicate counters: tag");
353				seen_counters = 1;
354				event->counter_mask = parse_counter_mask(value);
355				free(value);
356			} else if (strcmp(name, "um") == 0) {
357				if (seen_um)
358					parse_error("duplicate um: tag");
359				seen_um = 1;
360				event->unit = find_um(value);
361				event->unit->used = 1;
362				free(value);
363			} else if (strcmp(name, "minimum") == 0) {
364				if (seen_minimum)
365					parse_error("duplicate minimum: tag");
366				seen_minimum = 1;
367				event->min_count = parse_int(value);
368				free(value);
369			} else if (strcmp(name, "desc") == 0) {
370				event->desc = value;
371			} else {
372				parse_error("unknown tag");
373			}
374
375			free(name);
376		}
377next:
378		free(line);
379		line = op_get_line(fp);
380		++line_nr;
381	}
382
383	fclose(fp);
384}
385
386
387/* usefull for make check */
388static void check_unit_mask(struct op_unit_mask const * um,
389	char const * cpu_name)
390{
391	u32 i;
392
393	if (!um->used) {
394		fprintf(stderr, "um %s is not used\n", um->name);
395		exit(EXIT_FAILURE);
396	}
397
398	if (um->unit_type_mask == utm_mandatory && um->num != 1) {
399		fprintf(stderr, "mandatory um %s doesn't contain exactly one "
400			"entry (%s)\n", um->name, cpu_name);
401		exit(EXIT_FAILURE);
402	} else if (um->unit_type_mask == utm_bitmask) {
403		u32 default_mask = um->default_mask;
404		for (i = 0; i < um->num; ++i)
405			default_mask &= ~um->um[i].value;
406
407		if (default_mask) {
408			fprintf(stderr, "um %s default mask is not valid "
409				"(%s)\n", um->name, cpu_name);
410			exit(EXIT_FAILURE);
411		}
412	} else {
413		for (i = 0; i < um->num; ++i) {
414			if (um->default_mask == um->um[i].value)
415				break;
416		}
417
418		if (i == um->num) {
419			fprintf(stderr, "exclusive um %s default value is not "
420				"valid (%s)\n", um->name, cpu_name);
421			exit(EXIT_FAILURE);
422		}
423	}
424}
425
426
427static void load_events(op_cpu cpu_type)
428{
429	char const * cpu_name = op_get_cpu_name(cpu_type);
430	char * event_dir;
431	char * event_file;
432	char * um_file;
433	char * dir;
434	struct list_head * pos;
435
436	if (!list_empty(&events_list))
437		return;
438
439	dir = getenv("OPROFILE_EVENTS_DIR");
440	if (dir == NULL)
441		dir = OP_DATADIR;
442
443	event_dir = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) +
444                            strlen("/") + 1);
445	strcpy(event_dir, dir);
446	strcat(event_dir, "/");
447
448	strcat(event_dir, cpu_name);
449	strcat(event_dir, "/");
450
451	event_file = xmalloc(strlen(event_dir) + strlen("events") + 1);
452	strcpy(event_file, event_dir);
453	strcat(event_file, "events");
454
455	um_file = xmalloc(strlen(event_dir) + strlen("unit_masks") + 1);
456	strcpy(um_file, event_dir);
457	strcat(um_file, "unit_masks");
458
459	read_unit_masks(um_file);
460	read_events(event_file);
461
462	/* sanity check: all unit mask must be used */
463	list_for_each(pos, &um_list) {
464		struct op_unit_mask * um = list_entry(pos, struct op_unit_mask, um_next);
465
466		check_unit_mask(um, cpu_name);
467	}
468
469	free(um_file);
470	free(event_file);
471	free(event_dir);
472}
473
474
475struct list_head * op_events(op_cpu cpu_type)
476{
477	load_events(cpu_type);
478	return &events_list;
479}
480
481
482static void delete_unit_mask(struct op_unit_mask * unit)
483{
484	u32 cur;
485	for (cur = 0 ; cur < unit->num ; ++cur) {
486		if (unit->um[cur].desc)
487			free(unit->um[cur].desc);
488	}
489
490	if (unit->name)
491		free(unit->name);
492
493	list_del(&unit->um_next);
494	free(unit);
495}
496
497
498static void delete_event(struct op_event * event)
499{
500	if (event->name)
501		free(event->name);
502	if (event->desc)
503		free(event->desc);
504
505	list_del(&event->event_next);
506	free(event);
507}
508
509
510void op_free_events(void)
511{
512	struct list_head * pos, * pos2;
513	list_for_each_safe(pos, pos2, &events_list) {
514		struct op_event * event = list_entry(pos, struct op_event, event_next);
515		delete_event(event);
516	}
517
518	list_for_each_safe(pos, pos2, &um_list) {
519		struct op_unit_mask * unit = list_entry(pos, struct op_unit_mask, um_next);
520		delete_unit_mask(unit);
521	}
522}
523
524
525static struct op_event * find_event(u32 nr)
526{
527	struct list_head * pos;
528
529	list_for_each(pos, &events_list) {
530		struct op_event * event = list_entry(pos, struct op_event, event_next);
531		if (event->val == nr)
532			return event;
533	}
534
535	return NULL;
536}
537
538
539static FILE * open_event_mapping_file(char const * cpu_name)
540{
541	char * ev_map_file;
542	char * dir;
543	dir = getenv("OPROFILE_EVENTS_DIR");
544	if (dir == NULL)
545		dir = OP_DATADIR;
546
547	ev_map_file = xmalloc(strlen(dir) + strlen("/") + strlen(cpu_name) +
548	                    strlen("/") + + strlen("event_mappings") + 1);
549	strcpy(ev_map_file, dir);
550	strcat(ev_map_file, "/");
551
552	strcat(ev_map_file, cpu_name);
553	strcat(ev_map_file, "/");
554	strcat(ev_map_file, "event_mappings");
555	filename = ev_map_file;
556	return (fopen(ev_map_file, "r"));
557}
558
559
560/**
561 *  This function is PPC64-specific.
562 */
563static char const * get_mapping(u32 nr, FILE * fp)
564{
565	char * line;
566	char * name;
567	char * value;
568	char const * c;
569	char * map = NULL;
570	int seen_event = 0, seen_mmcr0 = 0, seen_mmcr1 = 0, seen_mmcra = 0;
571	u32 mmcr0 = 0;
572	u64 mmcr1 = 0;
573	u32 mmcra = 0;
574	int event_found = 0;
575
576	line_nr = 1;
577	line = op_get_line(fp);
578	while (line && !event_found) {
579		if (empty_line(line) || comment_line(line))
580			goto next;
581
582		seen_event = 0;
583		seen_mmcr0 = 0;
584		seen_mmcr1 = 0;
585		seen_mmcra = 0;
586		mmcr0 = 0;
587		mmcr1 = 0;
588		mmcra = 0;
589
590		c = line;
591		while (next_token(&c, &name, &value)) {
592			if (strcmp(name, "event") == 0) {
593				u32 evt;
594				if (seen_event)
595					parse_error("duplicate event tag");
596				seen_event = 1;
597				evt = parse_hex(value);
598				if (evt == nr)
599					event_found = 1;
600				free(value);
601			} else if (strcmp(name, "mmcr0") == 0) {
602				if (seen_mmcr0)
603					parse_error("duplicate mmcr0 tag");
604				seen_mmcr0 = 1;
605				mmcr0 = parse_hex(value);
606				free(value);
607			} else if (strcmp(name, "mmcr1") == 0) {
608				if (seen_mmcr1)
609					parse_error("duplicate mmcr1: tag");
610				seen_mmcr1 = 1;
611				mmcr1 = parse_long_hex(value);
612				free(value);
613			} else if (strcmp(name, "mmcra") == 0) {
614				if (seen_mmcra)
615					parse_error("duplicate mmcra: tag");
616				seen_mmcra = 1;
617				mmcra = parse_hex(value);
618				free(value);
619			} else {
620				parse_error("unknown tag");
621			}
622
623			free(name);
624		}
625next:
626		free(line);
627		line = op_get_line(fp);
628		++line_nr;
629	}
630	if (event_found) {
631		if (!seen_mmcr0 || !seen_mmcr1 || !seen_mmcra) {
632			fprintf(stderr, "Error: Missing information in line %d of event mapping file %s\n", line_nr, filename);
633			exit(EXIT_FAILURE);
634		}
635		map = xmalloc(70);
636		snprintf(map, 70, "mmcr0:%u mmcr1:%Lu mmcra:%u",
637		         mmcr0, mmcr1, mmcra);
638	}
639
640	return map;
641}
642
643
644char const * find_mapping_for_event(u32 nr, op_cpu cpu_type)
645{
646	char const * cpu_name = op_get_cpu_name(cpu_type);
647	FILE * fp = open_event_mapping_file(cpu_name);
648	char const * map = NULL;
649	switch (cpu_type) {
650		case CPU_PPC64_PA6T:
651		case CPU_PPC64_970:
652		case CPU_PPC64_970MP:
653		case CPU_PPC64_POWER4:
654		case CPU_PPC64_POWER5:
655		case CPU_PPC64_POWER5p:
656		case CPU_PPC64_POWER5pp:
657		case CPU_PPC64_POWER6:
658			if (!fp) {
659				fprintf(stderr, "oprofile: could not open event mapping file %s\n", filename);
660				exit(EXIT_FAILURE);
661			} else {
662				map = get_mapping(nr, fp);
663			}
664			break;
665		default:
666			break;
667	}
668
669	if (fp)
670		fclose(fp);
671
672	return map;
673}
674
675
676struct op_event * find_event_by_name(char const * name)
677{
678	struct list_head * pos;
679
680	list_for_each(pos, &events_list) {
681		struct op_event * event = list_entry(pos, struct op_event, event_next);
682		if (strcmp(event->name, name) == 0)
683			return event;
684	}
685
686	return NULL;
687}
688
689
690struct op_event * op_find_event(op_cpu cpu_type, u32 nr)
691{
692	struct op_event * event;
693
694	load_events(cpu_type);
695
696	event = find_event(nr);
697
698	return event;
699}
700
701
702int op_check_events(int ctr, u32 nr, u32 um, op_cpu cpu_type)
703{
704	int ret = OP_OK_EVENT;
705	struct op_event * event;
706	size_t i;
707	u32 ctr_mask = 1 << ctr;
708
709	load_events(cpu_type);
710
711	event = find_event(nr);
712
713	if (!event) {
714		ret |= OP_INVALID_EVENT;
715		return ret;
716	}
717
718	if ((event->counter_mask & ctr_mask) == 0)
719		ret |= OP_INVALID_COUNTER;
720
721	if (event->unit->unit_type_mask == utm_bitmask) {
722		for (i = 0; i < event->unit->num; ++i)
723			um &= ~(event->unit->um[i].value);
724
725		if (um)
726			ret |= OP_INVALID_UM;
727
728	} else {
729		for (i = 0; i < event->unit->num; ++i) {
730			if (event->unit->um[i].value == um)
731				break;
732		}
733
734		if (i == event->unit->num)
735			ret |= OP_INVALID_UM;
736	}
737
738	return ret;
739}
740
741
742void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr)
743{
744	descr->name = "";
745	descr->um = 0x0;
746	/* A fixed value of CPU cycles; this should ensure good
747	 * granulity even on faster CPUs, though it will generate more
748	 * interrupts.
749	 */
750	descr->count = 100000;
751
752	switch (cpu_type) {
753		case CPU_PPRO:
754		case CPU_PII:
755		case CPU_PIII:
756		case CPU_P6_MOBILE:
757		case CPU_CORE:
758		case CPU_CORE_2:
759		case CPU_ATHLON:
760		case CPU_HAMMER:
761		case CPU_FAMILY10:
762			descr->name = "CPU_CLK_UNHALTED";
763			break;
764
765		case CPU_RTC:
766			descr->name = "RTC_INTERRUPTS";
767			descr->count = 1024;
768			break;
769
770		case CPU_P4:
771		case CPU_P4_HT2:
772			descr->name = "GLOBAL_POWER_EVENTS";
773			descr->um = 0x1;
774			break;
775
776		case CPU_IA64:
777		case CPU_IA64_1:
778		case CPU_IA64_2:
779			descr->count = 1000000;
780			descr->name = "CPU_CYCLES";
781			break;
782
783		case CPU_AXP_EV4:
784		case CPU_AXP_EV5:
785		case CPU_AXP_PCA56:
786		case CPU_AXP_EV6:
787		case CPU_AXP_EV67:
788			descr->name = "CYCLES";
789			break;
790
791		// we could possibly use the CCNT
792		case CPU_ARM_XSCALE1:
793		case CPU_ARM_XSCALE2:
794		case CPU_ARM_MPCORE:
795		case CPU_ARM_V6:
796		case CPU_AVR32:
797			descr->name = "CPU_CYCLES";
798			break;
799
800		case CPU_PPC64_PA6T:
801		case CPU_PPC64_970:
802		case CPU_PPC64_970MP:
803		case CPU_PPC_7450:
804		case CPU_PPC64_POWER4:
805		case CPU_PPC64_POWER5:
806		case CPU_PPC64_POWER6:
807		case CPU_PPC64_POWER5p:
808		case CPU_PPC64_POWER5pp:
809		case CPU_PPC64_CELL:
810			descr->name = "CYCLES";
811			break;
812
813		case CPU_MIPS_20K:
814			descr->name = "CYCLES";
815			break;
816
817		case CPU_MIPS_24K:
818			descr->name = "INSTRUCTIONS";
819			break;
820
821		case CPU_MIPS_34K:
822			descr->name = "INSTRUCTIONS";
823			break;
824
825		case CPU_MIPS_5K:
826		case CPU_MIPS_25K:
827			descr->name = "CYCLES";
828			break;
829
830		case CPU_MIPS_R10000:
831		case CPU_MIPS_R12000:
832			descr->name = "INSTRUCTIONS_GRADUATED";
833			break;
834
835		case CPU_MIPS_RM7000:
836		case CPU_MIPS_RM9000:
837			descr->name = "INSTRUCTIONS_ISSUED";
838			break;
839
840		case CPU_MIPS_SB1:
841			descr->name = "INSN_SURVIVED_STAGE7";
842			break;
843
844		case CPU_MIPS_VR5432:
845		case CPU_MIPS_VR5500:
846			descr->name = "INSTRUCTIONS_EXECUTED";
847			break;
848
849		case CPU_PPC_E500:
850		case CPU_PPC_E500_2:
851		case CPU_PPC_E300:
852			descr->name = "CPU_CLK";
853			break;
854
855		// don't use default, if someone add a cpu he wants a compiler
856		// warning if he forgets to handle it here.
857		case CPU_TIMER_INT:
858		case CPU_NO_GOOD:
859		case MAX_CPU_TYPE:
860			break;
861	}
862}
863