diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2012-07-04 02:00:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-07-05 15:56:01 -0400 |
commit | 6a67943a18c264d5f3df436da38edb3e59adc905 (patch) | |
tree | f95860ecea31e3b557966a0026e98bacbc3928b8 /arch/x86/kernel/cpu | |
parent | 42089697244ba8e64fa43fb5e6d50d47a8e4cb00 (diff) |
perf/x86: Uncore filter support for SandyBridge-EP
This patch adds C-Box and PCU filter support for SandyBridge-EP
uncore. We can filter C-Box events by thread/core ID and filter
PCU events by frequency/voltage.
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1341381616-12229-5-git-send-email-zheng.z.yan@intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.c | 228 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.h | 24 |
2 files changed, 206 insertions, 46 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 4fecbd00ee75..19faffc60886 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -14,10 +14,13 @@ static cpumask_t uncore_cpu_mask; | |||
14 | /* constraint for the fixed counter */ | 14 | /* constraint for the fixed counter */ |
15 | static struct event_constraint constraint_fixed = | 15 | static struct event_constraint constraint_fixed = |
16 | EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL); | 16 | EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL); |
17 | static struct event_constraint constraint_empty = | ||
18 | EVENT_CONSTRAINT(0, 0, 0); | ||
17 | 19 | ||
18 | DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7"); | 20 | DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7"); |
19 | DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15"); | 21 | DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15"); |
20 | DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18"); | 22 | DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18"); |
23 | DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19"); | ||
21 | DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23"); | 24 | DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23"); |
22 | DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28"); | 25 | DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28"); |
23 | DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31"); | 26 | DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31"); |
@@ -26,8 +29,19 @@ DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28"); | |||
26 | DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15"); | 29 | DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15"); |
27 | DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30"); | 30 | DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30"); |
28 | DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51"); | 31 | DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51"); |
32 | DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4"); | ||
33 | DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17"); | ||
34 | DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22"); | ||
35 | DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31"); | ||
36 | DEFINE_UNCORE_FORMAT_ATTR(filter_brand0, filter_brand0, "config1:0-7"); | ||
37 | DEFINE_UNCORE_FORMAT_ATTR(filter_brand1, filter_brand1, "config1:8-15"); | ||
38 | DEFINE_UNCORE_FORMAT_ATTR(filter_brand2, filter_brand2, "config1:16-23"); | ||
39 | DEFINE_UNCORE_FORMAT_ATTR(filter_brand3, filter_brand3, "config1:24-31"); | ||
29 | 40 | ||
30 | /* Sandy Bridge-EP uncore support */ | 41 | /* Sandy Bridge-EP uncore support */ |
42 | static struct intel_uncore_type snbep_uncore_cbox; | ||
43 | static struct intel_uncore_type snbep_uncore_pcu; | ||
44 | |||
31 | static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box) | 45 | static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box) |
32 | { | 46 | { |
33 | struct pci_dev *pdev = box->pci_dev; | 47 | struct pci_dev *pdev = box->pci_dev; |
@@ -120,6 +134,10 @@ static void snbep_uncore_msr_enable_event(struct intel_uncore_box *box, | |||
120 | struct perf_event *event) | 134 | struct perf_event *event) |
121 | { | 135 | { |
122 | struct hw_perf_event *hwc = &event->hw; | 136 | struct hw_perf_event *hwc = &event->hw; |
137 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; | ||
138 | |||
139 | if (reg1->idx != EXTRA_REG_NONE) | ||
140 | wrmsrl(reg1->reg, reg1->config); | ||
123 | 141 | ||
124 | wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN); | 142 | wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN); |
125 | } | 143 | } |
@@ -149,6 +167,71 @@ static void snbep_uncore_msr_init_box(struct intel_uncore_box *box) | |||
149 | wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT); | 167 | wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT); |
150 | } | 168 | } |
151 | 169 | ||
170 | static struct event_constraint * | ||
171 | snbep_uncore_get_constraint(struct intel_uncore_box *box, | ||
172 | struct perf_event *event) | ||
173 | { | ||
174 | struct intel_uncore_extra_reg *er; | ||
175 | struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; | ||
176 | unsigned long flags; | ||
177 | bool ok = false; | ||
178 | |||
179 | if (reg1->idx == EXTRA_REG_NONE || (box->phys_id >= 0 && reg1->alloc)) | ||
180 | return NULL; | ||
181 | |||
182 | er = &box->shared_regs[reg1->idx]; | ||
183 | raw_spin_lock_irqsave(&er->lock, flags); | ||
184 | if (!atomic_read(&er->ref) || er->config1 == reg1->config) { | ||
185 | atomic_inc(&er->ref); | ||
186 | er->config1 = reg1->config; | ||
187 | ok = true; | ||
188 | } | ||
189 | raw_spin_unlock_irqrestore(&er->lock, flags); | ||
190 | |||
191 | if (ok) { | ||
192 | if (box->phys_id >= 0) | ||
193 | reg1->alloc = 1; | ||
194 | return NULL; | ||
195 | } | ||
196 | return &constraint_empty; | ||
197 | } | ||
198 | |||
199 | static void snbep_uncore_put_constraint(struct intel_uncore_box *box, | ||
200 | struct perf_event *event) | ||
201 | { | ||
202 | struct intel_uncore_extra_reg *er; | ||
203 | struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; | ||
204 | |||
205 | if (box->phys_id < 0 || !reg1->alloc) | ||
206 | return; | ||
207 | |||
208 | er = &box->shared_regs[reg1->idx]; | ||
209 | atomic_dec(&er->ref); | ||
210 | reg1->alloc = 0; | ||
211 | } | ||
212 | |||
213 | static int snbep_uncore_hw_config(struct intel_uncore_box *box, | ||
214 | struct perf_event *event) | ||
215 | { | ||
216 | struct hw_perf_event *hwc = &event->hw; | ||
217 | struct hw_perf_event_extra *reg1 = &hwc->extra_reg; | ||
218 | |||
219 | if (box->pmu->type == &snbep_uncore_cbox) { | ||
220 | reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER + | ||
221 | SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx; | ||
222 | reg1->config = event->attr.config1 & | ||
223 | SNBEP_CB0_MSR_PMON_BOX_FILTER_MASK; | ||
224 | } else if (box->pmu->type == &snbep_uncore_pcu) { | ||
225 | reg1->reg = SNBEP_PCU_MSR_PMON_BOX_FILTER; | ||
226 | reg1->config = event->attr.config1 & | ||
227 | SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK; | ||
228 | } else { | ||
229 | return 0; | ||
230 | } | ||
231 | reg1->idx = 0; | ||
232 | return 0; | ||
233 | } | ||
234 | |||
152 | static struct attribute *snbep_uncore_formats_attr[] = { | 235 | static struct attribute *snbep_uncore_formats_attr[] = { |
153 | &format_attr_event.attr, | 236 | &format_attr_event.attr, |
154 | &format_attr_umask.attr, | 237 | &format_attr_umask.attr, |
@@ -167,6 +250,20 @@ static struct attribute *snbep_uncore_ubox_formats_attr[] = { | |||
167 | NULL, | 250 | NULL, |
168 | }; | 251 | }; |
169 | 252 | ||
253 | static struct attribute *snbep_uncore_cbox_formats_attr[] = { | ||
254 | &format_attr_event.attr, | ||
255 | &format_attr_umask.attr, | ||
256 | &format_attr_edge.attr, | ||
257 | &format_attr_tid_en.attr, | ||
258 | &format_attr_inv.attr, | ||
259 | &format_attr_thresh8.attr, | ||
260 | &format_attr_filter_tid.attr, | ||
261 | &format_attr_filter_nid.attr, | ||
262 | &format_attr_filter_state.attr, | ||
263 | &format_attr_filter_opc.attr, | ||
264 | NULL, | ||
265 | }; | ||
266 | |||
170 | static struct attribute *snbep_uncore_pcu_formats_attr[] = { | 267 | static struct attribute *snbep_uncore_pcu_formats_attr[] = { |
171 | &format_attr_event.attr, | 268 | &format_attr_event.attr, |
172 | &format_attr_occ_sel.attr, | 269 | &format_attr_occ_sel.attr, |
@@ -175,6 +272,10 @@ static struct attribute *snbep_uncore_pcu_formats_attr[] = { | |||
175 | &format_attr_thresh5.attr, | 272 | &format_attr_thresh5.attr, |
176 | &format_attr_occ_invert.attr, | 273 | &format_attr_occ_invert.attr, |
177 | &format_attr_occ_edge.attr, | 274 | &format_attr_occ_edge.attr, |
275 | &format_attr_filter_brand0.attr, | ||
276 | &format_attr_filter_brand1.attr, | ||
277 | &format_attr_filter_brand2.attr, | ||
278 | &format_attr_filter_brand3.attr, | ||
178 | NULL, | 279 | NULL, |
179 | }; | 280 | }; |
180 | 281 | ||
@@ -203,6 +304,11 @@ static struct attribute_group snbep_uncore_ubox_format_group = { | |||
203 | .attrs = snbep_uncore_ubox_formats_attr, | 304 | .attrs = snbep_uncore_ubox_formats_attr, |
204 | }; | 305 | }; |
205 | 306 | ||
307 | static struct attribute_group snbep_uncore_cbox_format_group = { | ||
308 | .name = "format", | ||
309 | .attrs = snbep_uncore_cbox_formats_attr, | ||
310 | }; | ||
311 | |||
206 | static struct attribute_group snbep_uncore_pcu_format_group = { | 312 | static struct attribute_group snbep_uncore_pcu_format_group = { |
207 | .name = "format", | 313 | .name = "format", |
208 | .attrs = snbep_uncore_pcu_formats_attr, | 314 | .attrs = snbep_uncore_pcu_formats_attr, |
@@ -215,6 +321,9 @@ static struct intel_uncore_ops snbep_uncore_msr_ops = { | |||
215 | .disable_event = snbep_uncore_msr_disable_event, | 321 | .disable_event = snbep_uncore_msr_disable_event, |
216 | .enable_event = snbep_uncore_msr_enable_event, | 322 | .enable_event = snbep_uncore_msr_enable_event, |
217 | .read_counter = snbep_uncore_msr_read_counter, | 323 | .read_counter = snbep_uncore_msr_read_counter, |
324 | .get_constraint = snbep_uncore_get_constraint, | ||
325 | .put_constraint = snbep_uncore_put_constraint, | ||
326 | .hw_config = snbep_uncore_hw_config, | ||
218 | }; | 327 | }; |
219 | 328 | ||
220 | static struct intel_uncore_ops snbep_uncore_pci_ops = { | 329 | static struct intel_uncore_ops snbep_uncore_pci_ops = { |
@@ -307,31 +416,33 @@ static struct intel_uncore_type snbep_uncore_ubox = { | |||
307 | }; | 416 | }; |
308 | 417 | ||
309 | static struct intel_uncore_type snbep_uncore_cbox = { | 418 | static struct intel_uncore_type snbep_uncore_cbox = { |
310 | .name = "cbox", | 419 | .name = "cbox", |
311 | .num_counters = 4, | 420 | .num_counters = 4, |
312 | .num_boxes = 8, | 421 | .num_boxes = 8, |
313 | .perf_ctr_bits = 44, | 422 | .perf_ctr_bits = 44, |
314 | .event_ctl = SNBEP_C0_MSR_PMON_CTL0, | 423 | .event_ctl = SNBEP_C0_MSR_PMON_CTL0, |
315 | .perf_ctr = SNBEP_C0_MSR_PMON_CTR0, | 424 | .perf_ctr = SNBEP_C0_MSR_PMON_CTR0, |
316 | .event_mask = SNBEP_PMON_RAW_EVENT_MASK, | 425 | .event_mask = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK, |
317 | .box_ctl = SNBEP_C0_MSR_PMON_BOX_CTL, | 426 | .box_ctl = SNBEP_C0_MSR_PMON_BOX_CTL, |
318 | .msr_offset = SNBEP_CBO_MSR_OFFSET, | 427 | .msr_offset = SNBEP_CBO_MSR_OFFSET, |
319 | .constraints = snbep_uncore_cbox_constraints, | 428 | .num_shared_regs = 1, |
320 | .ops = &snbep_uncore_msr_ops, | 429 | .constraints = snbep_uncore_cbox_constraints, |
321 | .format_group = &snbep_uncore_format_group, | 430 | .ops = &snbep_uncore_msr_ops, |
431 | .format_group = &snbep_uncore_cbox_format_group, | ||
322 | }; | 432 | }; |
323 | 433 | ||
324 | static struct intel_uncore_type snbep_uncore_pcu = { | 434 | static struct intel_uncore_type snbep_uncore_pcu = { |
325 | .name = "pcu", | 435 | .name = "pcu", |
326 | .num_counters = 4, | 436 | .num_counters = 4, |
327 | .num_boxes = 1, | 437 | .num_boxes = 1, |
328 | .perf_ctr_bits = 48, | 438 | .perf_ctr_bits = 48, |
329 | .perf_ctr = SNBEP_PCU_MSR_PMON_CTR0, | 439 | .perf_ctr = SNBEP_PCU_MSR_PMON_CTR0, |
330 | .event_ctl = SNBEP_PCU_MSR_PMON_CTL0, | 440 | .event_ctl = SNBEP_PCU_MSR_PMON_CTL0, |
331 | .event_mask = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK, | 441 | .event_mask = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK, |
332 | .box_ctl = SNBEP_PCU_MSR_PMON_BOX_CTL, | 442 | .box_ctl = SNBEP_PCU_MSR_PMON_BOX_CTL, |
333 | .ops = &snbep_uncore_msr_ops, | 443 | .num_shared_regs = 1, |
334 | .format_group = &snbep_uncore_pcu_format_group, | 444 | .ops = &snbep_uncore_msr_ops, |
445 | .format_group = &snbep_uncore_pcu_format_group, | ||
335 | }; | 446 | }; |
336 | 447 | ||
337 | static struct intel_uncore_type *snbep_msr_uncores[] = { | 448 | static struct intel_uncore_type *snbep_msr_uncores[] = { |
@@ -747,15 +858,22 @@ static void uncore_pmu_init_hrtimer(struct intel_uncore_box *box) | |||
747 | box->hrtimer.function = uncore_pmu_hrtimer; | 858 | box->hrtimer.function = uncore_pmu_hrtimer; |
748 | } | 859 | } |
749 | 860 | ||
750 | struct intel_uncore_box *uncore_alloc_box(int cpu) | 861 | struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type, |
862 | int cpu) | ||
751 | { | 863 | { |
752 | struct intel_uncore_box *box; | 864 | struct intel_uncore_box *box; |
865 | int i, size; | ||
753 | 866 | ||
754 | box = kmalloc_node(sizeof(*box), GFP_KERNEL | __GFP_ZERO, | 867 | size = sizeof(*box) + type->num_shared_regs * |
755 | cpu_to_node(cpu)); | 868 | sizeof(struct intel_uncore_extra_reg); |
869 | |||
870 | box = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, cpu_to_node(cpu)); | ||
756 | if (!box) | 871 | if (!box) |
757 | return NULL; | 872 | return NULL; |
758 | 873 | ||
874 | for (i = 0; i < type->num_shared_regs; i++) | ||
875 | raw_spin_lock_init(&box->shared_regs[i].lock); | ||
876 | |||
759 | uncore_pmu_init_hrtimer(box); | 877 | uncore_pmu_init_hrtimer(box); |
760 | atomic_set(&box->refcnt, 1); | 878 | atomic_set(&box->refcnt, 1); |
761 | box->cpu = -1; | 879 | box->cpu = -1; |
@@ -834,11 +952,18 @@ static int uncore_collect_events(struct intel_uncore_box *box, | |||
834 | } | 952 | } |
835 | 953 | ||
836 | static struct event_constraint * | 954 | static struct event_constraint * |
837 | uncore_event_constraint(struct intel_uncore_type *type, | 955 | uncore_get_event_constraint(struct intel_uncore_box *box, |
838 | struct perf_event *event) | 956 | struct perf_event *event) |
839 | { | 957 | { |
958 | struct intel_uncore_type *type = box->pmu->type; | ||
840 | struct event_constraint *c; | 959 | struct event_constraint *c; |
841 | 960 | ||
961 | if (type->ops->get_constraint) { | ||
962 | c = type->ops->get_constraint(box, event); | ||
963 | if (c) | ||
964 | return c; | ||
965 | } | ||
966 | |||
842 | if (event->hw.config == ~0ULL) | 967 | if (event->hw.config == ~0ULL) |
843 | return &constraint_fixed; | 968 | return &constraint_fixed; |
844 | 969 | ||
@@ -852,19 +977,25 @@ uncore_event_constraint(struct intel_uncore_type *type, | |||
852 | return &type->unconstrainted; | 977 | return &type->unconstrainted; |
853 | } | 978 | } |
854 | 979 | ||
980 | static void uncore_put_event_constraint(struct intel_uncore_box *box, | ||
981 | struct perf_event *event) | ||
982 | { | ||
983 | if (box->pmu->type->ops->put_constraint) | ||
984 | box->pmu->type->ops->put_constraint(box, event); | ||
985 | } | ||
986 | |||
855 | static int uncore_assign_events(struct intel_uncore_box *box, | 987 | static int uncore_assign_events(struct intel_uncore_box *box, |
856 | int assign[], int n) | 988 | int assign[], int n) |
857 | { | 989 | { |
858 | unsigned long used_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)]; | 990 | unsigned long used_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)]; |
859 | struct event_constraint *c, *constraints[UNCORE_PMC_IDX_MAX]; | 991 | struct event_constraint *c, *constraints[UNCORE_PMC_IDX_MAX]; |
860 | int i, ret, wmin, wmax; | 992 | int i, wmin, wmax, ret = 0; |
861 | struct hw_perf_event *hwc; | 993 | struct hw_perf_event *hwc; |
862 | 994 | ||
863 | bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX); | 995 | bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX); |
864 | 996 | ||
865 | for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) { | 997 | for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) { |
866 | c = uncore_event_constraint(box->pmu->type, | 998 | c = uncore_get_event_constraint(box, box->event_list[i]); |
867 | box->event_list[i]); | ||
868 | constraints[i] = c; | 999 | constraints[i] = c; |
869 | wmin = min(wmin, c->weight); | 1000 | wmin = min(wmin, c->weight); |
870 | wmax = max(wmax, c->weight); | 1001 | wmax = max(wmax, c->weight); |
@@ -888,13 +1019,17 @@ static int uncore_assign_events(struct intel_uncore_box *box, | |||
888 | break; | 1019 | break; |
889 | 1020 | ||
890 | __set_bit(hwc->idx, used_mask); | 1021 | __set_bit(hwc->idx, used_mask); |
891 | assign[i] = hwc->idx; | 1022 | if (assign) |
1023 | assign[i] = hwc->idx; | ||
892 | } | 1024 | } |
893 | if (i == n) | ||
894 | return 0; | ||
895 | |||
896 | /* slow path */ | 1025 | /* slow path */ |
897 | ret = perf_assign_events(constraints, n, wmin, wmax, assign); | 1026 | if (i != n) |
1027 | ret = perf_assign_events(constraints, n, wmin, wmax, assign); | ||
1028 | |||
1029 | if (!assign || ret) { | ||
1030 | for (i = 0; i < n; i++) | ||
1031 | uncore_put_event_constraint(box, box->event_list[i]); | ||
1032 | } | ||
898 | return ret ? -EINVAL : 0; | 1033 | return ret ? -EINVAL : 0; |
899 | } | 1034 | } |
900 | 1035 | ||
@@ -1021,6 +1156,8 @@ static void uncore_pmu_event_del(struct perf_event *event, int flags) | |||
1021 | 1156 | ||
1022 | for (i = 0; i < box->n_events; i++) { | 1157 | for (i = 0; i < box->n_events; i++) { |
1023 | if (event == box->event_list[i]) { | 1158 | if (event == box->event_list[i]) { |
1159 | uncore_put_event_constraint(box, event); | ||
1160 | |||
1024 | while (++i < box->n_events) | 1161 | while (++i < box->n_events) |
1025 | box->event_list[i - 1] = box->event_list[i]; | 1162 | box->event_list[i - 1] = box->event_list[i]; |
1026 | 1163 | ||
@@ -1048,10 +1185,9 @@ static int uncore_validate_group(struct intel_uncore_pmu *pmu, | |||
1048 | { | 1185 | { |
1049 | struct perf_event *leader = event->group_leader; | 1186 | struct perf_event *leader = event->group_leader; |
1050 | struct intel_uncore_box *fake_box; | 1187 | struct intel_uncore_box *fake_box; |
1051 | int assign[UNCORE_PMC_IDX_MAX]; | ||
1052 | int ret = -EINVAL, n; | 1188 | int ret = -EINVAL, n; |
1053 | 1189 | ||
1054 | fake_box = uncore_alloc_box(smp_processor_id()); | 1190 | fake_box = uncore_alloc_box(pmu->type, smp_processor_id()); |
1055 | if (!fake_box) | 1191 | if (!fake_box) |
1056 | return -ENOMEM; | 1192 | return -ENOMEM; |
1057 | 1193 | ||
@@ -1073,7 +1209,7 @@ static int uncore_validate_group(struct intel_uncore_pmu *pmu, | |||
1073 | 1209 | ||
1074 | fake_box->n_events = n; | 1210 | fake_box->n_events = n; |
1075 | 1211 | ||
1076 | ret = uncore_assign_events(fake_box, assign, n); | 1212 | ret = uncore_assign_events(fake_box, NULL, n); |
1077 | out: | 1213 | out: |
1078 | kfree(fake_box); | 1214 | kfree(fake_box); |
1079 | return ret; | 1215 | return ret; |
@@ -1117,6 +1253,10 @@ int uncore_pmu_event_init(struct perf_event *event) | |||
1117 | return -EINVAL; | 1253 | return -EINVAL; |
1118 | event->cpu = box->cpu; | 1254 | event->cpu = box->cpu; |
1119 | 1255 | ||
1256 | event->hw.idx = -1; | ||
1257 | event->hw.last_tag = ~0ULL; | ||
1258 | event->hw.extra_reg.idx = EXTRA_REG_NONE; | ||
1259 | |||
1120 | if (event->attr.config == UNCORE_FIXED_EVENT) { | 1260 | if (event->attr.config == UNCORE_FIXED_EVENT) { |
1121 | /* no fixed counter */ | 1261 | /* no fixed counter */ |
1122 | if (!pmu->type->fixed_ctl) | 1262 | if (!pmu->type->fixed_ctl) |
@@ -1130,11 +1270,13 @@ int uncore_pmu_event_init(struct perf_event *event) | |||
1130 | hwc->config = ~0ULL; | 1270 | hwc->config = ~0ULL; |
1131 | } else { | 1271 | } else { |
1132 | hwc->config = event->attr.config & pmu->type->event_mask; | 1272 | hwc->config = event->attr.config & pmu->type->event_mask; |
1273 | if (pmu->type->ops->hw_config) { | ||
1274 | ret = pmu->type->ops->hw_config(box, event); | ||
1275 | if (ret) | ||
1276 | return ret; | ||
1277 | } | ||
1133 | } | 1278 | } |
1134 | 1279 | ||
1135 | event->hw.idx = -1; | ||
1136 | event->hw.last_tag = ~0ULL; | ||
1137 | |||
1138 | if (event->group_leader != event) | 1280 | if (event->group_leader != event) |
1139 | ret = uncore_validate_group(pmu, event); | 1281 | ret = uncore_validate_group(pmu, event); |
1140 | else | 1282 | else |
@@ -1276,7 +1418,7 @@ static int __devinit uncore_pci_add(struct intel_uncore_type *type, | |||
1276 | if (phys_id < 0) | 1418 | if (phys_id < 0) |
1277 | return -ENODEV; | 1419 | return -ENODEV; |
1278 | 1420 | ||
1279 | box = uncore_alloc_box(0); | 1421 | box = uncore_alloc_box(type, 0); |
1280 | if (!box) | 1422 | if (!box) |
1281 | return -ENOMEM; | 1423 | return -ENOMEM; |
1282 | 1424 | ||
@@ -1458,7 +1600,7 @@ static int __cpuinit uncore_cpu_prepare(int cpu, int phys_id) | |||
1458 | if (pmu->func_id < 0) | 1600 | if (pmu->func_id < 0) |
1459 | pmu->func_id = j; | 1601 | pmu->func_id = j; |
1460 | 1602 | ||
1461 | box = uncore_alloc_box(cpu); | 1603 | box = uncore_alloc_box(type, cpu); |
1462 | if (!box) | 1604 | if (!box) |
1463 | return -ENOMEM; | 1605 | return -ENOMEM; |
1464 | 1606 | ||
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index 88498c7b3420..b13e9ea81def 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h | |||
@@ -97,6 +97,10 @@ | |||
97 | SNBEP_PMON_CTL_INVERT | \ | 97 | SNBEP_PMON_CTL_INVERT | \ |
98 | SNBEP_U_MSR_PMON_CTL_TRESH_MASK) | 98 | SNBEP_U_MSR_PMON_CTL_TRESH_MASK) |
99 | 99 | ||
100 | #define SNBEP_CBO_PMON_CTL_TID_EN (1 << 19) | ||
101 | #define SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK (SNBEP_PMON_RAW_EVENT_MASK | \ | ||
102 | SNBEP_CBO_PMON_CTL_TID_EN) | ||
103 | |||
100 | /* SNB-EP PCU event control */ | 104 | /* SNB-EP PCU event control */ |
101 | #define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK 0x0000c000 | 105 | #define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK 0x0000c000 |
102 | #define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK 0x1f000000 | 106 | #define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK 0x1f000000 |
@@ -140,15 +144,17 @@ | |||
140 | /* SNB-EP Cbo register */ | 144 | /* SNB-EP Cbo register */ |
141 | #define SNBEP_C0_MSR_PMON_CTR0 0xd16 | 145 | #define SNBEP_C0_MSR_PMON_CTR0 0xd16 |
142 | #define SNBEP_C0_MSR_PMON_CTL0 0xd10 | 146 | #define SNBEP_C0_MSR_PMON_CTL0 0xd10 |
143 | #define SNBEP_C0_MSR_PMON_BOX_FILTER 0xd14 | ||
144 | #define SNBEP_C0_MSR_PMON_BOX_CTL 0xd04 | 147 | #define SNBEP_C0_MSR_PMON_BOX_CTL 0xd04 |
148 | #define SNBEP_C0_MSR_PMON_BOX_FILTER 0xd14 | ||
149 | #define SNBEP_CB0_MSR_PMON_BOX_FILTER_MASK 0xfffffc1f | ||
145 | #define SNBEP_CBO_MSR_OFFSET 0x20 | 150 | #define SNBEP_CBO_MSR_OFFSET 0x20 |
146 | 151 | ||
147 | /* SNB-EP PCU register */ | 152 | /* SNB-EP PCU register */ |
148 | #define SNBEP_PCU_MSR_PMON_CTR0 0xc36 | 153 | #define SNBEP_PCU_MSR_PMON_CTR0 0xc36 |
149 | #define SNBEP_PCU_MSR_PMON_CTL0 0xc30 | 154 | #define SNBEP_PCU_MSR_PMON_CTL0 0xc30 |
150 | #define SNBEP_PCU_MSR_PMON_BOX_FILTER 0xc34 | ||
151 | #define SNBEP_PCU_MSR_PMON_BOX_CTL 0xc24 | 155 | #define SNBEP_PCU_MSR_PMON_BOX_CTL 0xc24 |
156 | #define SNBEP_PCU_MSR_PMON_BOX_FILTER 0xc34 | ||
157 | #define SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK 0xffffffff | ||
152 | #define SNBEP_PCU_MSR_CORE_C3_CTR 0x3fc | 158 | #define SNBEP_PCU_MSR_CORE_C3_CTR 0x3fc |
153 | #define SNBEP_PCU_MSR_CORE_C6_CTR 0x3fd | 159 | #define SNBEP_PCU_MSR_CORE_C6_CTR 0x3fd |
154 | 160 | ||
@@ -163,7 +169,6 @@ struct intel_uncore_type { | |||
163 | int num_boxes; | 169 | int num_boxes; |
164 | int perf_ctr_bits; | 170 | int perf_ctr_bits; |
165 | int fixed_ctr_bits; | 171 | int fixed_ctr_bits; |
166 | int single_fixed; | ||
167 | unsigned perf_ctr; | 172 | unsigned perf_ctr; |
168 | unsigned event_ctl; | 173 | unsigned event_ctl; |
169 | unsigned event_mask; | 174 | unsigned event_mask; |
@@ -171,6 +176,8 @@ struct intel_uncore_type { | |||
171 | unsigned fixed_ctl; | 176 | unsigned fixed_ctl; |
172 | unsigned box_ctl; | 177 | unsigned box_ctl; |
173 | unsigned msr_offset; | 178 | unsigned msr_offset; |
179 | unsigned num_shared_regs:8; | ||
180 | unsigned single_fixed:1; | ||
174 | struct event_constraint unconstrainted; | 181 | struct event_constraint unconstrainted; |
175 | struct event_constraint *constraints; | 182 | struct event_constraint *constraints; |
176 | struct intel_uncore_pmu *pmus; | 183 | struct intel_uncore_pmu *pmus; |
@@ -188,6 +195,10 @@ struct intel_uncore_ops { | |||
188 | void (*disable_event)(struct intel_uncore_box *, struct perf_event *); | 195 | void (*disable_event)(struct intel_uncore_box *, struct perf_event *); |
189 | void (*enable_event)(struct intel_uncore_box *, struct perf_event *); | 196 | void (*enable_event)(struct intel_uncore_box *, struct perf_event *); |
190 | u64 (*read_counter)(struct intel_uncore_box *, struct perf_event *); | 197 | u64 (*read_counter)(struct intel_uncore_box *, struct perf_event *); |
198 | int (*hw_config)(struct intel_uncore_box *, struct perf_event *); | ||
199 | struct event_constraint *(*get_constraint)(struct intel_uncore_box *, | ||
200 | struct perf_event *); | ||
201 | void (*put_constraint)(struct intel_uncore_box *, struct perf_event *); | ||
191 | }; | 202 | }; |
192 | 203 | ||
193 | struct intel_uncore_pmu { | 204 | struct intel_uncore_pmu { |
@@ -200,6 +211,12 @@ struct intel_uncore_pmu { | |||
200 | struct list_head box_list; | 211 | struct list_head box_list; |
201 | }; | 212 | }; |
202 | 213 | ||
214 | struct intel_uncore_extra_reg { | ||
215 | raw_spinlock_t lock; | ||
216 | u64 config1; | ||
217 | atomic_t ref; | ||
218 | }; | ||
219 | |||
203 | struct intel_uncore_box { | 220 | struct intel_uncore_box { |
204 | int phys_id; | 221 | int phys_id; |
205 | int n_active; /* number of active events */ | 222 | int n_active; /* number of active events */ |
@@ -215,6 +232,7 @@ struct intel_uncore_box { | |||
215 | struct intel_uncore_pmu *pmu; | 232 | struct intel_uncore_pmu *pmu; |
216 | struct hrtimer hrtimer; | 233 | struct hrtimer hrtimer; |
217 | struct list_head list; | 234 | struct list_head list; |
235 | struct intel_uncore_extra_reg shared_regs[0]; | ||
218 | }; | 236 | }; |
219 | 237 | ||
220 | #define UNCORE_BOX_FLAG_INITIATED 0 | 238 | #define UNCORE_BOX_FLAG_INITIATED 0 |