2006-03-27 17:58:25 +04:00
/ *
* linux/ a r c h / a r m / k e r n e l / h e a d - c o m m o n . S
*
* Copyright ( C ) 1 9 9 4 - 2 0 0 2 R u s s e l l K i n g
* 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
*
* 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 .
*
* /
2008-03-05 08:50:07 +03:00
# define A T A G _ C O R E 0 x54 4 1 0 0 0 1
# define A T A G _ C O R E _ S I Z E ( ( 2 * 4 + 3 * 4 ) > > 2 )
2009-10-01 20:43:29 +04:00
# define A T A G _ C O R E _ S I Z E _ E M P T Y ( ( 2 * 4 ) > > 2 )
2008-03-05 08:50:07 +03:00
2009-07-24 15:32:52 +04:00
.align 2
2006-03-27 17:58:25 +04:00
.type _ _ switch_ d a t a , % o b j e c t
__switch_data :
.long __mmap_switched
.long __data_loc @ r4
2008-12-01 14:53:07 +03:00
.long _data @ r5
2006-03-27 17:58:25 +04:00
.long __bss_start @ r6
.long _end @ r7
.long processor_id @ r4
.long __machine_arch_type @ r5
2007-06-01 01:02:22 +04:00
.long __atags_pointer @ r6
.long cr_alignment @ r7
2006-03-27 17:58:25 +04:00
.long init_thread_union + THREAD_ S T A R T _ S P @ sp
/ *
* 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 i n M M U m o d e ,
* and u s e s a b s o l u t e 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
2007-06-01 01:02:22 +04:00
* r2 = a t a g s p o i n t e r
2006-03-27 17:58:25 +04:00
* r9 = p r o c e s s o r I D
* /
__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
2009-07-24 15:32:54 +04:00
ARM( l d m i a r3 , { r4 , r5 , r6 , r7 , s p } )
THUMB( l d m i a r3 , { r4 , r5 , r6 , r7 } )
THUMB( l d r s p , [ r3 , #16 ] )
2006-03-27 17:58:25 +04:00
str r9 , [ r4 ] @ Save processor ID
str r1 , [ r5 ] @ Save machine type
2007-06-01 01:02:22 +04:00
str r2 , [ r6 ] @ Save atags pointer
2006-03-27 17:58:25 +04:00
bic r4 , r0 , #C R _ A @ C l e a r ' A ' b i t
2007-06-01 01:02:22 +04:00
stmia r7 , { r0 , r4 } @ Save control register values
2006-03-27 17:58:25 +04:00
b s t a r t _ k e r n e l
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ m m a p _ s w i t c h e d )
2006-03-27 17:58:25 +04:00
/ *
* 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 ) .
* /
__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
2008-03-28 23:11:47 +03:00
mov r0 , r9
bl p r i n t h e x8
adr r0 , s t r _ p2
bl p r i n t a s c i i
2006-03-27 17:58:25 +04:00
b _ _ e r r o r
2008-03-28 23:11:47 +03:00
str_p1 : .asciz " \nError: unrecognized/unsupported processor variant (0x "
str_p2 : .asciz " ).\n "
2006-03-27 17:58:25 +04:00
.align
# endif
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ e r r o r _ p )
2006-03-27 17:58:25 +04:00
__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
2009-11-07 09:35:06 +03:00
adr r3 , 4 f
2006-03-27 17:58:25 +04:00
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
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ e r r o r _ a )
2006-03-27 17:58:25 +04:00
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
__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
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ e r r o r )
2006-03-27 17:58:25 +04:00
/ *
* 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 .
*
* r9 = c p u i d
* 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 ( p r e s e r v e d )
* /
__lookup_processor_type :
adr r3 , 3 f
2009-07-24 15:32:54 +04:00
ldmia r3 , { r5 - r7 }
add r3 , r3 , #8
2006-03-27 17:58:25 +04:00
sub r3 , r3 , r7 @ get offset between virt&phys
add r5 , r5 , r3 @ convert virt addresses to
add r6 , r6 , r3 @ physical address space
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
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ l o o k u p _ p r o c e s s o r _ t y p e )
2006-03-27 17:58:25 +04:00
/ *
* 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 - r7 , r9 , l r }
mov r9 , r0
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 - r7 , r9 , p c }
2008-08-28 14:22:32 +04:00
ENDPROC( l o o k u p _ p r o c e s s o r _ t y p e )
2006-03-27 17:58:25 +04:00
/ *
2008-08-02 13:55:55 +04:00
* Look i n < a s 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
2006-03-27 17:58:25 +04:00
* 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 .
* /
2009-07-24 15:32:52 +04:00
.align 2
2009-07-24 15:32:54 +04:00
3 : .long _ _ p r o c _ i n f o _ b e g i n
2006-03-27 17:58:25 +04:00
.long __proc_info_end
2009-07-24 15:32:54 +04:00
4 : .long .
2006-03-27 17:58:25 +04:00
.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
* /
__lookup_machine_type :
2009-07-24 15:32:54 +04:00
adr r3 , 4 b
2006-03-27 17:58:25 +04:00
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
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ l o o k u p _ m a c h i n e _ t y p e )
2006-03-27 17:58:25 +04:00
/ *
* 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 }
2008-08-28 14:22:32 +04:00
ENDPROC( l o o k u p _ m a c h i n e _ t y p e )
2007-06-01 01:02:22 +04:00
/ * Determine v a l i d i t y o f t h e r2 a t a g s p o i n t e r . T h e h e u r i s t i c r e q u i r e s
* that t h e p o i n t e r b e a l i g n e d , i n t h e f i r s t 1 6 k o f p h y s i c a l R A M a n d
* that t h e A T A G _ C O R E m a r k e r i s f i r s t a n d p r e s e n t . F u t u r e r e v i s i o n s
* of t h i s f u n c t i o n m a y b e m o r e l e n i e n t w i t h t h e p h y s i c a l a d d r e s s a n d
* may a l s o b e a b l e t o m o v e t h e A T A G S b l o c k i f n e c e s s a r y .
*
* r8 = m a c h i n f o
*
* Returns :
* r2 e i t h e r v a l i d a t a g s p o i n t e r , o r z e r o
* r5 , r6 c o r r u p t e d
* /
__vet_atags :
tst r2 , #0x3 @ aligned?
bne 1 f
ldr r5 , [ r2 , #0 ] @ is first tag ATAG_CORE?
2009-10-01 20:43:29 +04:00
cmp r5 , #A T A G _ C O R E _ S I Z E
cmpne r5 , #A T A G _ C O R E _ S I Z E _ E M P T Y
2007-06-01 01:02:22 +04:00
bne 1 f
ldr r5 , [ r2 , #4 ]
ldr r6 , =ATAG_CORE
cmp r5 , r6
bne 1 f
mov p c , l r @ atag pointer is ok
1 : mov r2 , #0
mov p c , l r
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ v e t _ a t a g s )