perf/x86/intel/pt: Add new timing packet enables
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>
Thu, 30 Jul 2015 13:15:31 +0000 (16:15 +0300)
committerIngo Molnar <mingo@kernel.org>
Tue, 4 Aug 2015 08:16:55 +0000 (10:16 +0200)
Intel PT chapter in the new Intel Architecture SDM adds several packets
corresponding enable bits and registers that control packet generation.
Also, additional bits in the Intel PT CPUID leaf were added to enumerate
presence and parameters of these new packets and features.

The packets and enables are:

  * CYC: cycle accurate mode, provides the number of cycles elapsed since
    previous CYC packet; its presence and available threshold values are
    enumerated via CPUID;

  * MTC: mini time counter packets, used for tracking TSC time between
    full TSC packets; its presence and available resolution options are
    enumerated via CPUID;

  * PSB packet period is now configurable, available period values are
    enumerated via CPUID.

This patch adds corresponding bit and register definitions, pmu driver
capabilities based on CPUID enumeration, new attribute format bits for
the new featurens and extends event configuration validation function
to take these into account.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: acme@infradead.org
Cc: adrian.hunter@intel.com
Cc: hpa@zytor.com
Link: http://lkml.kernel.org/r/1438262131-12725-1-git-send-email-alexander.shishkin@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/include/asm/msr-index.h
arch/x86/kernel/cpu/intel_pt.h
arch/x86/kernel/cpu/perf_event_intel_pt.c

index 9ebc3d0093736bcc2e62646a89fbac1f75c878d7..c665d34f7285df293e6d9d66656e4f2a600d4f86 100644 (file)
 
 #define MSR_IA32_RTIT_CTL              0x00000570
 #define RTIT_CTL_TRACEEN               BIT(0)
+#define RTIT_CTL_CYCLEACC              BIT(1)
 #define RTIT_CTL_OS                    BIT(2)
 #define RTIT_CTL_USR                   BIT(3)
 #define RTIT_CTL_CR3EN                 BIT(7)
 #define RTIT_CTL_TOPA                  BIT(8)
+#define RTIT_CTL_MTC_EN                        BIT(9)
 #define RTIT_CTL_TSC_EN                        BIT(10)
 #define RTIT_CTL_DISRETC               BIT(11)
 #define RTIT_CTL_BRANCH_EN             BIT(13)
+#define RTIT_CTL_MTC_RANGE_OFFSET      14
+#define RTIT_CTL_MTC_RANGE             (0x0full << RTIT_CTL_MTC_RANGE_OFFSET)
+#define RTIT_CTL_CYC_THRESH_OFFSET     19
+#define RTIT_CTL_CYC_THRESH            (0x0full << RTIT_CTL_CYC_THRESH_OFFSET)
+#define RTIT_CTL_PSB_FREQ_OFFSET       24
+#define RTIT_CTL_PSB_FREQ                      (0x0full << RTIT_CTL_PSB_FREQ_OFFSET)
 #define MSR_IA32_RTIT_STATUS           0x00000571
 #define RTIT_STATUS_CONTEXTEN          BIT(1)
 #define RTIT_STATUS_TRIGGEREN          BIT(2)
index 1c338b0eba050d3fc2272b92a6f11f5fcf42539f..feb293e9653162b98738f4db7c8073f02f3a22e8 100644 (file)
@@ -72,9 +72,15 @@ struct topa_entry {
 enum pt_capabilities {
        PT_CAP_max_subleaf = 0,
        PT_CAP_cr3_filtering,
+       PT_CAP_psb_cyc,
+       PT_CAP_mtc,
        PT_CAP_topa_output,
        PT_CAP_topa_multiple_entries,
+       PT_CAP_single_range_output,
        PT_CAP_payloads_lip,
+       PT_CAP_mtc_periods,
+       PT_CAP_cycle_thresholds,
+       PT_CAP_psb_periods,
 };
 
 struct pt_pmu {
index cc58ef8d9ada6dcc0790f493e9e47b216946517c..e20cfacb5a32cb54671d50b507737420c403ef23 100644 (file)
@@ -65,9 +65,15 @@ static struct pt_cap_desc {
 } pt_caps[] = {
        PT_CAP(max_subleaf,             0, CR_EAX, 0xffffffff),
        PT_CAP(cr3_filtering,           0, CR_EBX, BIT(0)),
+       PT_CAP(psb_cyc,                 0, CR_EBX, BIT(1)),
+       PT_CAP(mtc,                     0, CR_EBX, BIT(3)),
        PT_CAP(topa_output,             0, CR_ECX, BIT(0)),
        PT_CAP(topa_multiple_entries,   0, CR_ECX, BIT(1)),
+       PT_CAP(single_range_output,     0, CR_ECX, BIT(2)),
        PT_CAP(payloads_lip,            0, CR_ECX, BIT(31)),
+       PT_CAP(mtc_periods,             1, CR_EAX, 0xffff0000),
+       PT_CAP(cycle_thresholds,        1, CR_EBX, 0xffff),
+       PT_CAP(psb_periods,             1, CR_EBX, 0xffff0000),
 };
 
 static u32 pt_cap_get(enum pt_capabilities cap)
@@ -94,12 +100,22 @@ static struct attribute_group pt_cap_group = {
        .name   = "caps",
 };
 
+PMU_FORMAT_ATTR(cyc,           "config:1"      );
+PMU_FORMAT_ATTR(mtc,           "config:9"      );
 PMU_FORMAT_ATTR(tsc,           "config:10"     );
 PMU_FORMAT_ATTR(noretcomp,     "config:11"     );
+PMU_FORMAT_ATTR(mtc_period,    "config:14-17"  );
+PMU_FORMAT_ATTR(cyc_thresh,    "config:19-22"  );
+PMU_FORMAT_ATTR(psb_period,    "config:24-27"  );
 
 static struct attribute *pt_formats_attr[] = {
+       &format_attr_cyc.attr,
+       &format_attr_mtc.attr,
        &format_attr_tsc.attr,
        &format_attr_noretcomp.attr,
+       &format_attr_mtc_period.attr,
+       &format_attr_cyc_thresh.attr,
+       &format_attr_psb_period.attr,
        NULL,
 };
 
@@ -170,15 +186,65 @@ fail:
        return ret;
 }
 
-#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN | RTIT_CTL_DISRETC)
+#define RTIT_CTL_CYC_PSB (RTIT_CTL_CYCLEACC    | \
+                         RTIT_CTL_CYC_THRESH   | \
+                         RTIT_CTL_PSB_FREQ)
+
+#define RTIT_CTL_MTC   (RTIT_CTL_MTC_EN        | \
+                        RTIT_CTL_MTC_RANGE)
+
+#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN                | \
+                       RTIT_CTL_DISRETC        | \
+                       RTIT_CTL_CYC_PSB        | \
+                       RTIT_CTL_MTC)
 
 static bool pt_event_valid(struct perf_event *event)
 {
        u64 config = event->attr.config;
+       u64 allowed, requested;
 
        if ((config & PT_CONFIG_MASK) != config)
                return false;
 
+       if (config & RTIT_CTL_CYC_PSB) {
+               if (!pt_cap_get(PT_CAP_psb_cyc))
+                       return false;
+
+               allowed = pt_cap_get(PT_CAP_psb_periods);
+               requested = (config & RTIT_CTL_PSB_FREQ) >>
+                       RTIT_CTL_PSB_FREQ_OFFSET;
+               if (requested && (!(allowed & BIT(requested))))
+                       return false;
+
+               allowed = pt_cap_get(PT_CAP_cycle_thresholds);
+               requested = (config & RTIT_CTL_CYC_THRESH) >>
+                       RTIT_CTL_CYC_THRESH_OFFSET;
+               if (requested && (!(allowed & BIT(requested))))
+                       return false;
+       }
+
+       if (config & RTIT_CTL_MTC) {
+               /*
+                * In the unlikely case that CPUID lists valid mtc periods,
+                * but not the mtc capability, drop out here.
+                *
+                * Spec says that setting mtc period bits while mtc bit in
+                * CPUID is 0 will #GP, so better safe than sorry.
+                */
+               if (!pt_cap_get(PT_CAP_mtc))
+                       return false;
+
+               allowed = pt_cap_get(PT_CAP_mtc_periods);
+               if (!allowed)
+                       return false;
+
+               requested = (config & RTIT_CTL_MTC_RANGE) >>
+                       RTIT_CTL_MTC_RANGE_OFFSET;
+
+               if (!(allowed & BIT(requested)))
+                       return false;
+       }
+
        return true;
 }