aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/perf_counter.c272
1 files changed, 228 insertions, 44 deletions
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index 3b65f19a6681..6ebe9abf6aef 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -28,6 +28,7 @@ static bool perf_counters_initialized __read_mostly;
28static int nr_counters_generic __read_mostly; 28static int nr_counters_generic __read_mostly;
29static u64 perf_counter_mask __read_mostly; 29static u64 perf_counter_mask __read_mostly;
30static u64 counter_value_mask __read_mostly; 30static u64 counter_value_mask __read_mostly;
31static int counter_value_bits __read_mostly;
31 32
32static int nr_counters_fixed __read_mostly; 33static int nr_counters_fixed __read_mostly;
33 34
@@ -35,7 +36,9 @@ struct cpu_hw_counters {
35 struct perf_counter *counters[X86_PMC_IDX_MAX]; 36 struct perf_counter *counters[X86_PMC_IDX_MAX];
36 unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; 37 unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
37 unsigned long interrupts; 38 unsigned long interrupts;
38 u64 global_enable; 39 u64 throttle_ctrl;
40 u64 active_mask;
41 int enabled;
39}; 42};
40 43
41/* 44/*
@@ -43,21 +46,28 @@ struct cpu_hw_counters {
43 */ 46 */
44struct pmc_x86_ops { 47struct pmc_x86_ops {
45 u64 (*save_disable_all)(void); 48 u64 (*save_disable_all)(void);
46 void (*restore_all)(u64 ctrl); 49 void (*restore_all)(u64);
50 u64 (*get_status)(u64);
51 void (*ack_status)(u64);
52 void (*enable)(int, u64);
53 void (*disable)(int, u64);
47 unsigned eventsel; 54 unsigned eventsel;
48 unsigned perfctr; 55 unsigned perfctr;
49 int (*event_map)(int event); 56 u64 (*event_map)(int);
57 u64 (*raw_event)(u64);
50 int max_events; 58 int max_events;
51}; 59};
52 60
53static struct pmc_x86_ops *pmc_ops; 61static struct pmc_x86_ops *pmc_ops;
54 62
55static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters); 63static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters) = {
64 .enabled = 1,
65};
56 66
57/* 67/*
58 * Intel PerfMon v3. Used on Core2 and later. 68 * Intel PerfMon v3. Used on Core2 and later.
59 */ 69 */
60static const int intel_perfmon_event_map[] = 70static const u64 intel_perfmon_event_map[] =
61{ 71{
62 [PERF_COUNT_CPU_CYCLES] = 0x003c, 72 [PERF_COUNT_CPU_CYCLES] = 0x003c,
63 [PERF_COUNT_INSTRUCTIONS] = 0x00c0, 73 [PERF_COUNT_INSTRUCTIONS] = 0x00c0,
@@ -68,15 +78,29 @@ static const int intel_perfmon_event_map[] =
68 [PERF_COUNT_BUS_CYCLES] = 0x013c, 78 [PERF_COUNT_BUS_CYCLES] = 0x013c,
69}; 79};
70 80
71static int pmc_intel_event_map(int event) 81static u64 pmc_intel_event_map(int event)
72{ 82{
73 return intel_perfmon_event_map[event]; 83 return intel_perfmon_event_map[event];
74} 84}
75 85
86static u64 pmc_intel_raw_event(u64 event)
87{
88#define CORE_EVNTSEL_EVENT_MASK 0x000000FF
89#define CORE_EVNTSEL_UNIT_MASK 0x0000FF00
90#define CORE_EVNTSEL_COUNTER_MASK 0xFF000000
91
92#define CORE_EVNTSEL_MASK \
93 (CORE_EVNTSEL_EVENT_MASK | \
94 CORE_EVNTSEL_UNIT_MASK | \
95 CORE_EVNTSEL_COUNTER_MASK)
96
97 return event & CORE_EVNTSEL_MASK;
98}
99
76/* 100/*
77 * AMD Performance Monitor K7 and later. 101 * AMD Performance Monitor K7 and later.
78 */ 102 */
79static const int amd_perfmon_event_map[] = 103static const u64 amd_perfmon_event_map[] =
80{ 104{
81 [PERF_COUNT_CPU_CYCLES] = 0x0076, 105 [PERF_COUNT_CPU_CYCLES] = 0x0076,
82 [PERF_COUNT_INSTRUCTIONS] = 0x00c0, 106 [PERF_COUNT_INSTRUCTIONS] = 0x00c0,
@@ -86,11 +110,25 @@ static const int amd_perfmon_event_map[] =
86 [PERF_COUNT_BRANCH_MISSES] = 0x00c5, 110 [PERF_COUNT_BRANCH_MISSES] = 0x00c5,
87}; 111};
88 112
89static int pmc_amd_event_map(int event) 113static u64 pmc_amd_event_map(int event)
90{ 114{
91 return amd_perfmon_event_map[event]; 115 return amd_perfmon_event_map[event];
92} 116}
93 117
118static u64 pmc_amd_raw_event(u64 event)
119{
120#define K7_EVNTSEL_EVENT_MASK 0x7000000FF
121#define K7_EVNTSEL_UNIT_MASK 0x00000FF00
122#define K7_EVNTSEL_COUNTER_MASK 0x0FF000000
123
124#define K7_EVNTSEL_MASK \
125 (K7_EVNTSEL_EVENT_MASK | \
126 K7_EVNTSEL_UNIT_MASK | \
127 K7_EVNTSEL_COUNTER_MASK)
128
129 return event & K7_EVNTSEL_MASK;
130}
131
94/* 132/*
95 * Propagate counter elapsed time into the generic counter. 133 * Propagate counter elapsed time into the generic counter.
96 * Can only be executed on the CPU where the counter is active. 134 * Can only be executed on the CPU where the counter is active.
@@ -179,7 +217,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
179 * Raw event type provide the config in the event structure 217 * Raw event type provide the config in the event structure
180 */ 218 */
181 if (hw_event->raw) { 219 if (hw_event->raw) {
182 hwc->config |= hw_event->type; 220 hwc->config |= pmc_ops->raw_event(hw_event->type);
183 } else { 221 } else {
184 if (hw_event->type >= pmc_ops->max_events) 222 if (hw_event->type >= pmc_ops->max_events)
185 return -EINVAL; 223 return -EINVAL;
@@ -205,18 +243,24 @@ static u64 pmc_intel_save_disable_all(void)
205 243
206static u64 pmc_amd_save_disable_all(void) 244static u64 pmc_amd_save_disable_all(void)
207{ 245{
208 int idx; 246 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
209 u64 val, ctrl = 0; 247 int enabled, idx;
248
249 enabled = cpuc->enabled;
250 cpuc->enabled = 0;
251 barrier();
210 252
211 for (idx = 0; idx < nr_counters_generic; idx++) { 253 for (idx = 0; idx < nr_counters_generic; idx++) {
254 u64 val;
255
212 rdmsrl(MSR_K7_EVNTSEL0 + idx, val); 256 rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
213 if (val & ARCH_PERFMON_EVENTSEL0_ENABLE) 257 if (val & ARCH_PERFMON_EVENTSEL0_ENABLE) {
214 ctrl |= (1 << idx); 258 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
215 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; 259 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
216 wrmsrl(MSR_K7_EVNTSEL0 + idx, val); 260 }
217 } 261 }
218 262
219 return ctrl; 263 return enabled;
220} 264}
221 265
222u64 hw_perf_save_disable(void) 266u64 hw_perf_save_disable(void)
@@ -226,6 +270,9 @@ u64 hw_perf_save_disable(void)
226 270
227 return pmc_ops->save_disable_all(); 271 return pmc_ops->save_disable_all();
228} 272}
273/*
274 * Exported because of ACPI idle
275 */
229EXPORT_SYMBOL_GPL(hw_perf_save_disable); 276EXPORT_SYMBOL_GPL(hw_perf_save_disable);
230 277
231static void pmc_intel_restore_all(u64 ctrl) 278static void pmc_intel_restore_all(u64 ctrl)
@@ -235,11 +282,18 @@ static void pmc_intel_restore_all(u64 ctrl)
235 282
236static void pmc_amd_restore_all(u64 ctrl) 283static void pmc_amd_restore_all(u64 ctrl)
237{ 284{
238 u64 val; 285 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
239 int idx; 286 int idx;
240 287
288 cpuc->enabled = ctrl;
289 barrier();
290 if (!ctrl)
291 return;
292
241 for (idx = 0; idx < nr_counters_generic; idx++) { 293 for (idx = 0; idx < nr_counters_generic; idx++) {
242 if (ctrl & (1 << idx)) { 294 if (test_bit(idx, (unsigned long *)&cpuc->active_mask)) {
295 u64 val;
296
243 rdmsrl(MSR_K7_EVNTSEL0 + idx, val); 297 rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
244 val |= ARCH_PERFMON_EVENTSEL0_ENABLE; 298 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
245 wrmsrl(MSR_K7_EVNTSEL0 + idx, val); 299 wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
@@ -254,8 +308,112 @@ void hw_perf_restore(u64 ctrl)
254 308
255 pmc_ops->restore_all(ctrl); 309 pmc_ops->restore_all(ctrl);
256} 310}
311/*
312 * Exported because of ACPI idle
313 */
257EXPORT_SYMBOL_GPL(hw_perf_restore); 314EXPORT_SYMBOL_GPL(hw_perf_restore);
258 315
316static u64 pmc_intel_get_status(u64 mask)
317{
318 u64 status;
319
320 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
321
322 return status;
323}
324
325static u64 pmc_amd_get_status(u64 mask)
326{
327 u64 status = 0;
328 int idx;
329
330 for (idx = 0; idx < nr_counters_generic; idx++) {
331 s64 val;
332
333 if (!(mask & (1 << idx)))
334 continue;
335
336 rdmsrl(MSR_K7_PERFCTR0 + idx, val);
337 val <<= (64 - counter_value_bits);
338 if (val >= 0)
339 status |= (1 << idx);
340 }
341
342 return status;
343}
344
345static u64 hw_perf_get_status(u64 mask)
346{
347 if (unlikely(!perf_counters_initialized))
348 return 0;
349
350 return pmc_ops->get_status(mask);
351}
352
353static void pmc_intel_ack_status(u64 ack)
354{
355 wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack);
356}
357
358static void pmc_amd_ack_status(u64 ack)
359{
360}
361
362static void hw_perf_ack_status(u64 ack)
363{
364 if (unlikely(!perf_counters_initialized))
365 return;
366
367 pmc_ops->ack_status(ack);
368}
369
370static void pmc_intel_enable(int idx, u64 config)
371{
372 wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + idx,
373 config | ARCH_PERFMON_EVENTSEL0_ENABLE);
374}
375
376static void pmc_amd_enable(int idx, u64 config)
377{
378 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
379
380 set_bit(idx, (unsigned long *)&cpuc->active_mask);
381 if (cpuc->enabled)
382 config |= ARCH_PERFMON_EVENTSEL0_ENABLE;
383
384 wrmsrl(MSR_K7_EVNTSEL0 + idx, config);
385}
386
387static void hw_perf_enable(int idx, u64 config)
388{
389 if (unlikely(!perf_counters_initialized))
390 return;
391
392 pmc_ops->enable(idx, config);
393}
394
395static void pmc_intel_disable(int idx, u64 config)
396{
397 wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + idx, config);
398}
399
400static void pmc_amd_disable(int idx, u64 config)
401{
402 struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
403
404 clear_bit(idx, (unsigned long *)&cpuc->active_mask);
405 wrmsrl(MSR_K7_EVNTSEL0 + idx, config);
406
407}
408
409static void hw_perf_disable(int idx, u64 config)
410{
411 if (unlikely(!perf_counters_initialized))
412 return;
413
414 pmc_ops->disable(idx, config);
415}
416
259static inline void 417static inline void
260__pmc_fixed_disable(struct perf_counter *counter, 418__pmc_fixed_disable(struct perf_counter *counter,
261 struct hw_perf_counter *hwc, unsigned int __idx) 419 struct hw_perf_counter *hwc, unsigned int __idx)
@@ -278,7 +436,7 @@ __pmc_generic_disable(struct perf_counter *counter,
278 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) 436 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL))
279 __pmc_fixed_disable(counter, hwc, idx); 437 __pmc_fixed_disable(counter, hwc, idx);
280 else 438 else
281 wrmsr_safe(hwc->config_base + idx, hwc->config, 0); 439 hw_perf_disable(idx, hwc->config);
282} 440}
283 441
284static DEFINE_PER_CPU(u64, prev_left[X86_PMC_IDX_MAX]); 442static DEFINE_PER_CPU(u64, prev_left[X86_PMC_IDX_MAX]);
@@ -354,8 +512,7 @@ __pmc_generic_enable(struct perf_counter *counter,
354 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) 512 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL))
355 __pmc_fixed_enable(counter, hwc, idx); 513 __pmc_fixed_enable(counter, hwc, idx);
356 else 514 else
357 wrmsr(hwc->config_base + idx, 515 hw_perf_enable(idx, hwc->config);
358 hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE, 0);
359} 516}
360 517
361static int 518static int
@@ -567,22 +724,20 @@ perf_handle_group(struct perf_counter *sibling, u64 *status, u64 *overflown)
567 * This handler is triggered by the local APIC, so the APIC IRQ handling 724 * This handler is triggered by the local APIC, so the APIC IRQ handling
568 * rules apply: 725 * rules apply:
569 */ 726 */
570static void __smp_perf_counter_interrupt(struct pt_regs *regs, int nmi) 727static int __smp_perf_counter_interrupt(struct pt_regs *regs, int nmi)
571{ 728{
572 int bit, cpu = smp_processor_id(); 729 int bit, cpu = smp_processor_id();
573 u64 ack, status; 730 u64 ack, status;
574 struct cpu_hw_counters *cpuc = &per_cpu(cpu_hw_counters, cpu); 731 struct cpu_hw_counters *cpuc = &per_cpu(cpu_hw_counters, cpu);
732 int ret = 0;
575 733
576 rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, cpuc->global_enable); 734 cpuc->throttle_ctrl = hw_perf_save_disable();
577
578 /* Disable counters globally */
579 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
580 ack_APIC_irq();
581 735
582 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); 736 status = hw_perf_get_status(cpuc->throttle_ctrl);
583 if (!status) 737 if (!status)
584 goto out; 738 goto out;
585 739
740 ret = 1;
586again: 741again:
587 inc_irq_stat(apic_perf_irqs); 742 inc_irq_stat(apic_perf_irqs);
588 ack = status; 743 ack = status;
@@ -618,12 +773,12 @@ again:
618 } 773 }
619 } 774 }
620 775
621 wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack); 776 hw_perf_ack_status(ack);
622 777
623 /* 778 /*
624 * Repeat if there is more work to be done: 779 * Repeat if there is more work to be done:
625 */ 780 */
626 rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); 781 status = hw_perf_get_status(cpuc->throttle_ctrl);
627 if (status) 782 if (status)
628 goto again; 783 goto again;
629out: 784out:
@@ -631,32 +786,27 @@ out:
631 * Restore - do not reenable when global enable is off or throttled: 786 * Restore - do not reenable when global enable is off or throttled:
632 */ 787 */
633 if (++cpuc->interrupts < PERFMON_MAX_INTERRUPTS) 788 if (++cpuc->interrupts < PERFMON_MAX_INTERRUPTS)
634 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, cpuc->global_enable); 789 hw_perf_restore(cpuc->throttle_ctrl);
790
791 return ret;
635} 792}
636 793
637void perf_counter_unthrottle(void) 794void perf_counter_unthrottle(void)
638{ 795{
639 struct cpu_hw_counters *cpuc; 796 struct cpu_hw_counters *cpuc;
640 u64 global_enable;
641 797
642 if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) 798 if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
643 return; 799 return;
644 800
645 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
646 return;
647
648 if (unlikely(!perf_counters_initialized)) 801 if (unlikely(!perf_counters_initialized))
649 return; 802 return;
650 803
651 cpuc = &per_cpu(cpu_hw_counters, smp_processor_id()); 804 cpuc = &__get_cpu_var(cpu_hw_counters);
652 if (cpuc->interrupts >= PERFMON_MAX_INTERRUPTS) { 805 if (cpuc->interrupts >= PERFMON_MAX_INTERRUPTS) {
653 if (printk_ratelimit()) 806 if (printk_ratelimit())
654 printk(KERN_WARNING "PERFMON: max interrupts exceeded!\n"); 807 printk(KERN_WARNING "PERFMON: max interrupts exceeded!\n");
655 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, cpuc->global_enable); 808 hw_perf_restore(cpuc->throttle_ctrl);
656 } 809 }
657 rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, global_enable);
658 if (unlikely(cpuc->global_enable && !global_enable))
659 wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, cpuc->global_enable);
660 cpuc->interrupts = 0; 810 cpuc->interrupts = 0;
661} 811}
662 812
@@ -664,8 +814,8 @@ void smp_perf_counter_interrupt(struct pt_regs *regs)
664{ 814{
665 irq_enter(); 815 irq_enter();
666 apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR); 816 apic_write(APIC_LVTPC, LOCAL_PERF_VECTOR);
817 ack_APIC_irq();
667 __smp_perf_counter_interrupt(regs, 0); 818 __smp_perf_counter_interrupt(regs, 0);
668
669 irq_exit(); 819 irq_exit();
670} 820}
671 821
@@ -722,16 +872,23 @@ perf_counter_nmi_handler(struct notifier_block *self,
722{ 872{
723 struct die_args *args = __args; 873 struct die_args *args = __args;
724 struct pt_regs *regs; 874 struct pt_regs *regs;
875 int ret;
876
877 switch (cmd) {
878 case DIE_NMI:
879 case DIE_NMI_IPI:
880 break;
725 881
726 if (likely(cmd != DIE_NMI_IPI)) 882 default:
727 return NOTIFY_DONE; 883 return NOTIFY_DONE;
884 }
728 885
729 regs = args->regs; 886 regs = args->regs;
730 887
731 apic_write(APIC_LVTPC, APIC_DM_NMI); 888 apic_write(APIC_LVTPC, APIC_DM_NMI);
732 __smp_perf_counter_interrupt(regs, 1); 889 ret = __smp_perf_counter_interrupt(regs, 1);
733 890
734 return NOTIFY_STOP; 891 return ret ? NOTIFY_STOP : NOTIFY_OK;
735} 892}
736 893
737static __read_mostly struct notifier_block perf_counter_nmi_notifier = { 894static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
@@ -743,18 +900,28 @@ static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
743static struct pmc_x86_ops pmc_intel_ops = { 900static struct pmc_x86_ops pmc_intel_ops = {
744 .save_disable_all = pmc_intel_save_disable_all, 901 .save_disable_all = pmc_intel_save_disable_all,
745 .restore_all = pmc_intel_restore_all, 902 .restore_all = pmc_intel_restore_all,
903 .get_status = pmc_intel_get_status,
904 .ack_status = pmc_intel_ack_status,
905 .enable = pmc_intel_enable,
906 .disable = pmc_intel_disable,
746 .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, 907 .eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
747 .perfctr = MSR_ARCH_PERFMON_PERFCTR0, 908 .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
748 .event_map = pmc_intel_event_map, 909 .event_map = pmc_intel_event_map,
910 .raw_event = pmc_intel_raw_event,
749 .max_events = ARRAY_SIZE(intel_perfmon_event_map), 911 .max_events = ARRAY_SIZE(intel_perfmon_event_map),
750}; 912};
751 913
752static struct pmc_x86_ops pmc_amd_ops = { 914static struct pmc_x86_ops pmc_amd_ops = {
753 .save_disable_all = pmc_amd_save_disable_all, 915 .save_disable_all = pmc_amd_save_disable_all,
754 .restore_all = pmc_amd_restore_all, 916 .restore_all = pmc_amd_restore_all,
917 .get_status = pmc_amd_get_status,
918 .ack_status = pmc_amd_ack_status,
919 .enable = pmc_amd_enable,
920 .disable = pmc_amd_disable,
755 .eventsel = MSR_K7_EVNTSEL0, 921 .eventsel = MSR_K7_EVNTSEL0,
756 .perfctr = MSR_K7_PERFCTR0, 922 .perfctr = MSR_K7_PERFCTR0,
757 .event_map = pmc_amd_event_map, 923 .event_map = pmc_amd_event_map,
924 .raw_event = pmc_amd_raw_event,
758 .max_events = ARRAY_SIZE(amd_perfmon_event_map), 925 .max_events = ARRAY_SIZE(amd_perfmon_event_map),
759}; 926};
760 927
@@ -787,8 +954,25 @@ static struct pmc_x86_ops *pmc_intel_init(void)
787 954
788static struct pmc_x86_ops *pmc_amd_init(void) 955static struct pmc_x86_ops *pmc_amd_init(void)
789{ 956{
957 u64 old;
958 int bits;
959
790 nr_counters_generic = 4; 960 nr_counters_generic = 4;
791 nr_counters_fixed = 0; 961 nr_counters_fixed = 0;
962 counter_value_mask = ~0ULL;
963
964 rdmsrl(MSR_K7_PERFCTR0, old);
965 wrmsrl(MSR_K7_PERFCTR0, counter_value_mask);
966 /*
967 * read the truncated mask
968 */
969 rdmsrl(MSR_K7_PERFCTR0, counter_value_mask);
970 wrmsrl(MSR_K7_PERFCTR0, old);
971
972 bits = 32 + fls(counter_value_mask >> 32);
973 if (bits == 32)
974 bits = fls((u32)counter_value_mask);
975 counter_value_bits = bits;
792 976
793 pr_info("AMD Performance Monitoring support detected.\n"); 977 pr_info("AMD Performance Monitoring support detected.\n");
794 978