aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/perf_counter
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-06-05 14:22:46 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-06 07:14:47 -0400
commit8326f44da090d6d304d29b9fdc7fb3e20889e329 (patch)
treea15b2a2155c64a327b3cdf1da0997755d49390eb /Documentation/perf_counter
parenta21ca2cac582886a3e95c8bb84ff7c52d4d15e54 (diff)
perf_counter: Implement generalized cache event types
Extend generic event enumeration with the PERF_TYPE_HW_CACHE method. This is a 3-dimensional space: { L1-D, L1-I, L2, ITLB, DTLB, BPU } x { load, store, prefetch } x { accesses, misses } User-space passes in the 3 coordinates and the kernel provides a counter. (if the hardware supports that type and if the combination makes sense.) Combinations that make no sense produce a -EINVAL. Combinations that are not supported by the hardware produce -ENOTSUP. Extend the tools to deal with this, and rewrite the event symbol parsing code with various popular aliases for the units and access methods above. So 'l1-cache-miss' and 'l1d-read-ops' are both valid aliases. ( x86 is supported for now, with the Nehalem event table filled in, and with Core2 and Atom having placeholder tables. ) Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter')
-rw-r--r--Documentation/perf_counter/util/parse-events.c104
1 files changed, 101 insertions, 3 deletions
diff --git a/Documentation/perf_counter/util/parse-events.c b/Documentation/perf_counter/util/parse-events.c
index eb56bd996573..de9a77c47151 100644
--- a/Documentation/perf_counter/util/parse-events.c
+++ b/Documentation/perf_counter/util/parse-events.c
@@ -6,6 +6,8 @@
6#include "exec_cmd.h" 6#include "exec_cmd.h"
7#include "string.h" 7#include "string.h"
8 8
9extern char *strcasestr(const char *haystack, const char *needle);
10
9int nr_counters; 11int nr_counters;
10 12
11struct perf_counter_attr attrs[MAX_COUNTERS]; 13struct perf_counter_attr attrs[MAX_COUNTERS];
@@ -17,6 +19,7 @@ struct event_symbol {
17}; 19};
18 20
19#define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y 21#define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y
22#define CR(x, y) .type = PERF_TYPE_##x, .config = y
20 23
21static struct event_symbol event_symbols[] = { 24static struct event_symbol event_symbols[] = {
22 { C(HARDWARE, CPU_CYCLES), "cpu-cycles", }, 25 { C(HARDWARE, CPU_CYCLES), "cpu-cycles", },
@@ -69,6 +72,28 @@ static char *sw_event_names[] = {
69 "major faults", 72 "major faults",
70}; 73};
71 74
75#define MAX_ALIASES 8
76
77static char *hw_cache [][MAX_ALIASES] = {
78 { "l1-d" , "l1d" , "l1", "l1-data-cache" },
79 { "l1-i" , "l1i" , "l1-instruction-cache" },
80 { "l2" , },
81 { "dtlb", },
82 { "itlb", },
83 { "bpu" , "btb", "branch-cache", NULL },
84};
85
86static char *hw_cache_op [][MAX_ALIASES] = {
87 { "read" , "load" },
88 { "write" , "store" },
89 { "prefetch" , "speculative-read", "speculative-load" },
90};
91
92static char *hw_cache_result [][MAX_ALIASES] = {
93 { "access", "ops" },
94 { "miss", },
95};
96
72char *event_name(int counter) 97char *event_name(int counter)
73{ 98{
74 __u64 config = attrs[counter].config; 99 __u64 config = attrs[counter].config;
@@ -86,6 +111,30 @@ char *event_name(int counter)
86 return hw_event_names[config]; 111 return hw_event_names[config];
87 return "unknown-hardware"; 112 return "unknown-hardware";
88 113
114 case PERF_TYPE_HW_CACHE: {
115 __u8 cache_type, cache_op, cache_result;
116 static char name[100];
117
118 cache_type = (config >> 0) & 0xff;
119 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
120 return "unknown-ext-hardware-cache-type";
121
122 cache_op = (config >> 8) & 0xff;
123 if (cache_type > PERF_COUNT_HW_CACHE_OP_MAX)
124 return "unknown-ext-hardware-cache-op-type";
125
126 cache_result = (config >> 16) & 0xff;
127 if (cache_type > PERF_COUNT_HW_CACHE_RESULT_MAX)
128 return "unknown-ext-hardware-cache-result-type";
129
130 sprintf(name, "%s:%s:%s",
131 hw_cache[cache_type][0],
132 hw_cache_op[cache_op][0],
133 hw_cache_result[cache_result][0]);
134
135 return name;
136 }
137
89 case PERF_TYPE_SOFTWARE: 138 case PERF_TYPE_SOFTWARE:
90 if (config < PERF_SW_EVENTS_MAX) 139 if (config < PERF_SW_EVENTS_MAX)
91 return sw_event_names[config]; 140 return sw_event_names[config];
@@ -98,11 +147,60 @@ char *event_name(int counter)
98 return "unknown"; 147 return "unknown";
99} 148}
100 149
150static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size)
151{
152 int i, j;
153
154 for (i = 0; i < size; i++) {
155 for (j = 0; j < MAX_ALIASES; j++) {
156 if (!names[i][j])
157 break;
158 if (strcasestr(str, names[i][j]))
159 return i;
160 }
161 }
162
163 return 0;
164}
165
166static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
167{
168 __u8 cache_type = -1, cache_op = 0, cache_result = 0;
169
170 cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX);
171 /*
172 * No fallback - if we cannot get a clear cache type
173 * then bail out:
174 */
175 if (cache_type == -1)
176 return -EINVAL;
177
178 cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
179 /*
180 * Fall back to reads:
181 */
182 if (cache_type == -1)
183 cache_type = PERF_COUNT_HW_CACHE_OP_READ;
184
185 cache_result = parse_aliases(str, hw_cache_result,
186 PERF_COUNT_HW_CACHE_RESULT_MAX);
187 /*
188 * Fall back to accesses:
189 */
190 if (cache_result == -1)
191 cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS;
192
193 attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
194 attr->type = PERF_TYPE_HW_CACHE;
195
196 return 0;
197}
198
101/* 199/*
102 * Each event can have multiple symbolic names. 200 * Each event can have multiple symbolic names.
103 * Symbolic names are (almost) exactly matched. 201 * Symbolic names are (almost) exactly matched.
104 */ 202 */
105static int match_event_symbols(const char *str, struct perf_counter_attr *attr) 203static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
106{ 204{
107 __u64 config, id; 205 __u64 config, id;
108 int type; 206 int type;
@@ -147,7 +245,7 @@ static int match_event_symbols(const char *str, struct perf_counter_attr *attr)
147 } 245 }
148 } 246 }
149 247
150 return -EINVAL; 248 return parse_generic_hw_symbols(str, attr);
151} 249}
152 250
153int parse_events(const struct option *opt, const char *str, int unset) 251int parse_events(const struct option *opt, const char *str, int unset)
@@ -160,7 +258,7 @@ again:
160 if (nr_counters == MAX_COUNTERS) 258 if (nr_counters == MAX_COUNTERS)
161 return -1; 259 return -1;
162 260
163 ret = match_event_symbols(str, &attr); 261 ret = parse_event_symbols(str, &attr);
164 if (ret < 0) 262 if (ret < 0)
165 return ret; 263 return ret;
166 264