blob: 2fdfd1d923f2a753e952ae1e6d6bcfb4ba8ba0ba [file] [log] [blame]
Ingo Molnar8ad8db32009-05-26 11:10:09 +02001
2#include "../perf.h"
3#include "util.h"
4#include "parse-options.h"
5#include "parse-events.h"
6#include "exec_cmd.h"
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -03007#include "string.h"
Ingo Molnar8ad8db32009-05-26 11:10:09 +02008
9int nr_counters;
10
11__u64 event_id[MAX_COUNTERS] = { };
Ingo Molnar52425192009-05-26 09:17:18 +020012int event_mask[MAX_COUNTERS];
Ingo Molnar8ad8db32009-05-26 11:10:09 +020013
14struct event_symbol {
15 __u64 event;
16 char *symbol;
17};
18
19static struct event_symbol event_symbols[] = {
20 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cpu-cycles", },
21 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), "cycles", },
22 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS), "instructions", },
23 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES), "cache-references", },
24 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES), "cache-misses", },
25 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branch-instructions", },
26 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_INSTRUCTIONS), "branches", },
27 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BRANCH_MISSES), "branch-misses", },
28 {EID(PERF_TYPE_HARDWARE, PERF_COUNT_BUS_CYCLES), "bus-cycles", },
29
30 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK), "cpu-clock", },
31 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK), "task-clock", },
32 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "page-faults", },
33 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), "faults", },
34 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MIN), "minor-faults", },
35 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS_MAJ), "major-faults", },
36 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "context-switches", },
37 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), "cs", },
38 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "cpu-migrations", },
39 {EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), "migrations", },
40};
41
Ingo Molnar52425192009-05-26 09:17:18 +020042#define __PERF_COUNTER_FIELD(config, name) \
43 ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
44
45#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
46#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
47#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
48#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
49
50static char *hw_event_names[] = {
51 "CPU cycles",
52 "instructions",
53 "cache references",
54 "cache misses",
55 "branches",
56 "branch misses",
57 "bus cycles",
58};
59
60static char *sw_event_names[] = {
61 "cpu clock ticks",
62 "task clock ticks",
63 "pagefaults",
64 "context switches",
65 "CPU migrations",
66 "minor faults",
67 "major faults",
68};
69
70char *event_name(int ctr)
71{
72 __u64 config = event_id[ctr];
73 int type = PERF_COUNTER_TYPE(config);
74 int id = PERF_COUNTER_ID(config);
75 static char buf[32];
76
77 if (PERF_COUNTER_RAW(config)) {
78 sprintf(buf, "raw 0x%llx", PERF_COUNTER_CONFIG(config));
79 return buf;
80 }
81
82 switch (type) {
83 case PERF_TYPE_HARDWARE:
84 if (id < PERF_HW_EVENTS_MAX)
85 return hw_event_names[id];
86 return "unknown-hardware";
87
88 case PERF_TYPE_SOFTWARE:
89 if (id < PERF_SW_EVENTS_MAX)
90 return sw_event_names[id];
91 return "unknown-software";
92
93 default:
94 break;
95 }
96
97 return "unknown";
98}
99
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200100/*
101 * Each event can have multiple symbolic names.
102 * Symbolic names are (almost) exactly matched.
103 */
104static __u64 match_event_symbols(const char *str)
105{
106 __u64 config, id;
107 int type;
108 unsigned int i;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300109 const char *sep, *pstr;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200110
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300111 if (str[0] == 'r' && hex2u64(str + 1, &config) > 0)
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200112 return config | PERF_COUNTER_RAW_MASK;
113
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300114 pstr = str;
115 sep = strchr(pstr, ':');
116 if (sep) {
117 type = atoi(pstr);
118 pstr = sep + 1;
119 id = atoi(pstr);
120 sep = strchr(pstr, ':');
121 if (sep) {
122 pstr = sep + 1;
123 if (strchr(pstr, 'k'))
Ingo Molnar52425192009-05-26 09:17:18 +0200124 event_mask[nr_counters] |= EVENT_MASK_USER;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300125 if (strchr(pstr, 'u'))
Ingo Molnar52425192009-05-26 09:17:18 +0200126 event_mask[nr_counters] |= EVENT_MASK_KERNEL;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300127 }
128 return EID(type, id);
Ingo Molnar52425192009-05-26 09:17:18 +0200129 }
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200130
131 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
132 if (!strncmp(str, event_symbols[i].symbol,
133 strlen(event_symbols[i].symbol)))
134 return event_symbols[i].event;
135 }
136
137 return ~0ULL;
138}
139
140int parse_events(const struct option *opt, const char *str, int unset)
141{
142 __u64 config;
143
144again:
145 if (nr_counters == MAX_COUNTERS)
146 return -1;
147
148 config = match_event_symbols(str);
149 if (config == ~0ULL)
150 return -1;
151
152 event_id[nr_counters] = config;
153 nr_counters++;
154
155 str = strstr(str, ",");
156 if (str) {
157 str++;
158 goto again;
159 }
160
161 return 0;
162}
163
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200164/*
165 * Create the help text for the event symbols:
166 */
167void create_events_help(char *events_help_msg)
168{
169 unsigned int i;
170 char *str;
171 __u64 e;
172
173 str = events_help_msg;
174
175 str += sprintf(str,
176 "event name: [");
177
178 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
179 int type, id;
180
181 e = event_symbols[i].event;
182 type = PERF_COUNTER_TYPE(e);
183 id = PERF_COUNTER_ID(e);
184
185 if (i)
186 str += sprintf(str, "|");
187
188 str += sprintf(str, "%s",
189 event_symbols[i].symbol);
190 }
191
192 str += sprintf(str, "|rNNN]");
193}
194