summaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorH. Peter Anvin2012-11-27 17:54:36 +0100
committerH. Peter Anvin2012-11-27 18:26:33 +0100
commit6662c34fa9c60a48aaa5879cb229cd9a84de9c22 (patch)
treeb43ec727d60ebd16cb648eda12e149b10113091d /arch/x86
parentx86, kvm: Remove incorrect redundant assembly constraint (diff)
downloadkernel-qcow2-linux-6662c34fa9c60a48aaa5879cb229cd9a84de9c22.tar.gz
kernel-qcow2-linux-6662c34fa9c60a48aaa5879cb229cd9a84de9c22.tar.xz
kernel-qcow2-linux-6662c34fa9c60a48aaa5879cb229cd9a84de9c22.zip
x86-32: Unbreak booting on some 486 clones
There appear to have been some 486 clones, including the "enhanced" version of Am486, which have CPUID but not CR4. These 486 clones had only the FPU flag, if any, unlike the Intel 486s with CPUID, which also had VME and therefore needed CR4. Therefore, look at the basic CPUID flags and require at least one bit other than bit 0 before we modify CR4. Thanks to Christian Ludloff of sandpile.org for confirming this as a problem. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/head_32.S9
1 files changed, 7 insertions, 2 deletions
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 957a47aec64e..4dac2f68ed4a 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -292,8 +292,8 @@ default_entry:
* be using the global pages.
*
* NOTE! If we are on a 486 we may have no cr4 at all!
- * Specifically, cr4 exists if and only if CPUID exists,
- * which in turn exists if and only if EFLAGS.ID exists.
+ * Specifically, cr4 exists if and only if CPUID exists
+ * and has flags other than the FPU flag set.
*/
movl $X86_EFLAGS_ID,%ecx
pushl %ecx
@@ -308,6 +308,11 @@ default_entry:
testl %ecx,%eax
jz 6f # No ID flag = no CPUID = no CR4
+ movl $1,%eax
+ cpuid
+ andl $~1,%edx # Ignore CPUID.FPU
+ jz 6f # No flags or only CPUID.FPU = no CR4
+
movl pa(mmu_cr4_features),%eax
movl %eax,%cr4