aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/cpu/perfctr-watchdog.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/arch/i386/kernel/cpu/perfctr-watchdog.c b/arch/i386/kernel/cpu/perfctr-watchdog.c
index 4be488e73bee..93fecd4b03de 100644
--- a/arch/i386/kernel/cpu/perfctr-watchdog.c
+++ b/arch/i386/kernel/cpu/perfctr-watchdog.c
@@ -263,8 +263,8 @@ static int setup_k7_watchdog(unsigned nmi_hz)
263 unsigned int evntsel; 263 unsigned int evntsel;
264 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); 264 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
265 265
266 perfctr_msr = MSR_K7_PERFCTR0; 266 perfctr_msr = wd_ops->perfctr;
267 evntsel_msr = MSR_K7_EVNTSEL0; 267 evntsel_msr = wd_ops->evntsel;
268 268
269 wrmsrl(perfctr_msr, 0UL); 269 wrmsrl(perfctr_msr, 0UL);
270 270
@@ -343,8 +343,8 @@ static int setup_p6_watchdog(unsigned nmi_hz)
343 unsigned int evntsel; 343 unsigned int evntsel;
344 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); 344 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
345 345
346 perfctr_msr = MSR_P6_PERFCTR0; 346 perfctr_msr = wd_ops->perfctr;
347 evntsel_msr = MSR_P6_EVNTSEL0; 347 evntsel_msr = wd_ops->evntsel;
348 348
349 /* KVM doesn't implement this MSR */ 349 /* KVM doesn't implement this MSR */
350 if (wrmsr_safe(perfctr_msr, 0, 0) < 0) 350 if (wrmsr_safe(perfctr_msr, 0, 0) < 0)
@@ -569,8 +569,8 @@ static int setup_intel_arch_watchdog(unsigned nmi_hz)
569 (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT)) 569 (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
570 return 0; 570 return 0;
571 571
572 perfctr_msr = MSR_ARCH_PERFMON_PERFCTR1; 572 perfctr_msr = wd_ops->perfctr;
573 evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL1; 573 evntsel_msr = wd_ops->evntsel;
574 574
575 wrmsrl(perfctr_msr, 0UL); 575 wrmsrl(perfctr_msr, 0UL);
576 576
@@ -605,6 +605,16 @@ static struct wd_ops intel_arch_wd_ops = {
605 .evntsel = MSR_ARCH_PERFMON_EVENTSEL1, 605 .evntsel = MSR_ARCH_PERFMON_EVENTSEL1,
606}; 606};
607 607
608static struct wd_ops coreduo_wd_ops = {
609 .reserve = single_msr_reserve,
610 .unreserve = single_msr_unreserve,
611 .setup = setup_intel_arch_watchdog,
612 .rearm = p6_rearm,
613 .stop = single_msr_stop_watchdog,
614 .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
615 .evntsel = MSR_ARCH_PERFMON_EVENTSEL0,
616};
617
608static void probe_nmi_watchdog(void) 618static void probe_nmi_watchdog(void)
609{ 619{
610 switch (boot_cpu_data.x86_vendor) { 620 switch (boot_cpu_data.x86_vendor) {
@@ -615,6 +625,12 @@ static void probe_nmi_watchdog(void)
615 wd_ops = &k7_wd_ops; 625 wd_ops = &k7_wd_ops;
616 break; 626 break;
617 case X86_VENDOR_INTEL: 627 case X86_VENDOR_INTEL:
628 /* Work around Core Duo (Yonah) errata AE49 where perfctr1
629 doesn't have a working enable bit. */
630 if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) {
631 wd_ops = &coreduo_wd_ops;
632 break;
633 }
618 if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { 634 if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
619 wd_ops = &intel_arch_wd_ops; 635 wd_ops = &intel_arch_wd_ops;
620 break; 636 break;