diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2017-06-30 04:36:42 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-06-30 10:40:20 -0400 |
commit | 65c5e18f9df078f40abd22a3f6983eb9804b6d02 (patch) | |
tree | 5c3cfaa8d39e34970385f9d0adb042807a98e972 | |
parent | 47e780848e6229b102e601deeb1ce571dc69a84a (diff) |
perf script: Add synthesized Intel PT power and ptwrite events
Add definitions for synthesized Intel PT events for power and ptwrite.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/r/1498811802-2301-1-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/builtin-script.c | 114 | ||||
-rw-r--r-- | tools/perf/util/event.h | 118 |
2 files changed, 231 insertions, 1 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index e87b480bbdd0..b458a0cc3544 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -1203,10 +1203,122 @@ static void print_sample_bpf_output(struct perf_sample *sample) | |||
1203 | (char *)(sample->raw_data)); | 1203 | (char *)(sample->raw_data)); |
1204 | } | 1204 | } |
1205 | 1205 | ||
1206 | static void print_sample_synth(struct perf_sample *sample __maybe_unused, | 1206 | static void print_sample_spacing(int len, int spacing) |
1207 | { | ||
1208 | if (len > 0 && len < spacing) | ||
1209 | printf("%*s", spacing - len, ""); | ||
1210 | } | ||
1211 | |||
1212 | static void print_sample_pt_spacing(int len) | ||
1213 | { | ||
1214 | print_sample_spacing(len, 34); | ||
1215 | } | ||
1216 | |||
1217 | static void print_sample_synth_ptwrite(struct perf_sample *sample) | ||
1218 | { | ||
1219 | struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample); | ||
1220 | int len; | ||
1221 | |||
1222 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1223 | return; | ||
1224 | |||
1225 | len = printf(" IP: %u payload: %#" PRIx64 " ", | ||
1226 | data->ip, le64_to_cpu(data->payload)); | ||
1227 | print_sample_pt_spacing(len); | ||
1228 | } | ||
1229 | |||
1230 | static void print_sample_synth_mwait(struct perf_sample *sample) | ||
1231 | { | ||
1232 | struct perf_synth_intel_mwait *data = perf_sample__synth_ptr(sample); | ||
1233 | int len; | ||
1234 | |||
1235 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1236 | return; | ||
1237 | |||
1238 | len = printf(" hints: %#x extensions: %#x ", | ||
1239 | data->hints, data->extensions); | ||
1240 | print_sample_pt_spacing(len); | ||
1241 | } | ||
1242 | |||
1243 | static void print_sample_synth_pwre(struct perf_sample *sample) | ||
1244 | { | ||
1245 | struct perf_synth_intel_pwre *data = perf_sample__synth_ptr(sample); | ||
1246 | int len; | ||
1247 | |||
1248 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1249 | return; | ||
1250 | |||
1251 | len = printf(" hw: %u cstate: %u sub-cstate: %u ", | ||
1252 | data->hw, data->cstate, data->subcstate); | ||
1253 | print_sample_pt_spacing(len); | ||
1254 | } | ||
1255 | |||
1256 | static void print_sample_synth_exstop(struct perf_sample *sample) | ||
1257 | { | ||
1258 | struct perf_synth_intel_exstop *data = perf_sample__synth_ptr(sample); | ||
1259 | int len; | ||
1260 | |||
1261 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1262 | return; | ||
1263 | |||
1264 | len = printf(" IP: %u ", data->ip); | ||
1265 | print_sample_pt_spacing(len); | ||
1266 | } | ||
1267 | |||
1268 | static void print_sample_synth_pwrx(struct perf_sample *sample) | ||
1269 | { | ||
1270 | struct perf_synth_intel_pwrx *data = perf_sample__synth_ptr(sample); | ||
1271 | int len; | ||
1272 | |||
1273 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1274 | return; | ||
1275 | |||
1276 | len = printf(" deepest cstate: %u last cstate: %u wake reason: %#x ", | ||
1277 | data->deepest_cstate, data->last_cstate, | ||
1278 | data->wake_reason); | ||
1279 | print_sample_pt_spacing(len); | ||
1280 | } | ||
1281 | |||
1282 | static void print_sample_synth_cbr(struct perf_sample *sample) | ||
1283 | { | ||
1284 | struct perf_synth_intel_cbr *data = perf_sample__synth_ptr(sample); | ||
1285 | unsigned int percent, freq; | ||
1286 | int len; | ||
1287 | |||
1288 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1289 | return; | ||
1290 | |||
1291 | freq = (le32_to_cpu(data->freq) + 500) / 1000; | ||
1292 | len = printf(" cbr: %2u freq: %4u MHz ", data->cbr, freq); | ||
1293 | if (data->max_nonturbo) { | ||
1294 | percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10; | ||
1295 | len += printf("(%3u%%) ", percent); | ||
1296 | } | ||
1297 | print_sample_pt_spacing(len); | ||
1298 | } | ||
1299 | |||
1300 | static void print_sample_synth(struct perf_sample *sample, | ||
1207 | struct perf_evsel *evsel) | 1301 | struct perf_evsel *evsel) |
1208 | { | 1302 | { |
1209 | switch (evsel->attr.config) { | 1303 | switch (evsel->attr.config) { |
1304 | case PERF_SYNTH_INTEL_PTWRITE: | ||
1305 | print_sample_synth_ptwrite(sample); | ||
1306 | break; | ||
1307 | case PERF_SYNTH_INTEL_MWAIT: | ||
1308 | print_sample_synth_mwait(sample); | ||
1309 | break; | ||
1310 | case PERF_SYNTH_INTEL_PWRE: | ||
1311 | print_sample_synth_pwre(sample); | ||
1312 | break; | ||
1313 | case PERF_SYNTH_INTEL_EXSTOP: | ||
1314 | print_sample_synth_exstop(sample); | ||
1315 | break; | ||
1316 | case PERF_SYNTH_INTEL_PWRX: | ||
1317 | print_sample_synth_pwrx(sample); | ||
1318 | break; | ||
1319 | case PERF_SYNTH_INTEL_CBR: | ||
1320 | print_sample_synth_cbr(sample); | ||
1321 | break; | ||
1210 | default: | 1322 | default: |
1211 | break; | 1323 | break; |
1212 | } | 1324 | } |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 855733c2adcf..9967c87af7a6 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -255,6 +255,124 @@ enum auxtrace_error_type { | |||
255 | /* Attribute type for custom synthesized events */ | 255 | /* Attribute type for custom synthesized events */ |
256 | #define PERF_TYPE_SYNTH (INT_MAX + 1U) | 256 | #define PERF_TYPE_SYNTH (INT_MAX + 1U) |
257 | 257 | ||
258 | /* Attribute config for custom synthesized events */ | ||
259 | enum perf_synth_id { | ||
260 | PERF_SYNTH_INTEL_PTWRITE, | ||
261 | PERF_SYNTH_INTEL_MWAIT, | ||
262 | PERF_SYNTH_INTEL_PWRE, | ||
263 | PERF_SYNTH_INTEL_EXSTOP, | ||
264 | PERF_SYNTH_INTEL_PWRX, | ||
265 | PERF_SYNTH_INTEL_CBR, | ||
266 | }; | ||
267 | |||
268 | /* | ||
269 | * Raw data formats for synthesized events. Note that 4 bytes of padding are | ||
270 | * present to match the 'size' member of PERF_SAMPLE_RAW data which is always | ||
271 | * 8-byte aligned. That means we must dereference raw_data with an offset of 4. | ||
272 | * Refer perf_sample__synth_ptr() and perf_synth__raw_data(). It also means the | ||
273 | * structure sizes are 4 bytes bigger than the raw_size, refer | ||
274 | * perf_synth__raw_size(). | ||
275 | */ | ||
276 | |||
277 | struct perf_synth_intel_ptwrite { | ||
278 | u32 padding; | ||
279 | union { | ||
280 | struct { | ||
281 | u32 ip : 1, | ||
282 | reserved : 31; | ||
283 | }; | ||
284 | u32 flags; | ||
285 | }; | ||
286 | u64 payload; | ||
287 | }; | ||
288 | |||
289 | struct perf_synth_intel_mwait { | ||
290 | u32 padding; | ||
291 | u32 reserved; | ||
292 | union { | ||
293 | struct { | ||
294 | u64 hints : 8, | ||
295 | reserved1 : 24, | ||
296 | extensions : 2, | ||
297 | reserved2 : 30; | ||
298 | }; | ||
299 | u64 payload; | ||
300 | }; | ||
301 | }; | ||
302 | |||
303 | struct perf_synth_intel_pwre { | ||
304 | u32 padding; | ||
305 | u32 reserved; | ||
306 | union { | ||
307 | struct { | ||
308 | u64 reserved1 : 7, | ||
309 | hw : 1, | ||
310 | subcstate : 4, | ||
311 | cstate : 4, | ||
312 | reserved2 : 48; | ||
313 | }; | ||
314 | u64 payload; | ||
315 | }; | ||
316 | }; | ||
317 | |||
318 | struct perf_synth_intel_exstop { | ||
319 | u32 padding; | ||
320 | union { | ||
321 | struct { | ||
322 | u32 ip : 1, | ||
323 | reserved : 31; | ||
324 | }; | ||
325 | u32 flags; | ||
326 | }; | ||
327 | }; | ||
328 | |||
329 | struct perf_synth_intel_pwrx { | ||
330 | u32 padding; | ||
331 | u32 reserved; | ||
332 | union { | ||
333 | struct { | ||
334 | u64 deepest_cstate : 4, | ||
335 | last_cstate : 4, | ||
336 | wake_reason : 4, | ||
337 | reserved1 : 52; | ||
338 | }; | ||
339 | u64 payload; | ||
340 | }; | ||
341 | }; | ||
342 | |||
343 | struct perf_synth_intel_cbr { | ||
344 | u32 padding; | ||
345 | union { | ||
346 | struct { | ||
347 | u32 cbr : 8, | ||
348 | reserved1 : 8, | ||
349 | max_nonturbo : 8, | ||
350 | reserved2 : 8; | ||
351 | }; | ||
352 | u32 flags; | ||
353 | }; | ||
354 | u32 freq; | ||
355 | u32 reserved3; | ||
356 | }; | ||
357 | |||
358 | /* | ||
359 | * raw_data is always 4 bytes from an 8-byte boundary, so subtract 4 to get | ||
360 | * 8-byte alignment. | ||
361 | */ | ||
362 | static inline void *perf_sample__synth_ptr(struct perf_sample *sample) | ||
363 | { | ||
364 | return sample->raw_data - 4; | ||
365 | } | ||
366 | |||
367 | static inline void *perf_synth__raw_data(void *p) | ||
368 | { | ||
369 | return p + 4; | ||
370 | } | ||
371 | |||
372 | #define perf_synth__raw_size(d) (sizeof(d) - 4) | ||
373 | |||
374 | #define perf_sample__bad_synth_size(s, d) ((s)->raw_size < sizeof(d) - 4) | ||
375 | |||
258 | /* | 376 | /* |
259 | * The kernel collects the number of events it couldn't send in a stretch and | 377 | * The kernel collects the number of events it couldn't send in a stretch and |
260 | * when possible sends this number in a PERF_RECORD_LOST event. The number of | 378 | * when possible sends this number in a PERF_RECORD_LOST event. The number of |