aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-26 12:35:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-26 12:35:00 -0400
commit6a2e52f844ed0002579e9f6d3e6d6286fa3bd76d (patch)
tree5b72cfbec64093140928129119aefe91a4f9bb50 /arch
parentf48d42773bd14cfb9f392f32eff1856f924a9e6a (diff)
parent64dfab8e83644902ad2fd559a56c411b47e3ef3c (diff)
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "Most of the kernel diffstat relates to a group of Intel P6 and KNC (Xeon-Phi Knights Corner) PMU driver fixes, neither of which is in heavy use, so we took the fixes. The rest is diverse smallish fixes to the tooling and kernel side." * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86: Remove unused variable in nhmex_rbox_alter_er() perf/x86: Enable overflow on Intel KNC with a custom knc_pmu_handle_irq() perf/x86: Remove cpuc->enable check on Intl KNC event enable/disable perf/x86: Make Intel KNC use full 40-bit width of counters perf/x86/uncore: Handle pci_read_config_dword() errors perf/x86: Remove P6 cpuc->enabled check perf/x86: Update/fix generic events on P6 PMU perf/x86: Fix P6 FP_ASSIST event constraint perf, cpu hotplug: Use cached value of smp_processor_id() perf, cpu hotplug: Run CPU_STARTING notifiers with irqs disabled x86/perf: Fix virtualization sanity check perf test: Fix exclude_guest parse events tests perf tools: do not flush maps on COMM for perf report perf help: Fix --help for builtins perf trace: Check if sample raw_data field is set perf trace: Validate syscall id before growing syscall table
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/cpu/perf_event.c10
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c45
-rw-r--r--arch/x86/kernel/cpu/perf_event_knc.c93
-rw-r--r--arch/x86/kernel/cpu/perf_event_p6.c127
4 files changed, 228 insertions, 47 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 3373f84d1397..4a3374e61a93 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -208,12 +208,14 @@ static bool check_hw_exists(void)
208 } 208 }
209 209
210 /* 210 /*
211 * Now write a value and read it back to see if it matches, 211 * Read the current value, change it and read it back to see if it
212 * this is needed to detect certain hardware emulators (qemu/kvm) 212 * matches, this is needed to detect certain hardware emulators
213 * that don't trap on the MSR access and always return 0s. 213 * (qemu/kvm) that don't trap on the MSR access and always return 0s.
214 */ 214 */
215 val = 0xabcdUL;
216 reg = x86_pmu_event_addr(0); 215 reg = x86_pmu_event_addr(0);
216 if (rdmsrl_safe(reg, &val))
217 goto msr_fail;
218 val ^= 0xffffUL;
217 ret = wrmsrl_safe(reg, val); 219 ret = wrmsrl_safe(reg, val);
218 ret |= rdmsrl_safe(reg, &val_new); 220 ret |= rdmsrl_safe(reg, &val_new);
219 if (ret || val != val_new) 221 if (ret || val != val_new)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 5df8d32ba91e..3cf3d97cce3a 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -118,22 +118,24 @@ static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
118{ 118{
119 struct pci_dev *pdev = box->pci_dev; 119 struct pci_dev *pdev = box->pci_dev;
120 int box_ctl = uncore_pci_box_ctl(box); 120 int box_ctl = uncore_pci_box_ctl(box);
121 u32 config; 121 u32 config = 0;
122 122
123 pci_read_config_dword(pdev, box_ctl, &config); 123 if (!pci_read_config_dword(pdev, box_ctl, &config)) {
124 config |= SNBEP_PMON_BOX_CTL_FRZ; 124 config |= SNBEP_PMON_BOX_CTL_FRZ;
125 pci_write_config_dword(pdev, box_ctl, config); 125 pci_write_config_dword(pdev, box_ctl, config);
126 }
126} 127}
127 128
128static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box) 129static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
129{ 130{
130 struct pci_dev *pdev = box->pci_dev; 131 struct pci_dev *pdev = box->pci_dev;
131 int box_ctl = uncore_pci_box_ctl(box); 132 int box_ctl = uncore_pci_box_ctl(box);
132 u32 config; 133 u32 config = 0;
133 134
134 pci_read_config_dword(pdev, box_ctl, &config); 135 if (!pci_read_config_dword(pdev, box_ctl, &config)) {
135 config &= ~SNBEP_PMON_BOX_CTL_FRZ; 136 config &= ~SNBEP_PMON_BOX_CTL_FRZ;
136 pci_write_config_dword(pdev, box_ctl, config); 137 pci_write_config_dword(pdev, box_ctl, config);
138 }
137} 139}
138 140
139static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event) 141static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
@@ -156,7 +158,7 @@ static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct pe
156{ 158{
157 struct pci_dev *pdev = box->pci_dev; 159 struct pci_dev *pdev = box->pci_dev;
158 struct hw_perf_event *hwc = &event->hw; 160 struct hw_perf_event *hwc = &event->hw;
159 u64 count; 161 u64 count = 0;
160 162
161 pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count); 163 pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
162 pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1); 164 pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
@@ -603,11 +605,12 @@ static struct pci_driver snbep_uncore_pci_driver = {
603/* 605/*
604 * build pci bus to socket mapping 606 * build pci bus to socket mapping
605 */ 607 */
606static void snbep_pci2phy_map_init(void) 608static int snbep_pci2phy_map_init(void)
607{ 609{
608 struct pci_dev *ubox_dev = NULL; 610 struct pci_dev *ubox_dev = NULL;
609 int i, bus, nodeid; 611 int i, bus, nodeid;
610 u32 config; 612 int err = 0;
613 u32 config = 0;
611 614
612 while (1) { 615 while (1) {
613 /* find the UBOX device */ 616 /* find the UBOX device */
@@ -618,10 +621,14 @@ static void snbep_pci2phy_map_init(void)
618 break; 621 break;
619 bus = ubox_dev->bus->number; 622 bus = ubox_dev->bus->number;
620 /* get the Node ID of the local register */ 623 /* get the Node ID of the local register */
621 pci_read_config_dword(ubox_dev, 0x40, &config); 624 err = pci_read_config_dword(ubox_dev, 0x40, &config);
625 if (err)
626 break;
622 nodeid = config; 627 nodeid = config;
623 /* get the Node ID mapping */ 628 /* get the Node ID mapping */
624 pci_read_config_dword(ubox_dev, 0x54, &config); 629 err = pci_read_config_dword(ubox_dev, 0x54, &config);
630 if (err)
631 break;
625 /* 632 /*
626 * every three bits in the Node ID mapping register maps 633 * every three bits in the Node ID mapping register maps
627 * to a particular node. 634 * to a particular node.
@@ -633,7 +640,11 @@ static void snbep_pci2phy_map_init(void)
633 } 640 }
634 } 641 }
635 }; 642 };
636 return; 643
644 if (ubox_dev)
645 pci_dev_put(ubox_dev);
646
647 return err ? pcibios_err_to_errno(err) : 0;
637} 648}
638/* end of Sandy Bridge-EP uncore support */ 649/* end of Sandy Bridge-EP uncore support */
639 650
@@ -1547,7 +1558,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
1547{ 1558{
1548 struct hw_perf_event *hwc = &event->hw; 1559 struct hw_perf_event *hwc = &event->hw;
1549 struct hw_perf_event_extra *reg1 = &hwc->extra_reg; 1560 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
1550 int port;
1551 1561
1552 /* adjust the main event selector and extra register index */ 1562 /* adjust the main event selector and extra register index */
1553 if (reg1->idx % 2) { 1563 if (reg1->idx % 2) {
@@ -1559,7 +1569,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
1559 } 1569 }
1560 1570
1561 /* adjust extra register config */ 1571 /* adjust extra register config */
1562 port = reg1->idx / 6 + box->pmu->pmu_idx * 4;
1563 switch (reg1->idx % 6) { 1572 switch (reg1->idx % 6) {
1564 case 2: 1573 case 2:
1565 /* shift the 8~15 bits to the 0~7 bits */ 1574 /* shift the 8~15 bits to the 0~7 bits */
@@ -2578,9 +2587,11 @@ static int __init uncore_pci_init(void)
2578 2587
2579 switch (boot_cpu_data.x86_model) { 2588 switch (boot_cpu_data.x86_model) {
2580 case 45: /* Sandy Bridge-EP */ 2589 case 45: /* Sandy Bridge-EP */
2590 ret = snbep_pci2phy_map_init();
2591 if (ret)
2592 return ret;
2581 pci_uncores = snbep_pci_uncores; 2593 pci_uncores = snbep_pci_uncores;
2582 uncore_pci_driver = &snbep_uncore_pci_driver; 2594 uncore_pci_driver = &snbep_uncore_pci_driver;
2583 snbep_pci2phy_map_init();
2584 break; 2595 break;
2585 default: 2596 default:
2586 return 0; 2597 return 0;
diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c
index 7c46bfdbc373..4b7731bf23a8 100644
--- a/arch/x86/kernel/cpu/perf_event_knc.c
+++ b/arch/x86/kernel/cpu/perf_event_knc.c
@@ -3,6 +3,8 @@
3#include <linux/perf_event.h> 3#include <linux/perf_event.h>
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6#include <asm/hardirq.h>
7
6#include "perf_event.h" 8#include "perf_event.h"
7 9
8static const u64 knc_perfmon_event_map[] = 10static const u64 knc_perfmon_event_map[] =
@@ -173,30 +175,100 @@ static void knc_pmu_enable_all(int added)
173static inline void 175static inline void
174knc_pmu_disable_event(struct perf_event *event) 176knc_pmu_disable_event(struct perf_event *event)
175{ 177{
176 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
177 struct hw_perf_event *hwc = &event->hw; 178 struct hw_perf_event *hwc = &event->hw;
178 u64 val; 179 u64 val;
179 180
180 val = hwc->config; 181 val = hwc->config;
181 if (cpuc->enabled) 182 val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
182 val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
183 183
184 (void)wrmsrl_safe(hwc->config_base + hwc->idx, val); 184 (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
185} 185}
186 186
187static void knc_pmu_enable_event(struct perf_event *event) 187static void knc_pmu_enable_event(struct perf_event *event)
188{ 188{
189 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
190 struct hw_perf_event *hwc = &event->hw; 189 struct hw_perf_event *hwc = &event->hw;
191 u64 val; 190 u64 val;
192 191
193 val = hwc->config; 192 val = hwc->config;
194 if (cpuc->enabled) 193 val |= ARCH_PERFMON_EVENTSEL_ENABLE;
195 val |= ARCH_PERFMON_EVENTSEL_ENABLE;
196 194
197 (void)wrmsrl_safe(hwc->config_base + hwc->idx, val); 195 (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
198} 196}
199 197
198static inline u64 knc_pmu_get_status(void)
199{
200 u64 status;
201
202 rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
203
204 return status;
205}
206
207static inline void knc_pmu_ack_status(u64 ack)
208{
209 wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
210}
211
212static int knc_pmu_handle_irq(struct pt_regs *regs)
213{
214 struct perf_sample_data data;
215 struct cpu_hw_events *cpuc;
216 int handled = 0;
217 int bit, loops;
218 u64 status;
219
220 cpuc = &__get_cpu_var(cpu_hw_events);
221
222 knc_pmu_disable_all();
223
224 status = knc_pmu_get_status();
225 if (!status) {
226 knc_pmu_enable_all(0);
227 return handled;
228 }
229
230 loops = 0;
231again:
232 knc_pmu_ack_status(status);
233 if (++loops > 100) {
234 WARN_ONCE(1, "perf: irq loop stuck!\n");
235 perf_event_print_debug();
236 goto done;
237 }
238
239 inc_irq_stat(apic_perf_irqs);
240
241 for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
242 struct perf_event *event = cpuc->events[bit];
243
244 handled++;
245
246 if (!test_bit(bit, cpuc->active_mask))
247 continue;
248
249 if (!intel_pmu_save_and_restart(event))
250 continue;
251
252 perf_sample_data_init(&data, 0, event->hw.last_period);
253
254 if (perf_event_overflow(event, &data, regs))
255 x86_pmu_stop(event, 0);
256 }
257
258 /*
259 * Repeat if there is more work to be done:
260 */
261 status = knc_pmu_get_status();
262 if (status)
263 goto again;
264
265done:
266 knc_pmu_enable_all(0);
267
268 return handled;
269}
270
271
200PMU_FORMAT_ATTR(event, "config:0-7" ); 272PMU_FORMAT_ATTR(event, "config:0-7" );
201PMU_FORMAT_ATTR(umask, "config:8-15" ); 273PMU_FORMAT_ATTR(umask, "config:8-15" );
202PMU_FORMAT_ATTR(edge, "config:18" ); 274PMU_FORMAT_ATTR(edge, "config:18" );
@@ -214,7 +286,7 @@ static struct attribute *intel_knc_formats_attr[] = {
214 286
215static __initconst struct x86_pmu knc_pmu = { 287static __initconst struct x86_pmu knc_pmu = {
216 .name = "knc", 288 .name = "knc",
217 .handle_irq = x86_pmu_handle_irq, 289 .handle_irq = knc_pmu_handle_irq,
218 .disable_all = knc_pmu_disable_all, 290 .disable_all = knc_pmu_disable_all,
219 .enable_all = knc_pmu_enable_all, 291 .enable_all = knc_pmu_enable_all,
220 .enable = knc_pmu_enable_event, 292 .enable = knc_pmu_enable_event,
@@ -226,12 +298,11 @@ static __initconst struct x86_pmu knc_pmu = {
226 .event_map = knc_pmu_event_map, 298 .event_map = knc_pmu_event_map,
227 .max_events = ARRAY_SIZE(knc_perfmon_event_map), 299 .max_events = ARRAY_SIZE(knc_perfmon_event_map),
228 .apic = 1, 300 .apic = 1,
229 .max_period = (1ULL << 31) - 1, 301 .max_period = (1ULL << 39) - 1,
230 .version = 0, 302 .version = 0,
231 .num_counters = 2, 303 .num_counters = 2,
232 /* in theory 40 bits, early silicon is buggy though */ 304 .cntval_bits = 40,
233 .cntval_bits = 32, 305 .cntval_mask = (1ULL << 40) - 1,
234 .cntval_mask = (1ULL << 32) - 1,
235 .get_event_constraints = x86_get_event_constraints, 306 .get_event_constraints = x86_get_event_constraints,
236 .event_constraints = knc_event_constraints, 307 .event_constraints = knc_event_constraints,
237 .format_attrs = intel_knc_formats_attr, 308 .format_attrs = intel_knc_formats_attr,
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index e4dd0f7a0453..7d0270bd793e 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -8,13 +8,106 @@
8 */ 8 */
9static const u64 p6_perfmon_event_map[] = 9static const u64 p6_perfmon_event_map[] =
10{ 10{
11 [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, 11 [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, /* CPU_CLK_UNHALTED */
12 [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, 12 [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, /* INST_RETIRED */
13 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, 13 [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, /* L2_RQSTS:M:E:S:I */
14 [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, 14 [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, /* L2_RQSTS:I */
15 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, 15 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, /* BR_INST_RETIRED */
16 [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, 16 [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, /* BR_MISS_PRED_RETIRED */
17 [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, 17 [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, /* BUS_DRDY_CLOCKS */
18 [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2, /* RESOURCE_STALLS */
19
20};
21
22static __initconst u64 p6_hw_cache_event_ids
23 [PERF_COUNT_HW_CACHE_MAX]
24 [PERF_COUNT_HW_CACHE_OP_MAX]
25 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
26{
27 [ C(L1D) ] = {
28 [ C(OP_READ) ] = {
29 [ C(RESULT_ACCESS) ] = 0x0043, /* DATA_MEM_REFS */
30 [ C(RESULT_MISS) ] = 0x0045, /* DCU_LINES_IN */
31 },
32 [ C(OP_WRITE) ] = {
33 [ C(RESULT_ACCESS) ] = 0,
34 [ C(RESULT_MISS) ] = 0x0f29, /* L2_LD:M:E:S:I */
35 },
36 [ C(OP_PREFETCH) ] = {
37 [ C(RESULT_ACCESS) ] = 0,
38 [ C(RESULT_MISS) ] = 0,
39 },
40 },
41 [ C(L1I ) ] = {
42 [ C(OP_READ) ] = {
43 [ C(RESULT_ACCESS) ] = 0x0080, /* IFU_IFETCH */
44 [ C(RESULT_MISS) ] = 0x0f28, /* L2_IFETCH:M:E:S:I */
45 },
46 [ C(OP_WRITE) ] = {
47 [ C(RESULT_ACCESS) ] = -1,
48 [ C(RESULT_MISS) ] = -1,
49 },
50 [ C(OP_PREFETCH) ] = {
51 [ C(RESULT_ACCESS) ] = 0,
52 [ C(RESULT_MISS) ] = 0,
53 },
54 },
55 [ C(LL ) ] = {
56 [ C(OP_READ) ] = {
57 [ C(RESULT_ACCESS) ] = 0,
58 [ C(RESULT_MISS) ] = 0,
59 },
60 [ C(OP_WRITE) ] = {
61 [ C(RESULT_ACCESS) ] = 0,
62 [ C(RESULT_MISS) ] = 0x0025, /* L2_M_LINES_INM */
63 },
64 [ C(OP_PREFETCH) ] = {
65 [ C(RESULT_ACCESS) ] = 0,
66 [ C(RESULT_MISS) ] = 0,
67 },
68 },
69 [ C(DTLB) ] = {
70 [ C(OP_READ) ] = {
71 [ C(RESULT_ACCESS) ] = 0x0043, /* DATA_MEM_REFS */
72 [ C(RESULT_MISS) ] = 0,
73 },
74 [ C(OP_WRITE) ] = {
75 [ C(RESULT_ACCESS) ] = 0,
76 [ C(RESULT_MISS) ] = 0,
77 },
78 [ C(OP_PREFETCH) ] = {
79 [ C(RESULT_ACCESS) ] = 0,
80 [ C(RESULT_MISS) ] = 0,
81 },
82 },
83 [ C(ITLB) ] = {
84 [ C(OP_READ) ] = {
85 [ C(RESULT_ACCESS) ] = 0x0080, /* IFU_IFETCH */
86 [ C(RESULT_MISS) ] = 0x0085, /* ITLB_MISS */
87 },
88 [ C(OP_WRITE) ] = {
89 [ C(RESULT_ACCESS) ] = -1,
90 [ C(RESULT_MISS) ] = -1,
91 },
92 [ C(OP_PREFETCH) ] = {
93 [ C(RESULT_ACCESS) ] = -1,
94 [ C(RESULT_MISS) ] = -1,
95 },
96 },
97 [ C(BPU ) ] = {
98 [ C(OP_READ) ] = {
99 [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED */
100 [ C(RESULT_MISS) ] = 0x00c5, /* BR_MISS_PRED_RETIRED */
101 },
102 [ C(OP_WRITE) ] = {
103 [ C(RESULT_ACCESS) ] = -1,
104 [ C(RESULT_MISS) ] = -1,
105 },
106 [ C(OP_PREFETCH) ] = {
107 [ C(RESULT_ACCESS) ] = -1,
108 [ C(RESULT_MISS) ] = -1,
109 },
110 },
18}; 111};
19 112
20static u64 p6_pmu_event_map(int hw_event) 113static u64 p6_pmu_event_map(int hw_event)
@@ -34,7 +127,7 @@ static struct event_constraint p6_event_constraints[] =
34{ 127{
35 INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */ 128 INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */
36 INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ 129 INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
37 INTEL_EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */ 130 INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
38 INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ 131 INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
39 INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ 132 INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
40 INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ 133 INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
@@ -64,25 +157,25 @@ static void p6_pmu_enable_all(int added)
64static inline void 157static inline void
65p6_pmu_disable_event(struct perf_event *event) 158p6_pmu_disable_event(struct perf_event *event)
66{ 159{
67 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
68 struct hw_perf_event *hwc = &event->hw; 160 struct hw_perf_event *hwc = &event->hw;
69 u64 val = P6_NOP_EVENT; 161 u64 val = P6_NOP_EVENT;
70 162
71 if (cpuc->enabled)
72 val |= ARCH_PERFMON_EVENTSEL_ENABLE;
73
74 (void)wrmsrl_safe(hwc->config_base, val); 163 (void)wrmsrl_safe(hwc->config_base, val);
75} 164}
76 165
77static void p6_pmu_enable_event(struct perf_event *event) 166static void p6_pmu_enable_event(struct perf_event *event)
78{ 167{
79 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
80 struct hw_perf_event *hwc = &event->hw; 168 struct hw_perf_event *hwc = &event->hw;
81 u64 val; 169 u64 val;
82 170
83 val = hwc->config; 171 val = hwc->config;
84 if (cpuc->enabled) 172
85 val |= ARCH_PERFMON_EVENTSEL_ENABLE; 173 /*
174 * p6 only has a global event enable, set on PerfEvtSel0
175 * We "disable" events by programming P6_NOP_EVENT
176 * and we rely on p6_pmu_enable_all() being called
177 * to actually enable the events.
178 */
86 179
87 (void)wrmsrl_safe(hwc->config_base, val); 180 (void)wrmsrl_safe(hwc->config_base, val);
88} 181}
@@ -158,5 +251,9 @@ __init int p6_pmu_init(void)
158 251
159 x86_pmu = p6_pmu; 252 x86_pmu = p6_pmu;
160 253
254 memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
255 sizeof(hw_cache_event_ids));
256
257
161 return 0; 258 return 0;
162} 259}