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 / c o n f i g . h >
# 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 r o c i n f o . 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 >
# define P R O C I N F O _ M M U F L A G S 8
# define P R O C I N F O _ I N I T F U N C 1 2
# define M A C H I N F O _ T Y P E 0
# define M A C H I N F O _ P H Y S R A M 4
# define M A C H I N F O _ P H Y S I O 8
# define M A C H I N F O _ P G O F F I O 1 2
# define M A C H I N F O _ N A M E 1 6
2006-01-03 17:28:33 +00:00
# define K E R N E L _ R A M _ A D D R ( P A G E _ O F F S E T + T E X T _ O F F S E T )
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 .
* 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 _ 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 _ 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
* 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
* 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 _ 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
* /
2005-10-29 21:44:56 +01:00
# if ( K E R N E L _ R A M _ A D D R & 0 x f f f f ) ! = 0 x80 0 0
# error K E R N E L _ R A M _ 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
2005-10-29 21:44:56 +01:00
.equ swapper_ p g _ d i r , K E R N E L _ R A M _ 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
ldr \ r d , = ( _ _ v i r t _ t o _ p h y s ( K E R N E L _ R A M _ 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
# define T E X T A D D R 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 )
# else
# define T E X T A D D R K E R N E L _ R A M _ A D D R
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 ,
* r1 = m a c h i n e n r .
*
* 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 .
* /
_ _ INIT
.type stext, % f u n c t i o n
ENTRY( s t e x t )
msr c p s r _ c , #P S R _ F _ B I T | P S R _ I _ B I T | M O D E _ S V C @ e n s u r e s v c m o d e
@ and irqs disabled
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'
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
adr l r , _ _ e n a b l e _ m m u @ return (PIC) address
add p c , r10 , #P R O C I N F O _ I N I T F U N C
.type _ _ switch_ d a t a , % o b j e c t
__switch_data :
.long __mmap_switched
.long __data_loc @ r4
.long __data_start @ r5
.long __bss_start @ r6
.long _end @ r7
.long processor_id @ r4
.long __machine_arch_type @ r5
.long cr_alignment @ r6
2005-05-05 13:11:00 +01:00
.long init_thread_union + THREAD_ S T A R T _ S P @ sp
2005-04-16 15:20:36 -07:00
/ *
* The f o l l o w i n g f r a g m e n t o f c o d e i s e x e c u t e d w i t h t h e M M U o n , a n d u s e s
* absolute a d d r e s s e s ; this is not position independent.
*
* r0 = c p #15 c o n t r o l r e g i s t e r
* r1 = m a c h i n e I D
* r9 = p r o c e s s o r I D
* /
.type _ _ mmap_ s w i t c h e d , % f u n c t i o n
__mmap_switched :
adr r3 , _ _ s w i t c h _ d a t a + 4
ldmia r3 ! , { r4 , r5 , r6 , r7 }
cmp r4 , r5 @ Copy data segment if needed
1 : cmpne r5 , r6
ldrne f p , [ r4 ] , #4
strne f p , [ r5 ] , #4
bne 1 b
mov f p , #0 @ Clear BSS (and zero fp)
1 : cmp r6 , r7
strcc f p , [ r6 ] ,#4
bcc 1 b
ldmia r3 , { r4 , r5 , r6 , s p }
str r9 , [ r4 ] @ Save processor ID
str r1 , [ r5 ] @ Save machine type
bic r4 , r0 , #C R _ A @ C l e a r ' A ' b i t
stmia r6 , { r0 , r4 } @ Save control register values
b s t a r t _ k e r n e l
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 )
.type secondary_ s t a r t u p , #f u n c t i o n
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 .
* /
msr c p s r _ c , #P S R _ F _ B I T | P S R _ I _ B I T | M O D E _ S V C
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
ldmia r4 , { r5 , r6 , r13 } @ address to jump to after
sub r4 , r4 , r5 @ mmu has been enabled
ldr r4 , [ r6 , r4 ] @ get secondary_data.pgdir
adr l r , _ _ e n a b l e _ m m u @ return address
add p c , r10 , #12 @ initialise processor
@ (return control reg)
/ *
* 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 )
ldr s p , [ r6 , #4 ] @ get secondary_data.stack
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
.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.
* /
.type _ _ enable_ m m u , % f u n c t i o n
__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
/ *
* 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
.type _ _ turn_ m m u _ o n , % f u n c t i o n
__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
mov r3 , r3
mov p c , r13
/ *
* 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 :
* r0 , r3 , r5 , r6 , r7 c o r r u p t e d
* 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
* /
.type _ _ create_ p a g e _ t a b l e s , % f u n c t i o n
__create_page_tables :
ldr r5 , [ r8 , #M A C H I N F O _ P H Y S R A M ] @ p h y s r a m
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
ldr r7 , [ r10 , #P R O C I N F O _ M M U F L A G S ] @ m m u f l a g s
/ *
* 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 .
* /
mov r6 , p c , l s r #20 @ start of kernel section
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
* mapped r e g i o n . W e r o u n d T E X T A D D R d o w n t o t h e
* nearest m e g a b y t e b o u n d a r y . I t i s a s s u m e d t h a t
* the k e r n e l f i t s w i t h i n 4 c o n t i g o u s 1 M B s e c t i o n s .
* /
add r0 , r4 , #( T E X T A D D R & 0xff000000 ) > > 1 8 @ start of kernel
str r3 , [ r0 , #( T E X T A D D R & 0x00f00000 ) > > 1 8 ] !
add r3 , r3 , #1 < < 2 0
str r3 , [ r0 , #4 ] ! @ KERNEL + 1MB
add r3 , r3 , #1 < < 2 0
str r3 , [ r0 , #4 ] ! @ KERNEL + 2MB
add r3 , r3 , #1 < < 2 0
str r3 , [ r0 , #4 ] @ KERNEL + 3MB
/ *
* 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
2005-04-16 15:20:36 -07:00
orr r6 , r5 , r7
str r6 , [ r0 ]
# 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 .
* Mapping 3 M B s h o u l d b e p l e n t y .
* /
sub r3 , r4 , r5
mov r3 , r3 , l s r #20
add r0 , r0 , r3 , l s l #2
add r6 , r6 , r3 , l s l #20
str r6 , [ r0 ] , #4
add r6 , r6 , #( 1 < < 2 0 )
str r6 , [ r0 ] , #4
add r6 , r6 , #( 1 < < 2 0 )
str r6 , [ r0 ]
# endif
2005-07-01 11:56:55 +01:00
# ifdef C O N F I G _ D E B U G _ L L
2005-04-16 15:20:36 -07:00
bic r7 , r7 , #0x0c @ turn off cacheable
@ and bufferable bits
/ *
* 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
.ltorg
/ *
* Exception h a n d l i n g . S o m e t h i n g w e n t w r o n g a n d w e c a n ' t p r o c e e d . W e
* ought t o t e l l t h e u s e r , b u t s i n c e w e d o n ' t h a v e a n y g u a r a n t e e t h a t
* we' r e e v e n r u n n i n g o n t h e r i g h t a r c h i t e c t u r e , w e d o v i r t u a l l y n o t h i n g .
*
* If C O N F I G _ D E B U G _ L L i s s e t w e t r y t o p r i n t o u t s o m e t h i n g a b o u t t h e e r r o r
* and h o p e f o r t h e b e s t ( u s e f u l i f b o o t l o a d e r f a i l s t o p a s s a p r o p e r
* machine I D f o r e x a m p l e ) .
* /
.type _ _ error_ p , % f u n c t i o n
__error_p :
# ifdef C O N F I G _ D E B U G _ L L
adr r0 , s t r _ p1
bl p r i n t a s c i i
b _ _ e r r o r
str_p1 : .asciz " \nError: unrecognized/unsupported processor variant.\n "
.align
# endif
.type _ _ error_ a , % f u n c t i o n
__error_a :
# ifdef C O N F I G _ D E B U G _ L L
mov r4 , r1 @ preserve machine ID
adr r0 , s t r _ a1
bl p r i n t a s c i i
mov r0 , r4
bl p r i n t h e x8
adr r0 , s t r _ a2
bl p r i n t a s c i i
adr r3 , 3 f
ldmia r3 , { r4 , r5 , r6 } @ get machine desc list
sub r4 , r3 , r4 @ get offset between virt&phys
add r5 , r5 , r4 @ convert virt addresses to
add r6 , r6 , r4 @ physical address space
1 : ldr r0 , [ r5 , #M A C H I N F O _ T Y P E ] @ g e t m a c h i n e t y p e
bl p r i n t h e x8
mov r0 , #' \t '
bl p r i n t c h
ldr r0 , [ r5 , #M A C H I N F O _ N A M E ] @ g e t m a c h i n e n a m e
add r0 , r0 , r4
bl p r i n t a s c i i
mov r0 , #' \n '
bl p r i n t c h
add r5 , r5 , #S I Z E O F _ M A C H I N E _ D E S C @ n e x t m a c h i n e _ d e s c
cmp r5 , r6
blo 1 b
adr r0 , s t r _ a3
bl p r i n t a s c i i
b _ _ e r r o r
str_a1 : .asciz " \nError: unrecognized/unsupported machine ID (r1 = 0x "
str_a2 : .asciz " ).\n\nAvailable machine support:\n\nID (hex)\tNAME\n "
str_a3 : .asciz " \nPlease check your kernel config and/or bootloader.\n "
.align
# endif
.type _ _ error, % f u n c t i o n
__error :
# ifdef C O N F I G _ A R C H _ R P C
/ *
* Turn t h e s c r e e n r e d o n a e r r o r - R i s c P C o n l y .
* /
mov r0 , #0x02000000
mov r3 , #0x11
orr r3 , r3 , r3 , l s l #8
orr r3 , r3 , r3 , l s l #16
str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
str r3 , [ r0 ] , #4
# endif
1 : mov r0 , r0
b 1 b
/ *
* Read p r o c e s s o r I D r e g i s t e r ( C P #15 , C R 0 ) , a n d l o o k u p i n t h e l i n k e r - b u i l t
* supported p r o c e s s o r l i s t . N o t e t h a t w e c a n ' t u s e t h e a b s o l u t e a d d r e s s e s
* for t h e _ _ p r o c _ i n f o l i s t s s i n c e w e a r e n ' t r u n n i n g w i t h t h e M M U o n
* ( and t h e r e f o r e , w e a r e n o t i n t h e c o r r e c t a d d r e s s s p a c e ) . W e h a v e t o
* calculate t h e o f f s e t .
*
* Returns :
* r3 , r4 , r6 c o r r u p t e d
* r5 = p r o c _ i n f o p o i n t e r i n p h y s i c a l a d d r e s s s p a c e
* r9 = c p u i d
* /
.type _ _ lookup_ p r o c e s s o r _ t y p e , % f u n c t i o n
__lookup_processor_type :
adr r3 , 3 f
ldmda r3 , { r5 , r6 , r9 }
sub r3 , r3 , r9 @ get offset between virt&phys
add r5 , r5 , r3 @ convert virt addresses to
add r6 , r6 , r3 @ physical address space
mrc p15 , 0 , r9 , c0 , c0 @ get processor id
1 : ldmia r5 , { r3 , r4 } @ value, mask
and r4 , r4 , r9 @ mask wanted bits
teq r3 , r4
beq 2 f
add r5 , r5 , #P R O C _ I N F O _ S Z @ s i z e o f ( p r o c _ i n f o _ l i s t )
cmp r5 , r6
blo 1 b
mov r5 , #0 @ unknown processor
2 : mov p c , l r
/ *
* This p r o v i d e s a C - A P I v e r s i o n o f t h e a b o v e f u n c t i o n .
* /
ENTRY( l o o k u p _ p r o c e s s o r _ t y p e )
stmfd s p ! , { r4 - r6 , r9 , l r }
bl _ _ l o o k u p _ p r o c e s s o r _ t y p e
mov r0 , r5
ldmfd s p ! , { r4 - r6 , r9 , p c }
/ *
* Look i n i n c l u d e / a s m - a r m / p r o c i n f o . h a n d a r c h / a r m / k e r n e l / a r c h . [ c h ] f o r
* more i n f o r m a t i o n a b o u t t h e _ _ p r o c _ i n f o a n d _ _ a r c h _ i n f o s t r u c t u r e s .
* /
.long __proc_info_begin
.long __proc_info_end
3 : .long .
.long __arch_info_begin
.long __arch_info_end
/ *
* Lookup m a c h i n e a r c h i t e c t u r e i n t h e l i n k e r - b u i l d l i s t o f a r c h i t e c t u r e s .
* Note t h a t w e c a n ' t u s e t h e a b s o l u t e a d d r e s s e s f o r t h e _ _ a r c h _ i n f o
* lists s i n c e w e a r e n ' t r u n n i n g w i t h t h e M M U o n ( a n d t h e r e f o r e , w e a r e
* not i n t h e c o r r e c t a d d r e s s s p a c e ) . W e h a v e t o c a l c u l a t e t h e o f f s e t .
*
* r1 = m a c h i n e a r c h i t e c t u r e n u m b e r
* Returns :
* r3 , r4 , r6 c o r r u p t e d
* r5 = m a c h _ i n f o p o i n t e r i n p h y s i c a l a d d r e s s s p a c e
* /
.type _ _ lookup_ m a c h i n e _ t y p e , % f u n c t i o n
__lookup_machine_type :
adr r3 , 3 b
ldmia r3 , { r4 , r5 , r6 }
sub r3 , r3 , r4 @ get offset between virt&phys
add r5 , r5 , r3 @ convert virt addresses to
add r6 , r6 , r3 @ physical address space
1 : ldr r3 , [ r5 , #M A C H I N F O _ T Y P E ] @ g e t m a c h i n e t y p e
teq r3 , r1 @ matches loader number?
beq 2 f @ found
add r5 , r5 , #S I Z E O F _ M A C H I N E _ D E S C @ n e x t m a c h i n e _ d e s c
cmp r5 , r6
blo 1 b
mov r5 , #0 @ unknown machine
2 : mov p c , l r
/ *
* This p r o v i d e s a C - A P I v e r s i o n o f t h e a b o v e f u n c t i o n .
* /
ENTRY( l o o k u p _ m a c h i n e _ t y p e )
stmfd s p ! , { r4 - r6 , l r }
mov r1 , r0
bl _ _ l o o k u p _ m a c h i n e _ t y p e
mov r0 , r5
ldmfd s p ! , { r4 - r6 , p c }