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: Borislav Petkov <bp@suse.de> Link: http://lkml.kernel.org/r/1360592538-10643-3-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
166df91daf
commit
9efb58de91
@ -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
|
||||||
* NOTE! If we are on a 486 we may have no cr4 at all!
|
* DF in particular (even though we have cleared it earlier after copying the
|
||||||
* Specifically, cr4 exists if and only if CPUID exists
|
* command line) because GCC expects it.
|
||||||
* and has flags other than the FPU flag set.
|
|
||||||
*/
|
*/
|
||||||
movl $X86_EFLAGS_ID,%ecx
|
|
||||||
pushl %ecx
|
|
||||||
popfl
|
|
||||||
pushfl
|
|
||||||
popl %eax
|
|
||||||
pushl $0
|
pushl $0
|
||||||
popfl
|
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! Specifically, cr4 exists
|
||||||
|
* if and only if CPUID exists and has flags other than the FPU flag set.
|
||||||
|
*/
|
||||||
|
movl $-1,pa(X86_CPUID) # preset CPUID level
|
||||||
|
movl $X86_EFLAGS_ID,%ecx
|
||||||
|
pushl %ecx
|
||||||
|
popfl # set EFLAGS=ID
|
||||||
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:
|
|||||||
/* 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
|
|||||||
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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user