2007-05-02 19:27:12 +02:00
/*
* Copyright ( C ) 1994 Linus Torvalds
*
* Cyrix stuff , June 1998 by :
* - Rafael R . Reilova ( moved everything from head . S ) ,
* < rreilova @ ececs . uc . edu >
* - Channing Corn ( tests & fixes ) ,
* - Andrew D . Balsa ( code cleanup ) .
*/
# include <linux/init.h>
# include <linux/utsname.h>
2007-07-31 00:39:20 -07:00
# include <asm/bugs.h>
2007-05-02 19:27:12 +02:00
# include <asm/processor.h>
2008-01-30 13:30:39 +01:00
# include <asm/processor-flags.h>
2007-05-02 19:27:12 +02:00
# include <asm/i387.h>
# include <asm/msr.h>
# include <asm/paravirt.h>
# include <asm/alternative.h>
static double __initdata x = 4195835.0 ;
static double __initdata y = 3145727.0 ;
/*
* This used to check for exceptions . .
* However , it turns out that to support that ,
* the XMM trap handlers basically had to
* be buggy . So let ' s have a correct XMM trap
* handler , and forget about printing out
* some status at boot .
*
* We should really only care about bugs here
* anyway . Not features .
*/
static void __init check_fpu ( void )
{
2008-07-31 23:43:44 +02:00
s32 fdiv_bug ;
2011-06-30 17:19:32 -07:00
kernel_fpu_begin ( ) ;
2008-05-17 22:48:13 +02:00
/*
* trap_init ( ) enabled FXSR and company _before_ testing for FP
* problems here .
*
2013-03-20 15:07:25 +01:00
* Test for the divl bug : http : //en.wikipedia.org/wiki/Fdiv_bug
2008-05-17 22:48:13 +02:00
*/
2007-05-02 19:27:12 +02:00
__asm__ ( " fninit \n \t "
" fldl %1 \n \t "
" fdivl %2 \n \t "
" fmull %2 \n \t "
" fldl %1 \n \t "
" fsubp %%st,%%st(1) \n \t "
" fistpl %0 \n \t "
" fwait \n \t "
" fninit "
2008-07-31 23:43:44 +02:00
: " =m " ( * & fdiv_bug )
2007-05-02 19:27:12 +02:00
: " m " ( * & x ) , " m " ( * & y ) ) ;
2008-07-31 23:43:44 +02:00
2011-06-30 17:19:32 -07:00
kernel_fpu_end ( ) ;
2013-03-20 15:07:25 +01:00
if ( fdiv_bug ) {
set_cpu_bug ( & boot_cpu_data , X86_BUG_FDIV ) ;
2012-05-21 19:50:07 -07:00
pr_warn ( " Hmm, FPU with FDIV bug \n " ) ;
2013-03-20 15:07:25 +01:00
}
2007-05-02 19:27:12 +02:00
}
void __init check_bugs ( void )
{
identify_boot_cpu ( ) ;
# ifndef CONFIG_SMP
2012-05-21 19:50:07 -07:00
pr_info ( " CPU: " ) ;
2007-05-02 19:27:12 +02:00
print_cpu_info ( & boot_cpu_data ) ;
# endif
2013-04-08 17:57:44 +02:00
/*
* Check whether we are able to run this kernel safely on SMP .
*
* - i386 is no longer supported .
* - In order to run on anything without a TSC , we need to be
* compiled for a i486 .
*/
if ( boot_cpu_data . x86 < 4 )
panic ( " Kernel requires i486+ for 'invlpg' and other features " ) ;
2008-05-17 22:48:13 +02:00
init_utsname ( ) - > machine [ 1 ] =
' 0 ' + ( boot_cpu_data . x86 > 6 ? 6 : boot_cpu_data . x86 ) ;
2007-05-02 19:27:12 +02:00
alternative_instructions ( ) ;
2012-08-24 14:13:02 -07:00
/*
* kernel_fpu_begin / end ( ) in check_fpu ( ) relies on the patched
* alternative instructions .
*/
2013-04-29 16:04:20 +02:00
if ( cpu_has_fpu )
check_fpu ( ) ;
2007-05-02 19:27:12 +02:00
}