2012-02-09 08:47:17 -08:00
/ *
* Copyright ( c ) 2 0 1 2 L i n a r o L i m i t e d .
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify
* it u n d e r t h e t e r m s o f 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 a s p u b l i s h e d b y
* the F r e e S o f t w a r e F o u n d a t i o n ; either version 2 of the License, or
* ( at y o u r o p t i o n ) a n y l a t e r v e r s i o n .
*
* This p r o g r a m i s d i s t r i b u t e d i n t h e h o p e t h a t i t w i l l b e u s e f u l ,
* but W I T H O U T A N Y W A R R A N T Y ; without even the implied warranty of
* MERCHANTABILITY o r F I T N E S S F O R A P A R T I C U L A R P U R P O S E . S e e t h e
* GNU G e n e r a l P u b l i c L i c e n s e f o r m o r e d e t a i l s .
*
* You s h o u l d h a v e r e c e i v e d a c o p y o f 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 a l o n g
* with t h i s p r o g r a m ; if not, write to the Free Software Foundation, Inc.,
* 5 1 Franklin S t r e e t , F i f t h F l o o r , B o s t o n , M A 0 2 1 1 0 - 1 3 0 1 U S A .
* /
# include < l i n u x / i n i t . h >
# include < l i n u x / l i n k a g e . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / v i r t . h >
2012-02-10 18:07:07 -08:00
# ifndef Z I M A G E
2012-02-09 08:47:17 -08:00
/ *
* For t h e k e r n e l p r o p e r , w e n e e d t o f i n d o u t t h e C P U b o o t m o d e l o n g a f t e r
* boot, s o w e n e e d t o s t o r e i t i n a w r i t a b l e v a r i a b l e .
*
* This i s n o t i n . b s s , b e c a u s e w e s e t i t s u f f i c i e n t l y e a r l y t h a t t h e b o o t - t i m e
* zeroing o f . b s s w o u l d c l o b b e r i t .
* /
.data
ENTRY( _ _ b o o t _ c p u _ m o d e )
.long 0
.text
/ *
* Save t h e p r i m a r y C P U b o o t m o d e . R e q u i r e s 3 s c r a t c h r e g i s t e r s .
* /
.macro store_primary_cpu_mode reg1 , r e g 2 , r e g 3
mrs \ r e g 1 , c p s r
and \ r e g 1 , \ r e g 1 , #M O D E _ M A S K
adr \ r e g 2 , . L _ _ b o o t _ c p u _ m o d e _ o f f s e t
ldr \ r e g 3 , [ \ r e g 2 ]
str \ r e g 1 , [ \ r e g 2 , \ r e g 3 ]
.endm
/ *
* Compare t h e c u r r e n t m o d e w i t h t h e o n e s a v e d o n t h e p r i m a r y C P U .
* If t h e y d o n ' t m a t c h , r e c o r d t h a t f a c t . T h e Z b i t i n d i c a t e s
* if t h e r e ' s a m a t c h o r n o t .
* Requires 3 a d d i t i o n n a l s c r a t c h r e g i s t e r s .
* /
.macro compare_cpu_mode_with_primary mode, r e g 1 , r e g 2 , r e g 3
adr \ r e g 2 , . L _ _ b o o t _ c p u _ m o d e _ o f f s e t
ldr \ r e g 3 , [ \ r e g 2 ]
ldr \ r e g 1 , [ \ r e g 2 , \ r e g 3 ]
cmp \ m o d e , \ r e g 1 @ matches primary CPU boot mode?
orrne r7 , r7 , #B O O T _ C P U _ M O D E _ M I S M A T C H
strne r7 , [ r5 , r6 ] @ record what happened and give up
.endm
2012-02-10 18:07:07 -08:00
# else / * Z I M A G E * /
.macro store_primary_cpu_mode reg1 : req, r e g 2 : r e q , r e g 3 : r e q
.endm
/ *
* The z I m a g e l o a d e r o n l y r u n s o n o n e C P U , s o w e d o n ' t b o t h e r w i t h m u l t - C P U
* consistency c h e c k i n g :
* /
.macro compare_cpu_mode_with_primary mode, r e g 1 , r e g 2 , r e g 3
cmp \ m o d e , \ m o d e
.endm
# endif / * Z I M A G E * /
2012-02-09 08:47:17 -08:00
/ *
* Hypervisor s t u b i n s t a l l a t i o n f u n c t i o n s .
*
* These m u s t b e c a l l e d w i t h t h e M M U a n d D - c a c h e o f f .
* They a r e n o t A B I c o m p l i a n t a n d a r e o n l y i n t e n d e d t o b e c a l l e d f r o m t h e k e r n e l
* entry p o i n t s i n h e a d . S .
* /
@ Call this from the primary CPU
ENTRY( _ _ h y p _ s t u b _ i n s t a l l )
store_ p r i m a r y _ c p u _ m o d e r4 , r5 , r6
ENDPROC( _ _ h y p _ s t u b _ i n s t a l l )
@ fall through...
@ Secondary CPUs should call here
ENTRY( _ _ h y p _ s t u b _ i n s t a l l _ s e c o n d a r y )
mrs r4 , c p s r
and r4 , r4 , #M O D E _ M A S K
/ *
* If t h e s e c o n d a r y h a s b o o t e d w i t h a d i f f e r e n t m o d e , g i v e u p
* immediately.
* /
compare_ c p u _ m o d e _ w i t h _ p r i m a r y r4 , r5 , r6 , r7
bxne l r
/ *
* Once w e h a v e g i v e n u p o n o n e C P U , w e d o n o t t r y t o i n s t a l l t h e
* stub h y p e r v i s o r o n t h e r e m a i n i n g o n e s : b e c a u s e t h e s a v e d b o o t m o d e
* is m o d i f i e d , i t c a n ' t c o m p a r e e q u a l t o t h e C P S R m o d e f i e l d a n y
* more.
*
* Otherwise. . .
* /
cmp r4 , #H Y P _ M O D E
bxne l r @ give up if the CPU is not in HYP mode
/ *
* Configure H S C T L R t o s e t c o r r e c t e x c e p t i o n e n d i a n n e s s / i n s t r u c t i o n s e t
* state e t c .
* Turn o f f a l l t r a p s
* Eventually, C P U - s p e c i f i c c o d e m i g h t b e n e e d e d - - a s s u m e n o t f o r n o w
*
* This c o d e r e l i e s o n t h e " e r e t " i n s t r u c t i o n t o s y n c h r o n i z e t h e
* various c o p r o c e s s o r a c c e s s e s .
* /
@ Now install the hypervisor stub:
adr r7 , _ _ h y p _ s t u b _ v e c t o r s
mcr p15 , 4 , r7 , c12 , c0 , 0 @ set hypervisor vector base (HVBAR)
@ Disable all traps, so we don't get any nasty surprise
mov r7 , #0
mcr p15 , 4 , r7 , c1 , c1 , 0 @ HCR
mcr p15 , 4 , r7 , c1 , c1 , 2 @ HCPTR
mcr p15 , 4 , r7 , c1 , c1 , 3 @ HSTR
THUMB( o r r r7 , #( 1 < < 3 0 ) ) @ HSCTLR.TE
# ifdef C O N F I G _ C P U _ B I G _ E N D I A N
orr r7 , #( 1 < < 9 ) @ HSCTLR.EE
# endif
mcr p15 , 4 , r7 , c1 , c0 , 0 @ HSCTLR
mrc p15 , 4 , r7 , c1 , c1 , 1 @ HDCR
and r7 , #0x1f @ Preserve HPMN
mcr p15 , 4 , r7 , c1 , c1 , 1 @ HDCR
2012-08-01 14:46:41 +01:00
# if ! d e f i n e d ( Z I M A G E ) & & d e f i n e d ( C O N F I G _ A R M _ A R C H _ T I M E R )
@ make CNTP_* and CNTPCT accessible from PL1
mrc p15 , 0 , r7 , c0 , c1 , 1 @ ID_PFR1
lsr r7 , #16
and r7 , #0xf
cmp r7 , #1
bne 1 f
mrc p15 , 4 , r7 , c14 , c1 , 0 @ CNTHCTL
orr r7 , r7 , #3 @ PL1PCEN | PL1PCTEN
mcr p15 , 4 , r7 , c14 , c1 , 0 @ CNTHCTL
1 :
# endif
2012-02-09 08:47:17 -08:00
bic r7 , r4 , #M O D E _ M A S K
orr r7 , r7 , #S V C _ M O D E
THUMB( o r r r7 , r7 , #P S R _ T _ B I T )
msr s p s r _ c x s f , r7 @ This is SPSR_hyp.
_ _ MSR_ E L R _ H Y P ( 1 4 ) @ msr elr_hyp, lr
_ _ ERET @ return, switching to SVC mode
@ The boot CPU mode is left in r4.
ENDPROC( _ _ h y p _ s t u b _ i n s t a l l _ s e c o n d a r y )
__hyp_stub_do_trap :
cmp r0 , #- 1
mrceq p15 , 4 , r0 , c12 , c0 , 0 @ get HVBAR
mcrne p15 , 4 , r0 , c12 , c0 , 0 @ set HVBAR
_ _ ERET
ENDPROC( _ _ h y p _ s t u b _ d o _ t r a p )
/ *
* __hyp_set_vectors : Call t h i s a f t e r b o o t t o s e t t h e i n i t i a l h y p e r v i s o r
* vectors a s p a r t o f h y p e r v i s o r i n s t a l l a t i o n . O n a n S M P s y s t e m , t h i s s h o u l d
* be c a l l e d o n e a c h C P U .
*
* r0 m u s t b e t h e p h y s i c a l a d d r e s s o f t h e n e w v e c t o r t a b l e ( w h i c h m u s t l i e i n
* the b o t t o m 4 G B o f p h y s i c a l a d d r e s s s p a c e .
*
* r0 m u s t b e 3 2 - b y t e a l i g n e d .
*
* Before c a l l i n g t h i s , y o u m u s t c h e c k t h a t t h e s t u b h y p e r v i s o r i s i n s t a l l e d
* everywhere, b y w a i t i n g f o r a n y s e c o n d a r y C P U s t o b e b r o u g h t u p a n d t h e n
* checking t h a t B O O T _ C P U _ M O D E _ H A V E _ H Y P ( _ _ b o o t _ c p u _ m o d e ) i s t r u e .
*
* If n o t , t h e r e i s a p r e - e x i s t i n g h y p e r v i s o r , s o m e C P U s f a i l e d t o b o o t , o r
* something e l s e w e n t w r o n g . . . i n s u c h c a s e s , t r y i n g t o i n s t a l l a n e w
* hypervisor i s u n l i k e l y t o w o r k a s d e s i r e d .
*
* When y o u c a l l i n t o y o u r s h i n y n e w h y p e r v i s o r , s p _ h y p w i l l c o n t a i n j u n k ,
* so y o u w i l l n e e d t o s e t t h a t t o s o m e t h i n g s e n s i b l e a t t h e n e w h y p e r v i s o r ' s
* initialisation e n t r y p o i n t .
* /
ENTRY( _ _ h y p _ g e t _ v e c t o r s )
mov r0 , #- 1
ENDPROC( _ _ h y p _ g e t _ v e c t o r s )
@ fall through
ENTRY( _ _ h y p _ s e t _ v e c t o r s )
_ _ HVC( 0 )
bx l r
ENDPROC( _ _ h y p _ s e t _ v e c t o r s )
2012-02-10 18:07:07 -08:00
# ifndef Z I M A G E
2012-02-09 08:47:17 -08:00
.align 2
.L__boot_cpu_mode_offset :
.long __boot_cpu_mode - .
2012-02-10 18:07:07 -08:00
# endif
2012-02-09 08:47:17 -08:00
.align 5
__hyp_stub_vectors :
__hyp_stub_reset : W( b ) .
__hyp_stub_und : W( b ) .
__hyp_stub_svc : W( b ) .
__hyp_stub_pabort : W( b ) .
__hyp_stub_dabort : W( b ) .
__hyp_stub_trap : W( b ) _ _ h y p _ s t u b _ d o _ t r a p
__hyp_stub_irq : W( b ) .
__hyp_stub_fiq : W( b ) .
ENDPROC( _ _ h y p _ s t u b _ v e c t o r s )