2005-04-16 15:20:36 -07:00
/ *
* linux/ a r c h / a r m / k e r n e l / h e a d . S
*
* Copyright ( C ) 1 9 9 4 - 2 0 0 2 R u s s e l l K i n g
2005-06-18 09:33:31 +01:00
* Copyright ( c ) 2 0 0 3 A R M L i m i t e d
* All R i g h t s R e s e r v e d
2005-04-16 15:20:36 -07:00
*
* 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 v e r s i o n 2 a s
* published b y t h e F r e e S o f t w a r e F o u n d a t i o n .
*
* Kernel s t a r t u p c o d e f o r a l l 3 2 - b i t C P U s
* /
# include < l i n u x / l i n k a g e . h >
# include < l i n u x / i n i t . h >
# include < a s m / a s s e m b l e r . h >
# include < a s m / d o m a i n . h >
# include < a s m / p t r a c e . h >
2005-09-09 21:08:59 +02:00
# include < a s m / a s m - o f f s e t s . h >
2005-10-29 21:44:55 +01:00
# include < a s m / m e m o r y . h >
2005-05-05 13:11:00 +01:00
# include < a s m / t h r e a d _ i n f o . h >
2005-04-16 15:20:36 -07:00
# include < a s m / s y s t e m . h >
2007-01-21 20:08:33 +01:00
# if ( P H Y S _ O F F S E T & 0 x00 1 f f f f f )
# error " P H Y S _ O F F S E T m u s t b e a t a n e v e n 2 M i B b o u n d a r y ! "
# endif
2006-12-11 22:29:16 +00:00
# define K E R N E L _ R A M _ V A D D R ( P A G E _ O F F S E T + T E X T _ O F F S E T )
# define K E R N E L _ R A M _ P A D D R ( P H Y S _ O F F S E T + T E X T _ O F F S E T )
2006-01-03 17:28:33 +00:00
2007-05-31 22:02:22 +01:00
2005-04-16 15:20:36 -07:00
/ *
2005-10-29 21:44:56 +01:00
* swapper_ p g _ d i r i s t h e v i r t u a l a d d r e s s o f t h e i n i t i a l p a g e t a b l e .
2006-12-11 22:29:16 +00:00
* We p l a c e t h e p a g e t a b l e s 1 6 K b e l o w K E R N E L _ R A M _ V A D D R . T h e r e f o r e , w e m u s t
* make s u r e t h a t K E R N E L _ R A M _ V A D D R i s c o r r e c t l y s e t . C u r r e n t l y , w e e x p e c t
2005-10-29 21:44:56 +01:00
* the l e a s t s i g n i f i c a n t 1 6 b i t s t o b e 0 x80 0 0 , b u t w e c o u l d p r o b a b l y
2006-12-11 22:29:16 +00:00
* relax t h i s r e s t r i c t i o n t o K E R N E L _ R A M _ V A D D R > = P A G E _ O F F S E T + 0 x40 0 0 .
2005-04-16 15:20:36 -07:00
* /
2006-12-11 22:29:16 +00:00
# if ( K E R N E L _ R A M _ V A D D R & 0 x f f f f ) ! = 0 x80 0 0
# error K E R N E L _ R A M _ V A D D R m u s t s t a r t a t 0 x X X X X 8 0 0 0
2005-04-16 15:20:36 -07:00
# endif
.globl swapper_pg_dir
2006-12-11 22:29:16 +00:00
.equ swapper_ p g _ d i r , K E R N E L _ R A M _ V A D D R - 0 x40 0 0
2005-04-16 15:20:36 -07:00
2005-10-29 21:44:56 +01:00
.macro pgtbl, r d
2006-12-11 22:29:16 +00:00
ldr \ r d , = ( K E R N E L _ R A M _ P A D D R - 0 x40 0 0 )
2005-04-16 15:20:36 -07:00
.endm
2005-10-29 21:44:56 +01:00
# ifdef C O N F I G _ X I P _ K E R N E L
2007-02-22 16:18:09 +01:00
# define K E R N E L _ S T A R T X I P _ V I R T _ A D D R ( C O N F I G _ X I P _ P H Y S _ A D D R )
# define K E R N E L _ E N D _ e d a t a _ l o c
2005-10-29 21:44:56 +01:00
# else
2007-02-22 16:18:09 +01:00
# define K E R N E L _ S T A R T K E R N E L _ R A M _ V A D D R
# define K E R N E L _ E N D _ e n d
2005-04-16 15:20:36 -07:00
# endif
/ *
* Kernel s t a r t u p e n t r y p o i n t .
* - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* This i s n o r m a l l y c a l l e d f r o m t h e d e c o m p r e s s o r c o d e . T h e r e q u i r e m e n t s
* are : MMU = o f f , D - c a c h e = o f f , I - c a c h e = d o n t c a r e , r0 = 0 ,
2007-05-31 22:02:22 +01:00
* r1 = m a c h i n e n r , r2 = a t a g s p o i n t e r .
2005-04-16 15:20:36 -07:00
*
* This c o d e i s m o s t l y p o s i t i o n i n d e p e n d e n t , s o i f y o u l i n k t h e k e r n e l a t
* 0 xc0 0 0 8 0 0 0 , y o u c a l l t h i s a t _ _ p a ( 0 x c00 0 8 0 0 0 ) .
*
* See l i n u x / a r c h / a r m / t o o l s / m a c h - t y p e s f o r t h e c o m p l e t e l i s t o f m a c h i n e
* numbers f o r r1 .
*
* We' r e t r y i n g t o k e e p c r a p t o a m i n i m u m ; DO NOT add any machine specific
* crap h e r e - t h a t ' s w h a t t h e b o o t l o a d e r ( o r i n e x t r e m e , w e l l j u s t i f i e d
* circumstances, z I m a g e ) i s f o r .
* /
2007-05-08 15:15:45 +01:00
.section " .text .head " , " ax"
2005-04-16 15:20:36 -07:00
ENTRY( s t e x t )
2009-07-24 12:32:54 +01:00
setmode P S R _ F _ B I T | P S R _ I _ B I T | S V C _ M O D E , r9 @ ensure svc mode
2005-04-16 15:20:36 -07:00
@ and irqs disabled
2006-02-24 21:04:56 +00:00
mrc p15 , 0 , r9 , c0 , c0 @ get processor id
2005-04-16 15:20:36 -07:00
bl _ _ l o o k u p _ p r o c e s s o r _ t y p e @ r5=procinfo r9=cpuid
movs r10 , r5 @ invalid processor (r5=0)?
2005-11-25 15:43:22 +00:00
beq _ _ e r r o r _ p @ yes, error 'p'
2005-04-16 15:20:36 -07:00
bl _ _ l o o k u p _ m a c h i n e _ t y p e @ r5=machinfo
movs r8 , r5 @ invalid machine (r5=0)?
beq _ _ e r r o r _ a @ yes, error 'a'
2007-05-31 22:02:22 +01:00
bl _ _ v e t _ a t a g s
2005-04-16 15:20:36 -07:00
bl _ _ c r e a t e _ p a g e _ t a b l e s
/ *
* The f o l l o w i n g c a l l s C P U s p e c i f i c c o d e i n a p o s i t i o n i n d e p e n d e n t
* manner. S e e a r c h / a r m / m m / p r o c - * . S f o r d e t a i l s . r10 = b a s e o f
* xxx_ p r o c _ i n f o s t r u c t u r e s e l e c t e d b y _ _ l o o k u p _ m a c h i n e _ t y p e
* above. O n r e t u r n , t h e C P U w i l l b e r e a d y f o r t h e M M U t o b e
* turned o n , a n d r0 w i l l h o l d t h e C P U c o n t r o l r e g i s t e r v a l u e .
* /
ldr r13 , _ _ s w i t c h _ d a t a @ address to jump to after
@ mmu has been enabled
2009-07-24 12:32:54 +01:00
adr l r , B S Y M ( _ _ e n a b l e _ m m u ) @ return (PIC) address
ARM( a d d p c , r10 , #P R O C I N F O _ I N I T F U N C )
THUMB( a d d r12 , r10 , #P R O C I N F O _ I N I T F U N C )
THUMB( m o v p c , r12 )
2008-08-28 11:22:32 +01:00
ENDPROC( s t e x t )
2005-04-16 15:20:36 -07:00
2005-06-18 09:33:31 +01:00
# if d e f i n e d ( C O N F I G _ S M P )
ENTRY( s e c o n d a r y _ s t a r t u p )
/ *
* Common e n t r y p o i n t f o r s e c o n d a r y C P U s .
*
* Ensure t h a t w e ' r e i n S V C m o d e , a n d I R Q s a r e d i s a b l e d . L o o k u p
* the p r o c e s s o r t y p e - t h e r e i s n o n e e d t o c h e c k t h e m a c h i n e t y p e
* as i t h a s a l r e a d y b e e n v a l i d a t e d b y t h e p r i m a r y p r o c e s s o r .
* /
2009-07-24 12:32:54 +01:00
setmode P S R _ F _ B I T | P S R _ I _ B I T | S V C _ M O D E , r9
2006-02-24 21:04:56 +00:00
mrc p15 , 0 , r9 , c0 , c0 @ get processor id
2005-06-18 09:33:31 +01:00
bl _ _ l o o k u p _ p r o c e s s o r _ t y p e
movs r10 , r5 @ invalid processor?
moveq r0 , #' p ' @ yes, error 'p'
beq _ _ e r r o r
/ *
* Use t h e p a g e t a b l e s s u p p l i e d f r o m _ _ c p u _ u p .
* /
adr r4 , _ _ s e c o n d a r y _ d a t a
2009-07-24 12:32:54 +01:00
ldmia r4 , { r5 , r7 , r12 } @ address to jump to after
2005-06-18 09:33:31 +01:00
sub r4 , r4 , r5 @ mmu has been enabled
2006-07-26 18:57:40 +01:00
ldr r4 , [ r7 , r4 ] @ get secondary_data.pgdir
2009-07-24 12:32:54 +01:00
adr l r , B S Y M ( _ _ e n a b l e _ m m u ) @ return address
mov r13 , r12 @ __secondary_switched address
ARM( a d d p c , r10 , #P R O C I N F O _ I N I T F U N C ) @ i n i t i a l i s e p r o c e s s o r
@ (return control reg)
THUMB( a d d r12 , r10 , #P R O C I N F O _ I N I T F U N C )
THUMB( m o v p c , r12 )
2008-08-28 11:22:32 +01:00
ENDPROC( s e c o n d a r y _ s t a r t u p )
2005-06-18 09:33:31 +01:00
/ *
* r6 = & s e c o n d a r y _ d a t a
* /
ENTRY( _ _ s e c o n d a r y _ s w i t c h e d )
2006-07-26 18:57:40 +01:00
ldr s p , [ r7 , #4 ] @ get secondary_data.stack
2005-06-18 09:33:31 +01:00
mov f p , #0
b s e c o n d a r y _ s t a r t _ k e r n e l
2008-08-28 11:22:32 +01:00
ENDPROC( _ _ s e c o n d a r y _ s w i t c h e d )
2005-06-18 09:33:31 +01:00
.type _ _ secondary_ d a t a , % o b j e c t
__secondary_data :
.long .
.long secondary_data
.long __secondary_switched
# endif / * d e f i n e d ( C O N F I G _ S M P ) * /
2005-04-16 15:20:36 -07:00
/ *
* Setup c o m m o n b i t s b e f o r e f i n a l l y e n a b l i n g t h e M M U . E s s e n t i a l l y
* this i s j u s t l o a d i n g t h e p a g e t a b l e p o i n t e r a n d d o m a i n a c c e s s
* registers.
* /
__enable_mmu :
# ifdef C O N F I G _ A L I G N M E N T _ T R A P
orr r0 , r0 , #C R _ A
# else
bic r0 , r0 , #C R _ A
# endif
# ifdef C O N F I G _ C P U _ D C A C H E _ D I S A B L E
bic r0 , r0 , #C R _ C
# endif
# ifdef C O N F I G _ C P U _ B P R E D I C T _ D I S A B L E
bic r0 , r0 , #C R _ Z
# endif
# ifdef C O N F I G _ C P U _ I C A C H E _ D I S A B L E
bic r0 , r0 , #C R _ I
# endif
mov r5 , #( d o m a i n _ v a l ( D O M A I N _ U S E R , D O M A I N _ M A N A G E R ) | \
domain_ v a l ( D O M A I N _ K E R N E L , D O M A I N _ M A N A G E R ) | \
domain_ v a l ( D O M A I N _ T A B L E , D O M A I N _ M A N A G E R ) | \
domain_ v a l ( D O M A I N _ I O , D O M A I N _ C L I E N T ) )
mcr p15 , 0 , r5 , c3 , c0 , 0 @ load domain access register
mcr p15 , 0 , r4 , c2 , c0 , 0 @ load page table pointer
b _ _ t u r n _ m m u _ o n
2008-08-28 11:22:32 +01:00
ENDPROC( _ _ e n a b l e _ m m u )
2005-04-16 15:20:36 -07:00
/ *
* Enable t h e M M U . T h i s c o m p l e t e l y c h a n g e s t h e s t r u c t u r e o f t h e v i s i b l e
* memory s p a c e . Y o u w i l l n o t b e a b l e t o t r a c e e x e c u t i o n t h r o u g h t h i s .
* If y o u h a v e a n e n q u i r y a b o u t t h i s , * p l e a s e * c h e c k t h e l i n u x - a r m - k e r n e l
* mailing l i s t a r c h i v e s B E F O R E s e n d i n g a n o t h e r p o s t t o t h e l i s t .
*
* r0 = c p #15 c o n t r o l r e g i s t e r
* r1 3 = * v i r t u a l * a d d r e s s t o j u m p t o u p o n c o m p l e t i o n
*
* other r e g i s t e r s d e p e n d o n t h e f u n c t i o n c a l l e d u p o n c o m p l e t i o n
* /
.align 5
__turn_mmu_on :
mov r0 , r0
mcr p15 , 0 , r0 , c1 , c0 , 0 @ write control reg
mrc p15 , 0 , r3 , c0 , c0 , 0 @ read id reg
mov r3 , r3
2009-07-24 12:32:54 +01:00
mov r3 , r13
mov p c , r3
2008-08-28 11:22:32 +01:00
ENDPROC( _ _ t u r n _ m m u _ o n )
2005-04-16 15:20:36 -07:00
/ *
* Setup t h e i n i t i a l p a g e t a b l e s . W e o n l y s e t u p t h e b a r e s t
* amount w h i c h a r e r e q u i r e d t o g e t t h e k e r n e l r u n n i n g , w h i c h
* generally m e a n s m a p p i n g i n t h e k e r n e l c o d e .
*
* r8 = m a c h i n f o
* r9 = c p u i d
* r1 0 = p r o c i n f o
*
* Returns :
2006-01-13 20:51:46 +00:00
* r0 , r3 , r6 , r7 c o r r u p t e d
2005-04-16 15:20:36 -07:00
* r4 = p h y s i c a l p a g e t a b l e a d d r e s s
* /
__create_page_tables :
2005-10-29 21:44:56 +01:00
pgtbl r4 @ page table address
2005-04-16 15:20:36 -07:00
/ *
* Clear t h e 1 6 K l e v e l 1 s w a p p e r p a g e t a b l e
* /
mov r0 , r4
mov r3 , #0
add r6 , r0 , #0x4000
1 : str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
teq r0 , r6
bne 1 b
2006-06-29 18:24:21 +01:00
ldr r7 , [ r10 , #P R O C I N F O _ M M _ M M U F L A G S ] @ m m _ m m u f l a g s
2005-04-16 15:20:36 -07:00
/ *
* Create i d e n t i t y m a p p i n g f o r f i r s t M B o f k e r n e l t o
* cater f o r t h e M M U e n a b l e . T h i s i d e n t i t y m a p p i n g
* will b e r e m o v e d b y p a g i n g _ i n i t ( ) . W e u s e o u r c u r r e n t p r o g r a m
* counter t o d e t e r m i n e c o r r e s p o n d i n g s e c t i o n b a s e a d d r e s s .
* /
2009-07-24 12:32:54 +01:00
mov r6 , p c
mov r6 , r6 , l s r #20 @ start of kernel section
2005-04-16 15:20:36 -07:00
orr r3 , r7 , r6 , l s l #20 @ flags + kernel base
str r3 , [ r4 , r6 , l s l #2 ] @ identity mapping
/ *
* Now s e t u p t h e p a g e t a b l e s f o r o u r k e r n e l d i r e c t
2006-09-29 21:14:05 +01:00
* mapped r e g i o n .
2005-04-16 15:20:36 -07:00
* /
2007-02-22 16:18:09 +01:00
add r0 , r4 , #( K E R N E L _ S T A R T & 0xff000000 ) > > 1 8
str r3 , [ r0 , #( K E R N E L _ S T A R T & 0x00f00000 ) > > 1 8 ] !
ldr r6 , = ( K E R N E L _ E N D - 1 )
add r0 , r0 , #4
add r6 , r4 , r6 , l s r #18
1 : cmp r0 , r6
add r3 , r3 , #1 < < 2 0
strls r3 , [ r0 ] , #4
bls 1 b
2005-04-16 15:20:36 -07:00
2007-02-21 15:32:28 +01:00
# ifdef C O N F I G _ X I P _ K E R N E L
/ *
* Map s o m e r a m t o c o v e r o u r . d a t a a n d . b s s a r e a s .
* /
orr r3 , r7 , #( K E R N E L _ R A M _ P A D D R & 0xff000000 )
2007-02-21 15:58:13 +01:00
.if ( KERNEL_ R A M _ P A D D R & 0 x00 f00 0 0 0 )
2007-02-21 15:32:28 +01:00
orr r3 , r3 , #( K E R N E L _ R A M _ P A D D R & 0x00f00000 )
2007-02-21 15:58:13 +01:00
.endif
2007-02-21 15:32:28 +01:00
add r0 , r4 , #( K E R N E L _ R A M _ V A D D R & 0xff000000 ) > > 1 8
str r3 , [ r0 , #( K E R N E L _ R A M _ V A D D R & 0x00f00000 ) > > 1 8 ] !
ldr r6 , = ( _ e n d - 1 )
add r0 , r0 , #4
add r6 , r4 , r6 , l s r #18
1 : cmp r0 , r6
add r3 , r3 , #1 < < 2 0
strls r3 , [ r0 ] , #4
bls 1 b
# endif
2005-04-16 15:20:36 -07:00
/ *
* Then m a p f i r s t 1 M B o f r a m i n c a s e i t c o n t a i n s o u r b o o t p a r a m s .
* /
2005-10-29 21:44:55 +01:00
add r0 , r4 , #P A G E _ O F F S E T > > 18
2007-01-21 20:08:33 +01:00
orr r6 , r7 , #( P H Y S _ O F F S E T & 0xff000000 )
2007-02-21 15:58:13 +01:00
.if ( PHYS_ O F F S E T & 0 x00 f00 0 0 0 )
orr r6 , r6 , #( P H Y S _ O F F S E T & 0x00f00000 )
.endif
2005-04-16 15:20:36 -07:00
str r6 , [ r0 ]
2005-07-01 11:56:55 +01:00
# ifdef C O N F I G _ D E B U G _ L L
2006-06-29 18:24:21 +01:00
ldr r7 , [ r10 , #P R O C I N F O _ I O _ M M U F L A G S ] @ i o _ m m u f l a g s
2005-04-16 15:20:36 -07:00
/ *
* Map i n I O s p a c e f o r s e r i a l d e b u g g i n g .
* This a l l o w s d e b u g m e s s a g e s t o b e o u t p u t
* via a s e r i a l c o n s o l e b e f o r e p a g i n g _ i n i t .
* /
ldr r3 , [ r8 , #M A C H I N F O _ P G O F F I O ]
add r0 , r4 , r3
rsb r3 , r3 , #0x4000 @ PTRS_PER_PGD*sizeof(long)
cmp r3 , #0x0800 @ limit to 512MB
movhi r3 , #0x0800
add r6 , r0 , r3
ldr r3 , [ r8 , #M A C H I N F O _ P H Y S I O ]
orr r3 , r3 , r7
1 : str r3 , [ r0 ] , #4
add r3 , r3 , #1 < < 2 0
teq r0 , r6
bne 1 b
# if d e f i n e d ( C O N F I G _ A R C H _ N E T W I N D E R ) | | d e f i n e d ( C O N F I G _ A R C H _ C A T S )
/ *
2005-11-25 15:43:22 +00:00
* If w e ' r e u s i n g t h e N e t W i n d e r o r C A T S , w e a l s o n e e d t o m a p
* in t h e 1 6 5 5 0 - t y p e s e r i a l p o r t f o r t h e d e b u g m e s s a g e s
2005-04-16 15:20:36 -07:00
* /
2005-07-01 11:56:55 +01:00
add r0 , r4 , #0xff000000 > > 1 8
orr r3 , r7 , #0x7c000000
str r3 , [ r0 ]
2005-04-16 15:20:36 -07:00
# endif
# ifdef C O N F I G _ A R C H _ R P C
/ *
* Map i n s c r e e n a t 0 x02 0 0 0 0 0 0 & S C R E E N 2 _ B A S E
* Similar r e a s o n s h e r e - f o r d e b u g . T h i s i s
* only f o r A c o r n R i s c P C a r c h i t e c t u r e s .
* /
2005-07-01 11:56:55 +01:00
add r0 , r4 , #0x02000000 > > 1 8
orr r3 , r7 , #0x02000000
2005-04-16 15:20:36 -07:00
str r3 , [ r0 ]
2005-07-01 11:56:55 +01:00
add r0 , r4 , #0xd8000000 > > 1 8
2005-04-16 15:20:36 -07:00
str r3 , [ r0 ]
2005-07-01 11:56:55 +01:00
# endif
2005-04-16 15:20:36 -07:00
# endif
mov p c , l r
2008-08-28 11:22:32 +01:00
ENDPROC( _ _ c r e a t e _ p a g e _ t a b l e s )
2005-04-16 15:20:36 -07:00
.ltorg
2006-03-27 14:58:25 +01:00
# include " h e a d - c o m m o n . S "