Commit 9efb58de authored by Borislav Petkov's avatar Borislav Petkov Committed by H. Peter Anvin

x86: Detect CPUID support early at boot

We detect CPUID function support on each CPU and save it for later use,
obviating the need to play the toggle EFLAGS.ID game every time. C code
is looking at ->cpuid_level anyway.
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: http://lkml.kernel.org/r/1360592538-10643-3-git-send-email-bp@alien8.deSigned-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 166df91d
...@@ -307,30 +307,39 @@ default_entry: ...@@ -307,30 +307,39 @@ default_entry:
movl %eax,%cr0 movl %eax,%cr0
/* /*
* New page tables may be in 4Mbyte page mode and may * We want to start out with EFLAGS unambiguously cleared. Some BIOSes leave
* be using the global pages. * bits like NT set. This would confuse the debugger if this code is traced. So
* initialize them properly now before switching to protected mode. That means
* DF in particular (even though we have cleared it earlier after copying the
* command line) because GCC expects it.
*/
pushl $0
popfl
/*
* New page tables may be in 4Mbyte page mode and may be using the global pages.
* *
* NOTE! If we are on a 486 we may have no cr4 at all! * NOTE! If we are on a 486 we may have no cr4 at all! Specifically, cr4 exists
* Specifically, cr4 exists if and only if CPUID exists * if and only if CPUID exists and has flags other than the FPU flag set.
* and has flags other than the FPU flag set.
*/ */
movl $-1,pa(X86_CPUID) # preset CPUID level
movl $X86_EFLAGS_ID,%ecx movl $X86_EFLAGS_ID,%ecx
pushl %ecx pushl %ecx
popfl popfl # set EFLAGS=ID
pushfl
popl %eax
pushl $0
popfl
pushfl pushfl
popl %edx popl %eax # get EFLAGS
xorl %edx,%eax testl $X86_EFLAGS_ID,%eax # did EFLAGS.ID remained set?
testl %ecx,%eax jz 6f # hw disallowed setting of ID bit
jz 6f # No ID flag = no CPUID = no CR4 # which means no CPUID and no CR4
xorl %eax,%eax
cpuid
movl %eax,pa(X86_CPUID) # save largest std CPUID function
movl $1,%eax movl $1,%eax
cpuid cpuid
andl $~1,%edx # Ignore CPUID.FPU andl $~1,%edx # Ignore CPUID.FPU
jz 6f # No flags or only CPUID.FPU = no CR4 jz 6f # No flags or only CPUID.FPU = no CR4
movl pa(mmu_cr4_features),%eax movl pa(mmu_cr4_features),%eax
movl %eax,%cr4 movl %eax,%cr4
...@@ -377,14 +386,6 @@ default_entry: ...@@ -377,14 +386,6 @@ default_entry:
/* Shift the stack pointer to a virtual address */ /* Shift the stack pointer to a virtual address */
addl $__PAGE_OFFSET, %esp addl $__PAGE_OFFSET, %esp
/*
* Initialize eflags. Some BIOS's leave bits like NT set. This would
* confuse the debugger if this code is traced.
* XXX - best to initialize before switching to protected mode.
*/
pushl $0
popfl
/* /*
* start system 32-bit setup. We need to re-do some of the things done * start system 32-bit setup. We need to re-do some of the things done
* in 16-bit mode for the "real" operations. * in 16-bit mode for the "real" operations.
...@@ -461,7 +462,6 @@ is486: movl $0x50022,%ecx # set AM, WP, NE and MP ...@@ -461,7 +462,6 @@ is486: movl $0x50022,%ecx # set AM, WP, NE and MP
xorl %eax,%eax # Clear LDT xorl %eax,%eax # Clear LDT
lldt %ax lldt %ax
cld # gcc2 wants the direction flag cleared at all times
pushl $0 # fake return address for unwinder pushl $0 # fake return address for unwinder
jmp *(initial_code) jmp *(initial_code)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment