Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf/x86/intel/pt: Add new timing packet enables

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>

authored by

Alexander Shishkin and committed by
Ingo Molnar
b1bf72d6 9a6694cf

+81 -1
+8
arch/x86/include/asm/msr-index.h
··· 80 80 81 81 #define MSR_IA32_RTIT_CTL 0x00000570 82 82 #define RTIT_CTL_TRACEEN BIT(0) 83 + #define RTIT_CTL_CYCLEACC BIT(1) 83 84 #define RTIT_CTL_OS BIT(2) 84 85 #define RTIT_CTL_USR BIT(3) 85 86 #define RTIT_CTL_CR3EN BIT(7) 86 87 #define RTIT_CTL_TOPA BIT(8) 88 + #define RTIT_CTL_MTC_EN BIT(9) 87 89 #define RTIT_CTL_TSC_EN BIT(10) 88 90 #define RTIT_CTL_DISRETC BIT(11) 89 91 #define RTIT_CTL_BRANCH_EN BIT(13) 92 + #define RTIT_CTL_MTC_RANGE_OFFSET 14 93 + #define RTIT_CTL_MTC_RANGE (0x0full << RTIT_CTL_MTC_RANGE_OFFSET) 94 + #define RTIT_CTL_CYC_THRESH_OFFSET 19 95 + #define RTIT_CTL_CYC_THRESH (0x0full << RTIT_CTL_CYC_THRESH_OFFSET) 96 + #define RTIT_CTL_PSB_FREQ_OFFSET 24 97 + #define RTIT_CTL_PSB_FREQ (0x0full << RTIT_CTL_PSB_FREQ_OFFSET) 90 98 #define MSR_IA32_RTIT_STATUS 0x00000571 91 99 #define RTIT_STATUS_CONTEXTEN BIT(1) 92 100 #define RTIT_STATUS_TRIGGEREN BIT(2)
+6
arch/x86/kernel/cpu/intel_pt.h
··· 72 72 enum pt_capabilities { 73 73 PT_CAP_max_subleaf = 0, 74 74 PT_CAP_cr3_filtering, 75 + PT_CAP_psb_cyc, 76 + PT_CAP_mtc, 75 77 PT_CAP_topa_output, 76 78 PT_CAP_topa_multiple_entries, 79 + PT_CAP_single_range_output, 77 80 PT_CAP_payloads_lip, 81 + PT_CAP_mtc_periods, 82 + PT_CAP_cycle_thresholds, 83 + PT_CAP_psb_periods, 78 84 }; 79 85 80 86 struct pt_pmu {
+67 -1
arch/x86/kernel/cpu/perf_event_intel_pt.c
··· 65 65 } pt_caps[] = { 66 66 PT_CAP(max_subleaf, 0, CR_EAX, 0xffffffff), 67 67 PT_CAP(cr3_filtering, 0, CR_EBX, BIT(0)), 68 + PT_CAP(psb_cyc, 0, CR_EBX, BIT(1)), 69 + PT_CAP(mtc, 0, CR_EBX, BIT(3)), 68 70 PT_CAP(topa_output, 0, CR_ECX, BIT(0)), 69 71 PT_CAP(topa_multiple_entries, 0, CR_ECX, BIT(1)), 72 + PT_CAP(single_range_output, 0, CR_ECX, BIT(2)), 70 73 PT_CAP(payloads_lip, 0, CR_ECX, BIT(31)), 74 + PT_CAP(mtc_periods, 1, CR_EAX, 0xffff0000), 75 + PT_CAP(cycle_thresholds, 1, CR_EBX, 0xffff), 76 + PT_CAP(psb_periods, 1, CR_EBX, 0xffff0000), 71 77 }; 72 78 73 79 static u32 pt_cap_get(enum pt_capabilities cap) ··· 100 94 .name = "caps", 101 95 }; 102 96 97 + PMU_FORMAT_ATTR(cyc, "config:1" ); 98 + PMU_FORMAT_ATTR(mtc, "config:9" ); 103 99 PMU_FORMAT_ATTR(tsc, "config:10" ); 104 100 PMU_FORMAT_ATTR(noretcomp, "config:11" ); 101 + PMU_FORMAT_ATTR(mtc_period, "config:14-17" ); 102 + PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" ); 103 + PMU_FORMAT_ATTR(psb_period, "config:24-27" ); 105 104 106 105 static struct attribute *pt_formats_attr[] = { 106 + &format_attr_cyc.attr, 107 + &format_attr_mtc.attr, 107 108 &format_attr_tsc.attr, 108 109 &format_attr_noretcomp.attr, 110 + &format_attr_mtc_period.attr, 111 + &format_attr_cyc_thresh.attr, 112 + &format_attr_psb_period.attr, 109 113 NULL, 110 114 }; 111 115 ··· 186 170 return ret; 187 171 } 188 172 189 - #define PT_CONFIG_MASK (RTIT_CTL_TSC_EN | RTIT_CTL_DISRETC) 173 + #define RTIT_CTL_CYC_PSB (RTIT_CTL_CYCLEACC | \ 174 + RTIT_CTL_CYC_THRESH | \ 175 + RTIT_CTL_PSB_FREQ) 176 + 177 + #define RTIT_CTL_MTC (RTIT_CTL_MTC_EN | \ 178 + RTIT_CTL_MTC_RANGE) 179 + 180 + #define PT_CONFIG_MASK (RTIT_CTL_TSC_EN | \ 181 + RTIT_CTL_DISRETC | \ 182 + RTIT_CTL_CYC_PSB | \ 183 + RTIT_CTL_MTC) 190 184 191 185 static bool pt_event_valid(struct perf_event *event) 192 186 { 193 187 u64 config = event->attr.config; 188 + u64 allowed, requested; 194 189 195 190 if ((config & PT_CONFIG_MASK) != config) 196 191 return false; 192 + 193 + if (config & RTIT_CTL_CYC_PSB) { 194 + if (!pt_cap_get(PT_CAP_psb_cyc)) 195 + return false; 196 + 197 + allowed = pt_cap_get(PT_CAP_psb_periods); 198 + requested = (config & RTIT_CTL_PSB_FREQ) >> 199 + RTIT_CTL_PSB_FREQ_OFFSET; 200 + if (requested && (!(allowed & BIT(requested)))) 201 + return false; 202 + 203 + allowed = pt_cap_get(PT_CAP_cycle_thresholds); 204 + requested = (config & RTIT_CTL_CYC_THRESH) >> 205 + RTIT_CTL_CYC_THRESH_OFFSET; 206 + if (requested && (!(allowed & BIT(requested)))) 207 + return false; 208 + } 209 + 210 + if (config & RTIT_CTL_MTC) { 211 + /* 212 + * In the unlikely case that CPUID lists valid mtc periods, 213 + * but not the mtc capability, drop out here. 214 + * 215 + * Spec says that setting mtc period bits while mtc bit in 216 + * CPUID is 0 will #GP, so better safe than sorry. 217 + */ 218 + if (!pt_cap_get(PT_CAP_mtc)) 219 + return false; 220 + 221 + allowed = pt_cap_get(PT_CAP_mtc_periods); 222 + if (!allowed) 223 + return false; 224 + 225 + requested = (config & RTIT_CTL_MTC_RANGE) >> 226 + RTIT_CTL_MTC_RANGE_OFFSET; 227 + 228 + if (!(allowed & BIT(requested))) 229 + return false; 230 + } 197 231 198 232 return true; 199 233 }