diff options
-rw-r--r-- | arch/i386/kernel/cpu/perfctr-watchdog.c | 28 |
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 | ||
608 | static 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 | |||
608 | static void probe_nmi_watchdog(void) | 618 | static 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; |