aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/events/core.c34
-rw-r--r--arch/x86/events/intel/core.c18
-rw-r--r--arch/x86/events/intel/ds.c51
-rw-r--r--arch/x86/events/intel/pt.c5
-rw-r--r--arch/x86/events/perf_event.h17
-rw-r--r--arch/x86/include/asm/intel_pt.h2
-rw-r--r--arch/x86/include/asm/msr-index.h4
7 files changed, 130 insertions, 1 deletions
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 325959d19d9a..15b90b1a8fb1 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1005,6 +1005,27 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,
1005 1005
1006 /* current number of events already accepted */ 1006 /* current number of events already accepted */
1007 n = cpuc->n_events; 1007 n = cpuc->n_events;
1008 if (!cpuc->n_events)
1009 cpuc->pebs_output = 0;
1010
1011 if (!cpuc->is_fake && leader->attr.precise_ip) {
1012 /*
1013 * For PEBS->PT, if !aux_event, the group leader (PT) went
1014 * away, the group was broken down and this singleton event
1015 * can't schedule any more.
1016 */
1017 if (is_pebs_pt(leader) && !leader->aux_event)
1018 return -EINVAL;
1019
1020 /*
1021 * pebs_output: 0: no PEBS so far, 1: PT, 2: DS
1022 */
1023 if (cpuc->pebs_output &&
1024 cpuc->pebs_output != is_pebs_pt(leader) + 1)
1025 return -EINVAL;
1026
1027 cpuc->pebs_output = is_pebs_pt(leader) + 1;
1028 }
1008 1029
1009 if (is_x86_event(leader)) { 1030 if (is_x86_event(leader)) {
1010 if (n >= max_count) 1031 if (n >= max_count)
@@ -2241,6 +2262,17 @@ static int x86_pmu_check_period(struct perf_event *event, u64 value)
2241 return 0; 2262 return 0;
2242} 2263}
2243 2264
2265static int x86_pmu_aux_output_match(struct perf_event *event)
2266{
2267 if (!(pmu.capabilities & PERF_PMU_CAP_AUX_OUTPUT))
2268 return 0;
2269
2270 if (x86_pmu.aux_output_match)
2271 return x86_pmu.aux_output_match(event);
2272
2273 return 0;
2274}
2275
2244static struct pmu pmu = { 2276static struct pmu pmu = {
2245 .pmu_enable = x86_pmu_enable, 2277 .pmu_enable = x86_pmu_enable,
2246 .pmu_disable = x86_pmu_disable, 2278 .pmu_disable = x86_pmu_disable,
@@ -2266,6 +2298,8 @@ static struct pmu pmu = {
2266 .sched_task = x86_pmu_sched_task, 2298 .sched_task = x86_pmu_sched_task,
2267 .task_ctx_size = sizeof(struct x86_perf_task_context), 2299 .task_ctx_size = sizeof(struct x86_perf_task_context),
2268 .check_period = x86_pmu_check_period, 2300 .check_period = x86_pmu_check_period,
2301
2302 .aux_output_match = x86_pmu_aux_output_match,
2269}; 2303};
2270 2304
2271void arch_perf_update_userpage(struct perf_event *event, 2305void arch_perf_update_userpage(struct perf_event *event,
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 648260b5f367..28459f4b795a 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -18,6 +18,7 @@
18#include <asm/cpufeature.h> 18#include <asm/cpufeature.h>
19#include <asm/hardirq.h> 19#include <asm/hardirq.h>
20#include <asm/intel-family.h> 20#include <asm/intel-family.h>
21#include <asm/intel_pt.h>
21#include <asm/apic.h> 22#include <asm/apic.h>
22#include <asm/cpu_device_id.h> 23#include <asm/cpu_device_id.h>
23 24
@@ -3298,6 +3299,13 @@ static int intel_pmu_hw_config(struct perf_event *event)
3298 } 3299 }
3299 } 3300 }
3300 3301
3302 if (event->attr.aux_output) {
3303 if (!event->attr.precise_ip)
3304 return -EINVAL;
3305
3306 event->hw.flags |= PERF_X86_EVENT_PEBS_VIA_PT;
3307 }
3308
3301 if (event->attr.type != PERF_TYPE_RAW) 3309 if (event->attr.type != PERF_TYPE_RAW)
3302 return 0; 3310 return 0;
3303 3311
@@ -3811,6 +3819,14 @@ static int intel_pmu_check_period(struct perf_event *event, u64 value)
3811 return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0; 3819 return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0;
3812} 3820}
3813 3821
3822static int intel_pmu_aux_output_match(struct perf_event *event)
3823{
3824 if (!x86_pmu.intel_cap.pebs_output_pt_available)
3825 return 0;
3826
3827 return is_intel_pt_event(event);
3828}
3829
3814PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63"); 3830PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
3815 3831
3816PMU_FORMAT_ATTR(ldlat, "config1:0-15"); 3832PMU_FORMAT_ATTR(ldlat, "config1:0-15");
@@ -3935,6 +3951,8 @@ static __initconst const struct x86_pmu intel_pmu = {
3935 .sched_task = intel_pmu_sched_task, 3951 .sched_task = intel_pmu_sched_task,
3936 3952
3937 .check_period = intel_pmu_check_period, 3953 .check_period = intel_pmu_check_period,
3954
3955 .aux_output_match = intel_pmu_aux_output_match,
3938}; 3956};
3939 3957
3940static __init void intel_clovertown_quirk(void) 3958static __init void intel_clovertown_quirk(void)
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index f1269e804e9b..ce83950036c5 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -902,6 +902,9 @@ struct event_constraint *intel_pebs_constraints(struct perf_event *event)
902 */ 902 */
903static inline bool pebs_needs_sched_cb(struct cpu_hw_events *cpuc) 903static inline bool pebs_needs_sched_cb(struct cpu_hw_events *cpuc)
904{ 904{
905 if (cpuc->n_pebs == cpuc->n_pebs_via_pt)
906 return false;
907
905 return cpuc->n_pebs && (cpuc->n_pebs == cpuc->n_large_pebs); 908 return cpuc->n_pebs && (cpuc->n_pebs == cpuc->n_large_pebs);
906} 909}
907 910
@@ -919,6 +922,9 @@ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
919 u64 threshold; 922 u64 threshold;
920 int reserved; 923 int reserved;
921 924
925 if (cpuc->n_pebs_via_pt)
926 return;
927
922 if (x86_pmu.flags & PMU_FL_PEBS_ALL) 928 if (x86_pmu.flags & PMU_FL_PEBS_ALL)
923 reserved = x86_pmu.max_pebs_events + x86_pmu.num_counters_fixed; 929 reserved = x86_pmu.max_pebs_events + x86_pmu.num_counters_fixed;
924 else 930 else
@@ -1059,10 +1065,40 @@ void intel_pmu_pebs_add(struct perf_event *event)
1059 cpuc->n_pebs++; 1065 cpuc->n_pebs++;
1060 if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS) 1066 if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS)
1061 cpuc->n_large_pebs++; 1067 cpuc->n_large_pebs++;
1068 if (hwc->flags & PERF_X86_EVENT_PEBS_VIA_PT)
1069 cpuc->n_pebs_via_pt++;
1062 1070
1063 pebs_update_state(needed_cb, cpuc, event, true); 1071 pebs_update_state(needed_cb, cpuc, event, true);
1064} 1072}
1065 1073
1074static void intel_pmu_pebs_via_pt_disable(struct perf_event *event)
1075{
1076 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
1077
1078 if (!is_pebs_pt(event))
1079 return;
1080
1081 if (!(cpuc->pebs_enabled & ~PEBS_VIA_PT_MASK))
1082 cpuc->pebs_enabled &= ~PEBS_VIA_PT_MASK;
1083}
1084
1085static void intel_pmu_pebs_via_pt_enable(struct perf_event *event)
1086{
1087 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
1088 struct hw_perf_event *hwc = &event->hw;
1089 struct debug_store *ds = cpuc->ds;
1090
1091 if (!is_pebs_pt(event))
1092 return;
1093
1094 if (!(event->hw.flags & PERF_X86_EVENT_LARGE_PEBS))
1095 cpuc->pebs_enabled |= PEBS_PMI_AFTER_EACH_RECORD;
1096
1097 cpuc->pebs_enabled |= PEBS_OUTPUT_PT;
1098
1099 wrmsrl(MSR_RELOAD_PMC0 + hwc->idx, ds->pebs_event_reset[hwc->idx]);
1100}
1101
1066void intel_pmu_pebs_enable(struct perf_event *event) 1102void intel_pmu_pebs_enable(struct perf_event *event)
1067{ 1103{
1068 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 1104 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
@@ -1100,6 +1136,8 @@ void intel_pmu_pebs_enable(struct perf_event *event)
1100 } else { 1136 } else {
1101 ds->pebs_event_reset[hwc->idx] = 0; 1137 ds->pebs_event_reset[hwc->idx] = 0;
1102 } 1138 }
1139
1140 intel_pmu_pebs_via_pt_enable(event);
1103} 1141}
1104 1142
1105void intel_pmu_pebs_del(struct perf_event *event) 1143void intel_pmu_pebs_del(struct perf_event *event)
@@ -1111,6 +1149,8 @@ void intel_pmu_pebs_del(struct perf_event *event)
1111 cpuc->n_pebs--; 1149 cpuc->n_pebs--;
1112 if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS) 1150 if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS)
1113 cpuc->n_large_pebs--; 1151 cpuc->n_large_pebs--;
1152 if (hwc->flags & PERF_X86_EVENT_PEBS_VIA_PT)
1153 cpuc->n_pebs_via_pt--;
1114 1154
1115 pebs_update_state(needed_cb, cpuc, event, false); 1155 pebs_update_state(needed_cb, cpuc, event, false);
1116} 1156}
@@ -1120,7 +1160,8 @@ void intel_pmu_pebs_disable(struct perf_event *event)
1120 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 1160 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
1121 struct hw_perf_event *hwc = &event->hw; 1161 struct hw_perf_event *hwc = &event->hw;
1122 1162
1123 if (cpuc->n_pebs == cpuc->n_large_pebs) 1163 if (cpuc->n_pebs == cpuc->n_large_pebs &&
1164 cpuc->n_pebs != cpuc->n_pebs_via_pt)
1124 intel_pmu_drain_pebs_buffer(); 1165 intel_pmu_drain_pebs_buffer();
1125 1166
1126 cpuc->pebs_enabled &= ~(1ULL << hwc->idx); 1167 cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
@@ -1131,6 +1172,8 @@ void intel_pmu_pebs_disable(struct perf_event *event)
1131 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST) 1172 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
1132 cpuc->pebs_enabled &= ~(1ULL << 63); 1173 cpuc->pebs_enabled &= ~(1ULL << 63);
1133 1174
1175 intel_pmu_pebs_via_pt_disable(event);
1176
1134 if (cpuc->enabled) 1177 if (cpuc->enabled)
1135 wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); 1178 wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
1136 1179
@@ -2031,6 +2074,12 @@ void __init intel_ds_init(void)
2031 PERF_SAMPLE_REGS_INTR); 2074 PERF_SAMPLE_REGS_INTR);
2032 } 2075 }
2033 pr_cont("PEBS fmt4%c%s, ", pebs_type, pebs_qual); 2076 pr_cont("PEBS fmt4%c%s, ", pebs_type, pebs_qual);
2077
2078 if (x86_pmu.intel_cap.pebs_output_pt_available) {
2079 pr_cont("PEBS-via-PT, ");
2080 x86_get_pmu()->capabilities |= PERF_PMU_CAP_AUX_OUTPUT;
2081 }
2082
2034 break; 2083 break;
2035 2084
2036 default: 2085 default:
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index fa43d90799cc..b1bb4d28e0be 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -1564,6 +1564,11 @@ void cpu_emergency_stop_pt(void)
1564 pt_event_stop(pt->handle.event, PERF_EF_UPDATE); 1564 pt_event_stop(pt->handle.event, PERF_EF_UPDATE);
1565} 1565}
1566 1566
1567int is_intel_pt_event(struct perf_event *event)
1568{
1569 return event->pmu == &pt_pmu.pmu;
1570}
1571
1567static __init int pt_init(void) 1572static __init int pt_init(void)
1568{ 1573{
1569 int ret, cpu, prior_warn = 0; 1574 int ret, cpu, prior_warn = 0;
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 8751008fc170..ecacfbf4ebc1 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -76,6 +76,7 @@ static inline bool constraint_match(struct event_constraint *c, u64 ecode)
76#define PERF_X86_EVENT_EXCL_ACCT 0x0100 /* accounted EXCL event */ 76#define PERF_X86_EVENT_EXCL_ACCT 0x0100 /* accounted EXCL event */
77#define PERF_X86_EVENT_AUTO_RELOAD 0x0200 /* use PEBS auto-reload */ 77#define PERF_X86_EVENT_AUTO_RELOAD 0x0200 /* use PEBS auto-reload */
78#define PERF_X86_EVENT_LARGE_PEBS 0x0400 /* use large PEBS */ 78#define PERF_X86_EVENT_LARGE_PEBS 0x0400 /* use large PEBS */
79#define PERF_X86_EVENT_PEBS_VIA_PT 0x0800 /* use PT buffer for PEBS */
79 80
80struct amd_nb { 81struct amd_nb {
81 int nb_id; /* NorthBridge id */ 82 int nb_id; /* NorthBridge id */
@@ -85,6 +86,11 @@ struct amd_nb {
85}; 86};
86 87
87#define PEBS_COUNTER_MASK ((1ULL << MAX_PEBS_EVENTS) - 1) 88#define PEBS_COUNTER_MASK ((1ULL << MAX_PEBS_EVENTS) - 1)
89#define PEBS_PMI_AFTER_EACH_RECORD BIT_ULL(60)
90#define PEBS_OUTPUT_OFFSET 61
91#define PEBS_OUTPUT_MASK (3ull << PEBS_OUTPUT_OFFSET)
92#define PEBS_OUTPUT_PT (1ull << PEBS_OUTPUT_OFFSET)
93#define PEBS_VIA_PT_MASK (PEBS_OUTPUT_PT | PEBS_PMI_AFTER_EACH_RECORD)
88 94
89/* 95/*
90 * Flags PEBS can handle without an PMI. 96 * Flags PEBS can handle without an PMI.
@@ -211,6 +217,8 @@ struct cpu_hw_events {
211 u64 pebs_enabled; 217 u64 pebs_enabled;
212 int n_pebs; 218 int n_pebs;
213 int n_large_pebs; 219 int n_large_pebs;
220 int n_pebs_via_pt;
221 int pebs_output;
214 222
215 /* Current super set of events hardware configuration */ 223 /* Current super set of events hardware configuration */
216 u64 pebs_data_cfg; 224 u64 pebs_data_cfg;
@@ -510,6 +518,8 @@ union perf_capabilities {
510 */ 518 */
511 u64 full_width_write:1; 519 u64 full_width_write:1;
512 u64 pebs_baseline:1; 520 u64 pebs_baseline:1;
521 u64 pebs_metrics_available:1;
522 u64 pebs_output_pt_available:1;
513 }; 523 };
514 u64 capabilities; 524 u64 capabilities;
515}; 525};
@@ -692,6 +702,8 @@ struct x86_pmu {
692 * Check period value for PERF_EVENT_IOC_PERIOD ioctl. 702 * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
693 */ 703 */
694 int (*check_period) (struct perf_event *event, u64 period); 704 int (*check_period) (struct perf_event *event, u64 period);
705
706 int (*aux_output_match) (struct perf_event *event);
695}; 707};
696 708
697struct x86_perf_task_context { 709struct x86_perf_task_context {
@@ -901,6 +913,11 @@ static inline int amd_pmu_init(void)
901 913
902#endif /* CONFIG_CPU_SUP_AMD */ 914#endif /* CONFIG_CPU_SUP_AMD */
903 915
916static inline int is_pebs_pt(struct perf_event *event)
917{
918 return !!(event->hw.flags & PERF_X86_EVENT_PEBS_VIA_PT);
919}
920
904#ifdef CONFIG_CPU_SUP_INTEL 921#ifdef CONFIG_CPU_SUP_INTEL
905 922
906static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period) 923static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period)
diff --git a/arch/x86/include/asm/intel_pt.h b/arch/x86/include/asm/intel_pt.h
index 634f99b1dc22..423b788f495e 100644
--- a/arch/x86/include/asm/intel_pt.h
+++ b/arch/x86/include/asm/intel_pt.h
@@ -28,10 +28,12 @@ enum pt_capabilities {
28void cpu_emergency_stop_pt(void); 28void cpu_emergency_stop_pt(void);
29extern u32 intel_pt_validate_hw_cap(enum pt_capabilities cap); 29extern u32 intel_pt_validate_hw_cap(enum pt_capabilities cap);
30extern u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities cap); 30extern u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities cap);
31extern int is_intel_pt_event(struct perf_event *event);
31#else 32#else
32static inline void cpu_emergency_stop_pt(void) {} 33static inline void cpu_emergency_stop_pt(void) {}
33static inline u32 intel_pt_validate_hw_cap(enum pt_capabilities cap) { return 0; } 34static inline u32 intel_pt_validate_hw_cap(enum pt_capabilities cap) { return 0; }
34static inline u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities capability) { return 0; } 35static inline u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities capability) { return 0; }
36static inline int is_intel_pt_event(struct perf_event *event) { return 0; }
35#endif 37#endif
36 38
37#endif /* _ASM_X86_INTEL_PT_H */ 39#endif /* _ASM_X86_INTEL_PT_H */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 271d837d69a8..de753206b427 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -375,6 +375,10 @@
375/* Alternative perfctr range with full access. */ 375/* Alternative perfctr range with full access. */
376#define MSR_IA32_PMC0 0x000004c1 376#define MSR_IA32_PMC0 0x000004c1
377 377
378/* Auto-reload via MSR instead of DS area */
379#define MSR_RELOAD_PMC0 0x000014c1
380#define MSR_RELOAD_FIXED_CTR0 0x00001309
381
378/* AMD64 MSRs. Not complete. See the architecture manual for a more 382/* AMD64 MSRs. Not complete. See the architecture manual for a more
379 complete list. */ 383 complete list. */
380 384