diff --git a/arch/i386/kernel/cpu/perfctr-watchdog.c b/arch/i386/kernel/cpu/perfctr-watchdog.c index 9b5d6af..3a945f0 100644 --- a/arch/i386/kernel/cpu/perfctr-watchdog.c +++ b/arch/i386/kernel/cpu/perfctr-watchdog.c @@ -613,6 +613,17 @@ static struct wd_ops intel_arch_wd_ops = { .evntsel = MSR_ARCH_PERFMON_EVENTSEL1, }; +/* + * Check for Intel Core Duo because it has a bug with PERFEVTSEL1 + * (see Spefication Update bug AE49) and must use PERFEVTSEL0. We cannot + * use this counter on other processors supporting X86_FEATURE_ARCH_PERFMON + * because PEBS requires it. + */ +static inline int is_coreduo(void) +{ + return boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 14; +} + static void probe_nmi_watchdog(void) { switch (boot_cpu_data.x86_vendor) { @@ -623,13 +634,14 @@ static void probe_nmi_watchdog(void) wd_ops = &k7_wd_ops; break; case X86_VENDOR_INTEL: - if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { + if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON) + && !is_coreduo()) { wd_ops = &intel_arch_wd_ops; break; } switch (boot_cpu_data.x86) { case 6: - if (boot_cpu_data.x86_model > 0xd) + if (boot_cpu_data.x86_model > 0xe) return; wd_ops = &p6_wd_ops;