]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
perf intel-pt: Fix IPC with CYC threshold
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 5 Feb 2021 17:53:49 +0000 (19:53 +0200)
committerAndrea Righi <andrea.righi@canonical.com>
Mon, 15 Mar 2021 14:09:28 +0000 (15:09 +0100)
[ Upstream commit 6af4b60033e0ce0332fcdf256c965ad41942821a ]

The code assumed every CYC-eligible packet has a CYC packet, which is not
the case when CYC thresholds are used. Fix by checking if a CYC packet is
actually present in that case.

Fixes: 5b1dc0fd1da06 ("perf intel-pt: Add support for samples to contain IPC ratio")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: https://lore.kernel.org/r/20210205175350.23817-4-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
tools/perf/util/intel-pt.c

index ef29f6b25e60aa99a68d561396d3ab3b9a3a3684..197eb58a39cb7748bb4ff9fea06c1a2dead1d61f 100644 (file)
 #include "intel-pt-decoder.h"
 #include "intel-pt-log.h"
 
+#define BITULL(x) (1ULL << (x))
+
+/* IA32_RTIT_CTL MSR bits */
+#define INTEL_PT_CYC_ENABLE            BITULL(1)
+#define INTEL_PT_CYC_THRESHOLD         (BITULL(22) | BITULL(21) | BITULL(20) | BITULL(19))
+#define INTEL_PT_CYC_THRESHOLD_SHIFT   19
+
 #define INTEL_PT_BLK_SIZE 1024
 
 #define BIT63 (((uint64_t)1 << 63))
@@ -167,6 +174,8 @@ struct intel_pt_decoder {
        uint64_t sample_tot_cyc_cnt;
        uint64_t base_cyc_cnt;
        uint64_t cyc_cnt_timestamp;
+       uint64_t ctl;
+       uint64_t cyc_threshold;
        double tsc_to_cyc;
        bool continuous_period;
        bool overflow;
@@ -204,6 +213,14 @@ static uint64_t intel_pt_lower_power_of_2(uint64_t x)
        return x << i;
 }
 
+static uint64_t intel_pt_cyc_threshold(uint64_t ctl)
+{
+       if (!(ctl & INTEL_PT_CYC_ENABLE))
+               return 0;
+
+       return (ctl & INTEL_PT_CYC_THRESHOLD) >> INTEL_PT_CYC_THRESHOLD_SHIFT;
+}
+
 static void intel_pt_setup_period(struct intel_pt_decoder *decoder)
 {
        if (decoder->period_type == INTEL_PT_PERIOD_TICKS) {
@@ -245,12 +262,15 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
 
        decoder->flags              = params->flags;
 
+       decoder->ctl                = params->ctl;
        decoder->period             = params->period;
        decoder->period_type        = params->period_type;
 
        decoder->max_non_turbo_ratio    = params->max_non_turbo_ratio;
        decoder->max_non_turbo_ratio_fp = params->max_non_turbo_ratio;
 
+       decoder->cyc_threshold = intel_pt_cyc_threshold(decoder->ctl);
+
        intel_pt_setup_period(decoder);
 
        decoder->mtc_shift = params->mtc_period;
@@ -2017,6 +2037,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in
 
 static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
 {
+       int last_packet_type = INTEL_PT_PAD;
        bool no_tip = false;
        int err;
 
@@ -2025,6 +2046,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
                if (err)
                        return err;
 next:
+               if (decoder->cyc_threshold) {
+                       if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC)
+                               decoder->sample_cyc = false;
+                       last_packet_type = decoder->packet.type;
+               }
+
                if (decoder->hop) {
                        switch (intel_pt_hop_trace(decoder, &no_tip, &err)) {
                        case HOP_IGNORE:
index b52937b03c8c829606e3eebf54a65a199bbf6e0e..48adaa78acfc20fcdb62ab2ba0e9576fb88b8143 100644 (file)
@@ -244,6 +244,7 @@ struct intel_pt_params {
        void *data;
        bool return_compression;
        bool branch_enable;
+       uint64_t ctl;
        uint64_t period;
        enum intel_pt_period_type period_type;
        unsigned max_non_turbo_ratio;
index d6d93ee0301906d1500b2db71c3ac8ac3cca4ecf..2fff6f760457fb511aea7b898b7bdcc1338d5c82 100644 (file)
@@ -893,6 +893,18 @@ static bool intel_pt_sampling_mode(struct intel_pt *pt)
        return false;
 }
 
+static u64 intel_pt_ctl(struct intel_pt *pt)
+{
+       struct evsel *evsel;
+       u64 config;
+
+       evlist__for_each_entry(pt->session->evlist, evsel) {
+               if (intel_pt_get_config(pt, &evsel->core.attr, &config))
+                       return config;
+       }
+       return 0;
+}
+
 static u64 intel_pt_ns_to_ticks(const struct intel_pt *pt, u64 ns)
 {
        u64 quot, rem;
@@ -1026,6 +1038,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
        params.data = ptq;
        params.return_compression = intel_pt_return_compression(pt);
        params.branch_enable = intel_pt_branch_enable(pt);
+       params.ctl = intel_pt_ctl(pt);
        params.max_non_turbo_ratio = pt->max_non_turbo_ratio;
        params.mtc_period = intel_pt_mtc_period(pt);
        params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;