clockevents_register_device(levt);
}
-/*
- * Detect systems with known broken BIOS implementations
- */
-static int __init lapic_check_broken_bios(struct dmi_system_id *d)
-{
- printk(KERN_NOTICE "%s detected: disabling lapic timer.\n",
- d->ident);
- local_apic_timer_disabled = 1;
- return 0;
-}
-
-static struct dmi_system_id __initdata broken_bios_dmi_table[] = {
- {
- /*
- * BIOS exports only C1 state, but uses deeper power
- * modes behind the kernels back.
- */
- .callback = lapic_check_broken_bios,
- .ident = "HP nx6325",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
- },
- },
- {}
-};
-
/*
* In this functions we calibrate APIC bus clocks to the external timer.
*
long delta, deltapm;
int pm_referenced = 0;
- /* Detect know broken systems */
- dmi_check_system(broken_bios_dmi_table);
+ if (boot_cpu_has(X86_FEATURE_LAPIC_TIMER_BROKEN))
+ local_apic_timer_disabled = 1;
/*
* The local apic timer can be disabled via the kernel
- * commandline or from the dmi quirk above. Register the lapic
+ * commandline or from the test above. Register the lapic
* timer as a dummy clock event source on SMP systems, so the
* broadcast mechanism is used. On UP systems simply ignore it.
*/
extern void vide(void);
__asm__(".align 4\nvide: ret");
+#define ENABLE_C1E_MASK 0x18000000
+#define CPUID_PROCESSOR_SIGNATURE 1
+#define CPUID_XFAM 0x0ff00000
+#define CPUID_XFAM_K8 0x00000000
+#define CPUID_XFAM_10H 0x00100000
+#define CPUID_XFAM_11H 0x00200000
+#define CPUID_XMOD 0x000f0000
+#define CPUID_XMOD_REV_F 0x00040000
+
+/* AMD systems with C1E don't have a working lAPIC timer. Check for that. */
+static __cpuinit int amd_apic_timer_broken(void)
+{
+ u32 lo, hi;
+ u32 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
+ switch (eax & CPUID_XFAM) {
+ case CPUID_XFAM_K8:
+ if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F)
+ break;
+ case CPUID_XFAM_10H:
+ case CPUID_XFAM_11H:
+ rdmsr(MSR_K8_ENABLE_C1E, lo, hi);
+ if (lo & ENABLE_C1E_MASK)
+ return 1;
+ break;
+ default:
+ /* err on the side of caution */
+ return 1;
+ }
+ return 0;
+}
+
static void __cpuinit init_amd(struct cpuinfo_x86 *c)
{
u32 l, h;
if (cpuid_eax(0x80000000) >= 0x80000006)
num_cache_leaves = 3;
+
+ if (amd_apic_timer_broken())
+ set_bit(X86_FEATURE_LAPIC_TIMER_BROKEN, c->x86_capability);
}
static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
#define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
+#define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14) /* lapic timer broken in C1 */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
#define MSR_K7_FID_VID_CTL 0xC0010041
#define MSR_K7_FID_VID_STATUS 0xC0010042
+#define MSR_K8_ENABLE_C1E 0xC0010055
+
/* extended feature register */
#define MSR_EFER 0xc0000080