diff options
| -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, | ||
