Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

i386: Fix perfctr watchdog on core duo

Fix the NMI watchdog on Intel CoreDuo processor where the kernel would
get stuck during boot. The issue is related to errata AE49, where the
PERFEVTSEL1 counter does not have a working enable bit. Thus it is not
possible to use it for NMI.

The patch creates a dedicated wd_ops for CoreDuo which falls back to
using PERFEVTSEL0. The other Intel processors supporting the
architectural PMU will keep on using PERFEVTSEL1 as this allows other
subsystems, such as perfmon, to use PERFEVTSEL0 for PEBS monitoring in
particular. Bug initially reported by Daniel Walker.

AK: Added comments

Signed-off-by: Stephane Eranian <eranian@hpl.hp.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Stephane Eranian and committed by
Linus Torvalds
23d5ea5d b8da0d1c

+22 -6
+22 -6
arch/i386/kernel/cpu/perfctr-watchdog.c
··· 263 263 unsigned int evntsel; 264 264 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); 265 265 266 - perfctr_msr = MSR_K7_PERFCTR0; 267 - evntsel_msr = MSR_K7_EVNTSEL0; 266 + perfctr_msr = wd_ops->perfctr; 267 + evntsel_msr = wd_ops->evntsel; 268 268 269 269 wrmsrl(perfctr_msr, 0UL); 270 270 ··· 343 343 unsigned int evntsel; 344 344 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); 345 345 346 - perfctr_msr = MSR_P6_PERFCTR0; 347 - evntsel_msr = MSR_P6_EVNTSEL0; 346 + perfctr_msr = wd_ops->perfctr; 347 + evntsel_msr = wd_ops->evntsel; 348 348 349 349 /* KVM doesn't implement this MSR */ 350 350 if (wrmsr_safe(perfctr_msr, 0, 0) < 0) ··· 569 569 (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT)) 570 570 return 0; 571 571 572 - perfctr_msr = MSR_ARCH_PERFMON_PERFCTR1; 573 - evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL1; 572 + perfctr_msr = wd_ops->perfctr; 573 + evntsel_msr = wd_ops->evntsel; 574 574 575 575 wrmsrl(perfctr_msr, 0UL); 576 576 ··· 605 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 618 static void probe_nmi_watchdog(void) 609 619 { 610 620 switch (boot_cpu_data.x86_vendor) { ··· 625 615 wd_ops = &k7_wd_ops; 626 616 break; 627 617 case X86_VENDOR_INTEL: 618 + /* Work around Core Duo (Yonah) errata AE49 where perfctr1 619 + doesn't have a working enable bit. */ 620 + if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14) { 621 + wd_ops = &coreduo_wd_ops; 622 + break; 623 + } 628 624 if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { 629 625 wd_ops = &intel_arch_wd_ops; 630 626 break;