blob: eb56bd996573d11da0064c7868b49df3b914696c [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
Ingo Molnara21ca2c2009-06-06 09:58:57 +02009int nr_counters;
Ingo Molnar8ad8db32009-05-26 11:10:09 +020010
Ingo Molnara21ca2c2009-06-06 09:58:57 +020011struct perf_counter_attr attrs[MAX_COUNTERS];
Ingo Molnar8ad8db32009-05-26 11:10:09 +020012
13struct event_symbol {
Ingo Molnara21ca2c2009-06-06 09:58:57 +020014 __u8 type;
15 __u64 config;
16 char *symbol;
Ingo Molnar8ad8db32009-05-26 11:10:09 +020017};
18
Ingo Molnara21ca2c2009-06-06 09:58:57 +020019#define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y
Ingo Molnar8ad8db32009-05-26 11:10:09 +020020
Ingo Molnara21ca2c2009-06-06 09:58:57 +020021static struct event_symbol event_symbols[] = {
22 { C(HARDWARE, CPU_CYCLES), "cpu-cycles", },
23 { C(HARDWARE, CPU_CYCLES), "cycles", },
24 { C(HARDWARE, INSTRUCTIONS), "instructions", },
25 { C(HARDWARE, CACHE_REFERENCES), "cache-references", },
26 { C(HARDWARE, CACHE_MISSES), "cache-misses", },
27 { C(HARDWARE, BRANCH_INSTRUCTIONS), "branch-instructions", },
28 { C(HARDWARE, BRANCH_INSTRUCTIONS), "branches", },
29 { C(HARDWARE, BRANCH_MISSES), "branch-misses", },
30 { C(HARDWARE, BUS_CYCLES), "bus-cycles", },
31
32 { C(SOFTWARE, CPU_CLOCK), "cpu-clock", },
33 { C(SOFTWARE, TASK_CLOCK), "task-clock", },
34 { C(SOFTWARE, PAGE_FAULTS), "page-faults", },
35 { C(SOFTWARE, PAGE_FAULTS), "faults", },
36 { C(SOFTWARE, PAGE_FAULTS_MIN), "minor-faults", },
37 { C(SOFTWARE, PAGE_FAULTS_MAJ), "major-faults", },
38 { C(SOFTWARE, CONTEXT_SWITCHES), "context-switches", },
39 { C(SOFTWARE, CONTEXT_SWITCHES), "cs", },
40 { C(SOFTWARE, CPU_MIGRATIONS), "cpu-migrations", },
41 { C(SOFTWARE, CPU_MIGRATIONS), "migrations", },
Ingo Molnar8ad8db32009-05-26 11:10:09 +020042};
43
Ingo Molnar52425192009-05-26 09:17:18 +020044#define __PERF_COUNTER_FIELD(config, name) \
45 ((config & PERF_COUNTER_##name##_MASK) >> PERF_COUNTER_##name##_SHIFT)
46
47#define PERF_COUNTER_RAW(config) __PERF_COUNTER_FIELD(config, RAW)
48#define PERF_COUNTER_CONFIG(config) __PERF_COUNTER_FIELD(config, CONFIG)
49#define PERF_COUNTER_TYPE(config) __PERF_COUNTER_FIELD(config, TYPE)
50#define PERF_COUNTER_ID(config) __PERF_COUNTER_FIELD(config, EVENT)
51
52static char *hw_event_names[] = {
53 "CPU cycles",
54 "instructions",
55 "cache references",
56 "cache misses",
57 "branches",
58 "branch misses",
59 "bus cycles",
60};
61
62static char *sw_event_names[] = {
63 "cpu clock ticks",
64 "task clock ticks",
65 "pagefaults",
66 "context switches",
67 "CPU migrations",
68 "minor faults",
69 "major faults",
70};
71
Ingo Molnara21ca2c2009-06-06 09:58:57 +020072char *event_name(int counter)
Ingo Molnar52425192009-05-26 09:17:18 +020073{
Ingo Molnara21ca2c2009-06-06 09:58:57 +020074 __u64 config = attrs[counter].config;
75 int type = attrs[counter].type;
Ingo Molnar52425192009-05-26 09:17:18 +020076 static char buf[32];
77
Ingo Molnara21ca2c2009-06-06 09:58:57 +020078 if (attrs[counter].type == PERF_TYPE_RAW) {
79 sprintf(buf, "raw 0x%llx", config);
Ingo Molnar52425192009-05-26 09:17:18 +020080 return buf;
81 }
82
83 switch (type) {
84 case PERF_TYPE_HARDWARE:
Ingo Molnara21ca2c2009-06-06 09:58:57 +020085 if (config < PERF_HW_EVENTS_MAX)
86 return hw_event_names[config];
Ingo Molnar52425192009-05-26 09:17:18 +020087 return "unknown-hardware";
88
89 case PERF_TYPE_SOFTWARE:
Ingo Molnara21ca2c2009-06-06 09:58:57 +020090 if (config < PERF_SW_EVENTS_MAX)
91 return sw_event_names[config];
Ingo Molnar52425192009-05-26 09:17:18 +020092 return "unknown-software";
93
94 default:
95 break;
96 }
97
98 return "unknown";
99}
100
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200101/*
102 * Each event can have multiple symbolic names.
103 * Symbolic names are (almost) exactly matched.
104 */
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200105static int match_event_symbols(const char *str, struct perf_counter_attr *attr)
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200106{
107 __u64 config, id;
108 int type;
109 unsigned int i;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300110 const char *sep, *pstr;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200111
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200112 if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) {
113 attr->type = PERF_TYPE_RAW;
114 attr->config = config;
115
116 return 0;
117 }
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200118
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300119 pstr = str;
120 sep = strchr(pstr, ':');
121 if (sep) {
122 type = atoi(pstr);
123 pstr = sep + 1;
124 id = atoi(pstr);
125 sep = strchr(pstr, ':');
126 if (sep) {
127 pstr = sep + 1;
128 if (strchr(pstr, 'k'))
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200129 attr->exclude_user = 1;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300130 if (strchr(pstr, 'u'))
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200131 attr->exclude_kernel = 1;
Arnaldo Carvalho de Meloa0055ae2009-06-01 17:50:19 -0300132 }
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200133 attr->type = type;
134 attr->config = id;
135
136 return 0;
Ingo Molnar52425192009-05-26 09:17:18 +0200137 }
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200138
139 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
140 if (!strncmp(str, event_symbols[i].symbol,
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200141 strlen(event_symbols[i].symbol))) {
142
143 attr->type = event_symbols[i].type;
144 attr->config = event_symbols[i].config;
145
146 return 0;
147 }
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200148 }
149
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200150 return -EINVAL;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200151}
152
153int parse_events(const struct option *opt, const char *str, int unset)
154{
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200155 struct perf_counter_attr attr;
156 int ret;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200157
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200158 memset(&attr, 0, sizeof(attr));
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200159again:
160 if (nr_counters == MAX_COUNTERS)
161 return -1;
162
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200163 ret = match_event_symbols(str, &attr);
164 if (ret < 0)
165 return ret;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200166
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200167 attrs[nr_counters] = attr;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200168 nr_counters++;
169
170 str = strstr(str, ",");
171 if (str) {
172 str++;
173 goto again;
174 }
175
176 return 0;
177}
178
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200179/*
180 * Create the help text for the event symbols:
181 */
182void create_events_help(char *events_help_msg)
183{
184 unsigned int i;
185 char *str;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200186
187 str = events_help_msg;
188
189 str += sprintf(str,
190 "event name: [");
191
192 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
193 int type, id;
194
Ingo Molnara21ca2c2009-06-06 09:58:57 +0200195 type = event_symbols[i].type;
196 id = event_symbols[i].config;
Ingo Molnar8ad8db32009-05-26 11:10:09 +0200197
198 if (i)
199 str += sprintf(str, "|");
200
201 str += sprintf(str, "%s",
202 event_symbols[i].symbol);
203 }
204
205 str += sprintf(str, "|rNNN]");
206}