|
@@ -18,6 +18,7 @@
|
|
|
#include <asm/mtrr.h>
|
|
|
#include <asm/mce.h>
|
|
|
#include <asm/pat.h>
|
|
|
+#include <asm/asm.h>
|
|
|
#include <asm/numa.h>
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
#include <asm/mpspec.h>
|
|
@@ -215,6 +216,39 @@ static void __init early_cpu_support_print(void)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * The NOPL instruction is supposed to exist on all CPUs with
|
|
|
+ * family >= 6, unfortunately, that's not true in practice because
|
|
|
+ * of early VIA chips and (more importantly) broken virtualizers that
|
|
|
+ * are not easy to detect. Hence, probe for it based on first
|
|
|
+ * principles.
|
|
|
+ *
|
|
|
+ * Note: no 64-bit chip is known to lack these, but put the code here
|
|
|
+ * for consistency with 32 bits, and to make it utterly trivial to
|
|
|
+ * diagnose the problem should it ever surface.
|
|
|
+ */
|
|
|
+static void __cpuinit detect_nopl(struct cpuinfo_x86 *c)
|
|
|
+{
|
|
|
+ const u32 nopl_signature = 0x888c53b1; /* Random number */
|
|
|
+ u32 has_nopl = nopl_signature;
|
|
|
+
|
|
|
+ clear_cpu_cap(c, X86_FEATURE_NOPL);
|
|
|
+ if (c->x86 >= 6) {
|
|
|
+ asm volatile("\n"
|
|
|
+ "1: .byte 0x0f,0x1f,0xc0\n" /* nopl %eax */
|
|
|
+ "2:\n"
|
|
|
+ " .section .fixup,\"ax\"\n"
|
|
|
+ "3: xor %0,%0\n"
|
|
|
+ " jmp 2b\n"
|
|
|
+ " .previous\n"
|
|
|
+ _ASM_EXTABLE(1b,3b)
|
|
|
+ : "+a" (has_nopl));
|
|
|
+
|
|
|
+ if (has_nopl == nopl_signature)
|
|
|
+ set_cpu_cap(c, X86_FEATURE_NOPL);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c);
|
|
|
|
|
|
void __init early_cpu_init(void)
|
|
@@ -313,6 +347,8 @@ static void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
|
|
|
c->x86_phys_bits = eax & 0xff;
|
|
|
}
|
|
|
|
|
|
+ detect_nopl(c);
|
|
|
+
|
|
|
if (c->x86_vendor != X86_VENDOR_UNKNOWN &&
|
|
|
cpu_devs[c->x86_vendor]->c_early_init)
|
|
|
cpu_devs[c->x86_vendor]->c_early_init(c);
|