Skip to content

Commit

Permalink
x86: Detect CPUID support early at boot
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Borislav Petkov authored and H. Peter Anvin committed Feb 12, 2013
1 parent 166df91 commit 9efb58d
Showing 1 changed file with 25 additions and 25 deletions.
50 changes: 25 additions & 25 deletions arch/x86/kernel/head_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -307,30 +307,39 @@ default_entry:
movl %eax,%cr0

/*
* New page tables may be in 4Mbyte page mode and may
* be using the global pages.
* We want to start out with EFLAGS unambiguously cleared. Some BIOSes leave
* 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!
* Specifically, cr4 exists if and only if CPUID exists
* and has flags other than the FPU flag set.
* 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
pushfl
popl %eax
pushl $0
popfl
popfl # set EFLAGS=ID
pushfl
popl %edx
xorl %edx,%eax
testl %ecx,%eax
jz 6f # No ID flag = no CPUID = no CR4
popl %eax # get EFLAGS
testl $X86_EFLAGS_ID,%eax # did EFLAGS.ID remained set?
jz 6f # hw disallowed setting of ID bit
# which means no CPUID and no CR4

xorl %eax,%eax
cpuid
movl %eax,pa(X86_CPUID) # save largest std CPUID function

movl $1,%eax
cpuid
andl $~1,%edx # Ignore CPUID.FPU
jz 6f # No flags or only CPUID.FPU = no CR4
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
Expand Down Expand Up @@ -377,14 +386,6 @@ default_entry:
/* Shift the stack pointer to a virtual address */
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
* in 16-bit mode for the "real" operations.
Expand Down Expand Up @@ -461,7 +462,6 @@ is486: movl $0x50022,%ecx # set AM, WP, NE and MP
xorl %eax,%eax # Clear LDT
lldt %ax

cld # gcc2 wants the direction flag cleared at all times
pushl $0 # fake return address for unwinder
jmp *(initial_code)

Expand Down

0 comments on commit 9efb58d

Please sign in to comment.