Add definitions for synthesized Intel PT events for power and ptwrite.

Signed-off-by: Adrian Hunter <adrian.hun...@intel.com>
---
 tools/perf/builtin-script.c | 114 +++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/event.h     |  90 ++++++++++++++++++++++++++++++++++
 2 files changed, 203 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index f7a5130d2fd0..4a13daacba25 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1120,10 +1120,122 @@ static void print_sample_bpf_output(struct perf_sample 
*sample)
                       (char *)(sample->raw_data));
 }
 
-static void print_sample_synth(struct perf_sample *sample __maybe_unused,
+static void print_sample_spacing(int len, int spacing)
+{
+       if (len > 0 && len < spacing)
+               printf("%*s", spacing - len, "");
+}
+
+static void print_sample_pt_spacing(int len)
+{
+       print_sample_spacing(len, 34);
+}
+
+static void print_sample_synth_ptwrite(struct perf_sample *sample)
+{
+       struct perf_synth_intel_ptwrite *data = sample->raw_data;
+       int len;
+
+       if (sample->raw_size < sizeof(*data))
+               return;
+
+       len = printf(" IP: %u payload: %#" PRIx64 " ",
+                    data->ip, le64_to_cpu(data->payload));
+       print_sample_pt_spacing(len);
+}
+
+static void print_sample_synth_mwait(struct perf_sample *sample)
+{
+       struct perf_synth_intel_mwait *data = sample->raw_data;
+       int len;
+
+       if (sample->raw_size < sizeof(*data))
+               return;
+
+       len = printf(" hints: %#x extensions: %#x ",
+                    data->hints, data->extensions);
+       print_sample_pt_spacing(len);
+}
+
+static void print_sample_synth_pwre(struct perf_sample *sample)
+{
+       struct perf_synth_intel_pwre *data = sample->raw_data;
+       int len;
+
+       if (sample->raw_size < sizeof(*data))
+               return;
+
+       len = printf(" hw: %u cstate: %u sub-cstate: %u ",
+                    data->hw, data->cstate, data->subcstate);
+       print_sample_pt_spacing(len);
+}
+
+static void print_sample_synth_exstop(struct perf_sample *sample)
+{
+       struct perf_synth_intel_exstop *data = sample->raw_data;
+       int len;
+
+       if (sample->raw_size < sizeof(*data))
+               return;
+
+       len = printf(" IP: %u ", data->ip);
+       print_sample_pt_spacing(len);
+}
+
+static void print_sample_synth_pwrx(struct perf_sample *sample)
+{
+       struct perf_synth_intel_pwrx *data = sample->raw_data;
+       int len;
+
+       if (sample->raw_size < sizeof(*data))
+               return;
+
+       len = printf(" deepest cstate: %u last cstate: %u wake reason: %#x ",
+                    data->deepest_cstate, data->last_cstate,
+                    data->wake_reason);
+       print_sample_pt_spacing(len);
+}
+
+static void print_sample_synth_cbr(struct perf_sample *sample)
+{
+       struct perf_synth_intel_cbr *data = sample->raw_data;
+       unsigned int percent, freq;
+       int len;
+
+       if (sample->raw_size < sizeof(*data))
+               return;
+
+       freq = (le32_to_cpu(data->freq) + 500) / 1000;
+       len = printf(" cbr: %2u freq: %4u MHz ", data->cbr, freq);
+       if (data->max_nonturbo) {
+               percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10;
+               len += printf("(%3u%%) ", percent);
+       }
+       print_sample_pt_spacing(len);
+}
+
+static void print_sample_synth(struct perf_sample *sample,
                               struct perf_evsel *evsel)
 {
        switch (evsel->attr.config) {
+       case PERF_SYNTH_INTEL_PTWRITE:
+               print_sample_synth_ptwrite(sample);
+               break;
+       case PERF_SYNTH_INTEL_MWAIT:
+               print_sample_synth_mwait(sample);
+               break;
+       case PERF_SYNTH_INTEL_PWRE:
+               print_sample_synth_pwre(sample);
+               break;
+       case PERF_SYNTH_INTEL_EXSTOP:
+               print_sample_synth_exstop(sample);
+               break;
+       case PERF_SYNTH_INTEL_PWRX:
+               print_sample_synth_pwrx(sample);
+               break;
+       case PERF_SYNTH_INTEL_CBR:
+               print_sample_synth_cbr(sample);
+               break;
        default:
                break;
        }
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index af285ed951f4..7823d43315b7 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -255,6 +255,96 @@ enum auxtrace_error_type {
 /* Attribute type for custom synthesized events */
 #define PERF_TYPE_SYNTH                3000000000
 
+/* Attribute config for custom synthesized events */
+enum perf_synth_id {
+       PERF_SYNTH_INTEL_PTWRITE,
+       PERF_SYNTH_INTEL_MWAIT,
+       PERF_SYNTH_INTEL_PWRE,
+       PERF_SYNTH_INTEL_EXSTOP,
+       PERF_SYNTH_INTEL_PWRX,
+       PERF_SYNTH_INTEL_CBR,
+};
+
+/*
+ * Raw data formats for synthesized events. Note that raw data plus the raw 
data
+ * size (4 bytes) must align to 8-bytes.
+ */
+
+struct perf_synth_intel_ptwrite {
+       union {
+               struct {
+                       u32     ip              :  1,
+                               reserved        : 31;
+               };
+               u32     flags;
+       };
+       u64     payload;
+} __packed;
+
+struct perf_synth_intel_mwait {
+       u32 reserved;
+       union {
+               struct {
+                       u64     hints           :  8,
+                               reserved1       : 24,
+                               extensions      :  2,
+                               reserved2       : 30;
+               };
+               u64     payload;
+       };
+} __packed;
+
+struct perf_synth_intel_pwre {
+       u32 reserved;
+       union {
+               struct {
+                       u64     reserved1       :  7,
+                               hw              :  1,
+                               subcstate       :  4,
+                               cstate          :  4,
+                               reserved2       : 48;
+               };
+               u64     payload;
+       };
+} __packed;
+
+struct perf_synth_intel_exstop {
+       union {
+               struct {
+                       u32     ip              :  1,
+                               reserved        : 31;
+               };
+               u32     flags;
+       };
+};
+
+struct perf_synth_intel_pwrx {
+       u32 reserved;
+       union {
+               struct {
+                       u64     deepest_cstate  :  4,
+                               last_cstate     :  4,
+                               wake_reason     :  4,
+                               reserved1       : 52;
+               };
+               u64     payload;
+       };
+} __packed;
+
+struct perf_synth_intel_cbr {
+       union {
+               struct {
+                       u32     cbr             :  8,
+                               reserved1       :  8,
+                               max_nonturbo    :  8,
+                               reserved2       :  8;
+               };
+               u32     flags;
+       };
+       u32 freq;
+       u32 reserved3;
+};
+
 /*
  * The kernel collects the number of events it couldn't send in a stretch and
  * when possible sends this number in a PERF_RECORD_LOST event. The number of
-- 
1.9.1

Reply via email to