2007-05-02 21:27:08 +04:00
/ *
*
* verify_ c p u . S - C o d e f o r c p u l o n g m o d e a n d S S E v e r i f i c a t i o n . T h i s
* code h a s b e e n b o r r o w e d f r o m b o o t / s e t u p . S a n d w a s i n t r o d u c e d b y
* Andi K l e e n .
*
* Copyright ( c ) 2 0 0 7 A n d i K l e e n ( a k @suse.de)
* Copyright ( c ) 2 0 0 7 E r i c B i e d e r m a n ( e b i e d e r m @xmission.com)
* Copyright ( c ) 2 0 0 7 V i v e k G o y a l ( v g o y a l @in.ibm.com)
2010-11-10 21:35:52 +03:00
* Copyright ( c ) 2 0 1 0 K e e s C o o k ( k e e s . c o o k @canonical.com)
2007-05-02 21:27:08 +04:00
*
* This s o u r c e c o d e i s l i c e n s e d u n d e r t h e G N U G e n e r a l P u b l i c L i c e n s e ,
* Version 2 . S e e t h e f i l e C O P Y I N G f o r m o r e d e t a i l s .
*
* This i s a c o m m o n c o d e f o r v e r i f i c a t i o n w h e t h e r C P U s u p p o r t s
* long m o d e a n d S S E o r n o t . I t i s n o t c a l l e d d i r e c t l y i n s t e a d t h i s
* file i s i n c l u d e d a t v a r i o u s p l a c e s a n d c o m p i l e d i n t h a t c o n t e x t .
2010-11-10 21:35:52 +03:00
* This f i l e i s e x p e c t e d t o r u n i n 3 2 b i t c o d e . C u r r e n t l y :
2007-05-02 21:27:08 +04:00
*
2010-11-16 21:10:04 +03:00
* arch/ x86 / b o o t / c o m p r e s s e d / h e a d _ 6 4 . S : B o o t c p u v e r i f i c a t i o n
2011-03-17 22:24:16 +03:00
* arch/ x86 / k e r n e l / t r a m p o l i n e _ 6 4 . S : s e c o n d a r y p r o c e s s o r v e r i f i c a t i o n
2010-11-16 21:10:04 +03:00
* arch/ x86 / k e r n e l / h e a d _ 3 2 . S : p r o c e s s o r s t a r t u p
2007-05-02 21:27:08 +04:00
*
2010-11-10 21:35:52 +03:00
* verify_ c p u , r e t u r n s t h e s t a t u s o f l o n g m o d e a n d S S E i n r e g i s t e r % e a x .
2007-05-02 21:27:08 +04:00
* 0 : Success 1 : F a i l u r e
*
2010-11-10 21:35:52 +03:00
* On I n t e l , t h e X D _ D I S A B L E f l a g w i l l b e c l e a r e d a s a s i d e - e f f e c t .
*
2007-05-02 21:27:08 +04:00
* The c a l l e r n e e d s t o c h e c k f o r t h e e r r o r c o d e a n d t a k e t h e a c t i o n
* appropriately. E i t h e r d i s p l a y a m e s s a g e o r h a l t .
* /
2007-05-02 21:27:20 +04:00
# include < a s m / c p u f e a t u r e . h >
2010-07-17 17:03:27 +04:00
# include < a s m / m s r - i n d e x . h >
2007-05-02 21:27:08 +04:00
2007-05-02 21:27:20 +04:00
verify_cpu :
2007-05-02 21:27:08 +04:00
pushfl # S a v e c a l l e r p a s s e d f l a g s
pushl $ 0 # K i l l a n y d a n g e r o u s f l a g s
popfl
pushfl # s t a n d a r d w a y t o c h e c k f o r c p u i d
popl % e a x
movl % e a x ,% e b x
xorl $ 0 x20 0 0 0 0 ,% e a x
pushl % e a x
popfl
pushfl
popl % e a x
cmpl % e a x ,% e b x
jz v e r i f y _ c p u _ n o _ l o n g m o d e # c p u h a s n o c p u i d
movl $ 0 x0 ,% e a x # S e e i f c p u i d 1 i s i m p l e m e n t e d
cpuid
cmpl $ 0 x1 ,% e a x
jb v e r i f y _ c p u _ n o _ l o n g m o d e # n o c p u i d 1
xor % d i ,% d i
cmpl $ 0 x68 7 4 7 5 4 1 ,% e b x # A u t h e n t i c A M D
jnz v e r i f y _ c p u _ n o a m d
cmpl $ 0 x69 7 4 6 e 6 5 ,% e d x
jnz v e r i f y _ c p u _ n o a m d
cmpl $ 0 x44 4 d41 6 3 ,% e c x
jnz v e r i f y _ c p u _ n o a m d
mov $ 1 ,% d i # c p u i s f r o m A M D
2010-11-10 21:35:52 +03:00
jmp v e r i f y _ c p u _ c h e c k
2007-05-02 21:27:08 +04:00
verify_cpu_noamd :
2010-11-10 21:35:52 +03:00
cmpl $ 0 x75 6 e 6 5 4 7 ,% e b x # G e n u i n e I n t e l ?
jnz v e r i f y _ c p u _ c h e c k
cmpl $ 0 x49 6 5 6 e 6 9 ,% e d x
jnz v e r i f y _ c p u _ c h e c k
cmpl $ 0 x6 c65 7 4 6 e ,% e c x
jnz v e r i f y _ c p u _ c h e c k
# only c a l l I A 3 2 _ M I S C _ E N A B L E w h e n :
# family > 6 | | ( f a m i l y = = 6 & & m o d e l > = 0 x d )
movl $ 0 x1 , % e a x # c h e c k C P U f a m i l y a n d m o d e l
cpuid
movl % e a x , % e c x
andl $ 0 x0 f f00 f00 , % e a x # m a s k f a m i l y a n d e x t e n d e d f a m i l y
shrl $ 8 , % e a x
cmpl $ 6 , % e a x
ja v e r i f y _ c p u _ c l e a r _ x d # f a m i l y > 6 , o k
jb v e r i f y _ c p u _ c h e c k # f a m i l y < 6 , s k i p
andl $ 0 x00 0 f00 f0 , % e c x # m a s k m o d e l a n d e x t e n d e d m o d e l
shrl $ 4 , % e c x
cmpl $ 0 x d , % e c x
jb v e r i f y _ c p u _ c h e c k # f a m i l y = = 6 , m o d e l < 0 x d , s k i p
verify_cpu_clear_xd :
movl $ M S R _ I A 3 2 _ M I S C _ E N A B L E , % e c x
rdmsr
btrl $ 2 , % e d x # c l e a r M S R _ I A 32 _ M I S C _ E N A B L E _ X D _ D I S A B L E
jnc v e r i f y _ c p u _ c h e c k # o n l y w r i t e M S R i f b i t w a s c h a n g e d
wrmsr
verify_cpu_check :
2007-05-02 21:27:08 +04:00
movl $ 0 x1 ,% e a x # D o e s t h e c p u h a v e w h a t i t t a k e s
cpuid
2007-07-11 23:18:29 +04:00
andl $ R E Q U I R E D _ M A S K 0 ,% e d x
xorl $ R E Q U I R E D _ M A S K 0 ,% e d x
2007-05-02 21:27:08 +04:00
jnz v e r i f y _ c p u _ n o _ l o n g m o d e
movl $ 0 x80 0 0 0 0 0 0 ,% e a x # S e e i f e x t e n d e d c p u i d i s i m p l e m e n t e d
cpuid
cmpl $ 0 x80 0 0 0 0 0 1 ,% e a x
jb v e r i f y _ c p u _ n o _ l o n g m o d e # n o e x t e n d e d c p u i d
movl $ 0 x80 0 0 0 0 0 1 ,% e a x # D o e s t h e c p u h a v e w h a t i t t a k e s
cpuid
2007-07-11 23:18:29 +04:00
andl $ R E Q U I R E D _ M A S K 1 ,% e d x
xorl $ R E Q U I R E D _ M A S K 1 ,% e d x
2007-05-02 21:27:08 +04:00
jnz v e r i f y _ c p u _ n o _ l o n g m o d e
verify_cpu_sse_test :
movl $ 1 ,% e a x
cpuid
andl $ S S E _ M A S K ,% e d x
cmpl $ S S E _ M A S K ,% e d x
je v e r i f y _ c p u _ s s e _ o k
test % d i ,% d i
jz v e r i f y _ c p u _ n o _ l o n g m o d e # o n l y t r y t o f o r c e S S E o n A M D
2010-07-17 17:03:27 +04:00
movl $ M S R _ K 7 _ H W C R ,% e c x
2007-05-02 21:27:08 +04:00
rdmsr
btr $ 1 5 ,% e a x # e n a b l e S S E
wrmsr
xor % d i ,% d i # d o n ' t l o o p
jmp v e r i f y _ c p u _ s s e _ t e s t # t r y a g a i n
verify_cpu_no_longmode :
popfl # R e s t o r e c a l l e r p a s s e d f l a g s
movl $ 1 ,% e a x
ret
verify_cpu_sse_ok :
popfl # R e s t o r e c a l l e r p a s s e d f l a g s
xorl % e a x , % e a x
ret