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; |
