2005-04-16 15:20:36 -07:00
/ *
* linux/ a r c h / a r m / b o o t / c o m p r e s s e d / h e a d . S
*
* Copyright ( C ) 1 9 9 6 - 2 0 0 2 R u s s e l l K i n g
2006-03-27 10:21:34 +01:00
* Copyright ( C ) 2 0 0 4 H y o k S . C h o i ( M P U s u p p o r t )
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 .
* /
# include < l i n u x / l i n k a g e . h >
/ *
* Debugging s t u f f
*
* Note t h a t t h e s e m a c r o s m u s t n o t c o n t a i n a n y c o d e w h i c h i s n o t
* 1 0 0 % relocatable. A n y a t t e m p t t o d o s o w i l l r e s u l t i n a c r a s h .
* Please s e l e c t o n e o f t h e f o l l o w i n g w h e n t u r n i n g o n d e b u g g i n g .
* /
# ifdef D E B U G
2005-05-03 12:18:46 +01:00
# if d e f i n e d ( C O N F I G _ D E B U G _ I C E D C C )
2006-09-20 13:03:34 +01:00
2011-03-23 22:46:15 +01:00
# if d e f i n e d ( C O N F I G _ C P U _ V 6 ) | | d e f i n e d ( C O N F I G _ C P U _ V 6 K ) | | d e f i n e d ( C O N F I G _ C P U _ V 7 )
2010-02-01 23:26:53 +01:00
.macro loadsp, r b , t m p
2006-09-20 13:03:34 +01:00
.endm
.macro writeb, c h , r b
mcr p14 , 0 , \ c h , c0 , c5 , 0
.endm
2009-02-25 04:20:40 +01:00
# elif d e f i n e d ( C O N F I G _ C P U _ X S C A L E )
2010-02-01 23:26:53 +01:00
.macro loadsp, r b , t m p
2009-02-25 04:20:40 +01:00
.endm
.macro writeb, c h , r b
mcr p14 , 0 , \ c h , c8 , c0 , 0
.endm
2006-09-20 13:03:34 +01:00
# else
2010-02-01 23:26:53 +01:00
.macro loadsp, r b , t m p
2005-04-16 15:20:36 -07:00
.endm
2005-11-16 14:59:51 +00:00
.macro writeb, c h , r b
2007-12-13 09:31:34 +01:00
mcr p14 , 0 , \ c h , c1 , c0 , 0
2005-04-16 15:20:36 -07:00
.endm
2006-09-20 13:03:34 +01:00
# endif
2005-05-03 12:18:46 +01:00
# else
2005-11-16 14:59:51 +00:00
2008-08-05 16:14:15 +01:00
# include < m a c h / d e b u g - m a c r o . S >
2005-11-16 14:59:51 +00:00
2005-05-03 12:18:46 +01:00
.macro writeb, c h , r b
senduart \ c h , \ r b
2005-04-16 15:20:36 -07:00
.endm
2005-05-03 12:18:46 +01:00
2005-11-16 14:59:51 +00:00
# if d e f i n e d ( C O N F I G _ A R C H _ S A 1 1 0 0 )
2010-02-01 23:26:53 +01:00
.macro loadsp, r b , t m p
2005-04-16 15:20:36 -07:00
mov \ r b , #0x80000000 @ physical base address
2005-11-16 14:59:51 +00:00
# ifdef C O N F I G _ D E B U G _ L L _ S E R 3
2005-04-16 15:20:36 -07:00
add \ r b , \ r b , #0x00050000 @ Ser3
2005-11-16 14:59:51 +00:00
# else
2005-04-16 15:20:36 -07:00
add \ r b , \ r b , #0x00010000 @ Ser1
2005-11-16 14:59:51 +00:00
# endif
2005-04-16 15:20:36 -07:00
.endm
# elif d e f i n e d ( C O N F I G _ A R C H _ S 3 C 2 4 1 0 )
2010-02-01 23:26:53 +01:00
.macro loadsp, r b , t m p
2005-04-16 15:20:36 -07:00
mov \ r b , #0x50000000
2007-07-22 16:11:20 +01:00
add \ r b , \ r b , #0x4000 * C O N F I G _ S 3 C _ L O W L E V E L _ U A R T _ P O R T
2005-04-16 15:20:36 -07:00
.endm
# else
2010-02-01 23:26:53 +01:00
.macro loadsp, r b , t m p
addruart \ r b , \ t m p
2005-11-16 14:59:51 +00:00
.endm
2005-04-16 15:20:36 -07:00
# endif
2005-05-03 12:18:46 +01:00
# endif
2005-04-16 15:20:36 -07:00
# endif
.macro kputc,v a l
mov r0 , \ v a l
bl p u t c
.endm
.macro kphex,v a l ,l e n
mov r0 , \ v a l
mov r1 , #\ l e n
bl p h e x
.endm
.macro debug_reloc_start
# ifdef D E B U G
kputc #' \n '
kphex r6 , 8 / * p r o c e s s o r i d * /
kputc #' : '
kphex r7 , 8 / * a r c h i t e c t u r e i d * /
2006-09-26 17:36:37 +09:00
# ifdef C O N F I G _ C P U _ C P 1 5
2005-04-16 15:20:36 -07:00
kputc #' : '
mrc p15 , 0 , r0 , c1 , c0
kphex r0 , 8 / * c o n t r o l r e g * /
2006-09-26 17:36:37 +09:00
# endif
2005-04-16 15:20:36 -07:00
kputc #' \n '
kphex r5 , 8 / * d e c o m p r e s s e d k e r n e l s t a r t * /
kputc #' - '
2006-01-12 17:17:57 +00:00
kphex r9 , 8 / * d e c o m p r e s s e d k e r n e l e n d * /
2005-04-16 15:20:36 -07:00
kputc #' > '
kphex r4 , 8 / * k e r n e l e x e c u t i o n a d d r e s s * /
kputc #' \n '
# endif
.endm
.macro debug_reloc_end
# ifdef D E B U G
kphex r5 , 8 / * e n d o f k e r n e l * /
kputc #' \n '
mov r0 , r4
bl m e m d u m p / * d u m p 2 5 6 b y t e s a t s t a r t o f k e r n e l * /
# endif
.endm
.section " .start " , # alloc, #e x e c i n s t r
/ *
* sort o u t d i f f e r e n t c a l l i n g c o n v e n t i o n s
* /
.align
2010-11-29 19:43:27 +01:00
.arm @ Always enter in ARM state
2005-04-16 15:20:36 -07:00
start :
.type start,#f u n c t i o n
2011-02-12 22:25:27 +01:00
.rept 7
2005-04-16 15:20:36 -07:00
mov r0 , r0
.endr
2011-02-12 22:25:27 +01:00
ARM( m o v r0 , r0 )
ARM( b 1 f )
THUMB( a d r r12 , B S Y M ( 1 f ) )
THUMB( b x r12 )
2005-04-16 15:20:36 -07:00
.word 0x016f2818 @ Magic numbers to help the loader
.word start @ absolute load/run zImage address
.word _edata @ zImage end address
2010-11-29 19:43:27 +01:00
THUMB( . t h u m b )
2005-04-16 15:20:36 -07:00
1 : mov r7 , r1 @ save architecture ID
2006-01-12 17:17:57 +00:00
mov r8 , r2 @ save atags pointer
2005-04-16 15:20:36 -07:00
# ifndef _ _ A R M _ A R C H _ 2 _ _
/ *
* Booting f r o m A n g e l - n e e d t o e n t e r S V C m o d e a n d d i s a b l e
* FIQs/ I R Q s ( n u m e r i c d e f i n i t i o n s f r o m a n g e l a r m . h s o u r c e ) .
* We o n l y d o t h i s i f w e w e r e i n u s e r m o d e o n e n t r y .
* /
mrs r2 , c p s r @ get current mode
tst r2 , #3 @ not user?
bne n o t _ a n g e l
mov r0 , #0x17 @ angel_SWIreason_EnterSVC
2009-07-24 12:32:58 +01:00
ARM( s w i 0 x12 3 4 5 6 ) @ angel_SWI_ARM
THUMB( s v c 0 x a b ) @ angel_SWI_THUMB
2005-04-16 15:20:36 -07:00
not_angel :
mrs r2 , c p s r @ turn off interrupts to
orr r2 , r2 , #0xc0 @ prevent angel from running
msr c p s r _ c , r2
# else
teqp p c , #0x0c000003 @ turn off interrupts
# endif
/ *
* Note t h a t s o m e c a c h e f l u s h i n g a n d o t h e r s t u f f m a y
* be n e e d e d h e r e - i s t h e r e a n A n g e l S W I c a l l f o r t h i s ?
* /
/ *
* some a r c h i t e c t u r e s p e c i f i c c o d e c a n b e i n s e r t e d
2006-01-12 17:17:57 +00:00
* by t h e l i n k e r h e r e , b u t i t s h o u l d p r e s e r v e r7 , r8 , a n d r9 .
2005-04-16 15:20:36 -07:00
* /
.text
2011-02-21 07:06:45 +01:00
2010-07-05 15:56:50 +02:00
# ifdef C O N F I G _ A U T O _ Z R E L A D D R
@ determine final kernel image address
2010-11-29 19:43:26 +01:00
mov r4 , p c
and r4 , r4 , #0xf8000000
2010-07-05 15:56:50 +02:00
add r4 , r4 , #T E X T _ O F F S E T
# else
2010-09-09 22:39:41 +01:00
ldr r4 , =zreladdr
2010-07-05 15:56:50 +02:00
# endif
2005-04-16 15:20:36 -07:00
2011-02-21 07:06:45 +01:00
bl c a c h e _ o n
restart : adr r0 , L C 0
2011-04-19 15:42:43 -04:00
ldmia r0 , { r1 , r2 , r3 , r6 , r10 , r11 , r12 }
2011-04-27 16:15:11 -04:00
ldr s p , [ r0 , #28 ]
2011-02-21 07:06:45 +01:00
/ *
* We m i g h t b e r u n n i n g a t a d i f f e r e n t a d d r e s s . W e n e e d
* to f i x u p v a r i o u s p o i n t e r s .
* /
sub r0 , r0 , r1 @ calculate the delta offset
add r6 , r6 , r0 @ _edata
2011-04-19 15:42:43 -04:00
add r10 , r10 , r0 @ inflated kernel size location
/ *
* The k e r n e l b u i l d s y s t e m a p p e n d s t h e s i z e o f t h e
* decompressed k e r n e l a t t h e e n d o f t h e c o m p r e s s e d d a t a
* in l i t t l e - e n d i a n f o r m .
* /
ldrb r9 , [ r10 , #0 ]
ldrb l r , [ r10 , #1 ]
orr r9 , r9 , l r , l s l #8
ldrb l r , [ r10 , #2 ]
ldrb r10 , [ r10 , #3 ]
orr r9 , r9 , l r , l s l #16
orr r9 , r9 , r10 , l s l #24
2005-04-16 15:20:36 -07:00
2011-02-21 07:06:45 +01:00
# ifndef C O N F I G _ Z B O O T _ R O M
/* malloc space is above the relocated stack (64k max) */
add s p , s p , r0
add r10 , s p , #0x10000
# else
2005-04-16 15:20:36 -07:00
/ *
2011-02-21 07:06:45 +01:00
* With Z B O O T _ R O M t h e b s s / s t a c k i s n o n r e l o c a t a b l e ,
* but s o m e o n e c o u l d s t i l l r u n t h i s c o d e f r o m R A M ,
* in w h i c h c a s e o u r r e f e r e n c e i s _ e d a t a .
2005-04-16 15:20:36 -07:00
* /
2011-02-21 07:06:45 +01:00
mov r10 , r6
# endif
2011-05-27 18:45:50 -04:00
mov r5 , #0 @ init dtb size to 0
# ifdef C O N F I G _ A R M _ A P P E N D E D _ D T B
/ *
* r0 = d e l t a
* r2 = B S S s t a r t
* r3 = B S S e n d
* r4 = f i n a l k e r n e l a d d r e s s
* r5 = a p p e n d e d d t b s i z e ( s t i l l u n k n o w n )
* r6 = _ e d a t a
* r7 = a r c h i t e c t u r e I D
* r8 = a t a g s / d e v i c e t r e e p o i n t e r
* r9 = s i z e o f d e c o m p r e s s e d i m a g e
* r1 0 = e n d o f t h i s i m a g e , i n c l u d i n g b s s / s t a c k / m a l l o c s p a c e i f n o n X I P
* r1 1 = G O T s t a r t
* r1 2 = G O T e n d
* sp = s t a c k p o i n t e r
*
* if t h e r e a r e d e v i c e t r e e s ( d t b ) a p p e n d e d t o z I m a g e , a d v a n c e r10 s o t h a t t h e
* dtb d a t a w i l l g e t r e l o c a t e d a l o n g w i t h t h e k e r n e l i f n e c e s s a r y .
* /
ldr l r , [ r6 , #0 ]
# ifndef _ _ A R M E B _ _
ldr r1 , =0xedfe0dd0 @ sig is 0xd00dfeed big endian
# else
ldr r1 , =0xd00dfeed
# endif
cmp l r , r1
bne d t b _ c h e c k _ d o n e @ not found
2011-09-13 22:37:07 -04:00
# ifdef C O N F I G _ A R M _ A T A G _ D T B _ C O M P A T
/ *
* OK. . . L e t ' s d o s o m e f u n k y b u s i n e s s h e r e .
* If w e d o h a v e a D T B a p p e n d e d t o z I m a g e , a n d w e d o h a v e
* an A T A G l i s t a r o u n d , w e w a n t t h e l a t e r t o b e t r a n s l a t e d
* and f o l d e d i n t o t h e f o r m e r h e r e . T o b e o n t h e s a f e s i d e ,
* let' s t e m p o r a r i l y m o v e t h e s t a c k a w a y i n t o t h e m a l l o c
* area. N o G O T f i x u p h a s o c c u r r e d y e t , b u t n o n e o f t h e
* code w e ' r e a b o u t t o c a l l u s e s a n y g l o b a l v a r i a b l e .
* /
add s p , s p , #0x10000
stmfd s p ! , { r0 - r3 , i p , l r }
mov r0 , r8
mov r1 , r6
sub r2 , s p , r6
bl a t a g s _ t o _ f d t
/ *
* If r e t u r n e d v a l u e i s 1 , t h e r e i s n o A T A G a t t h e l o c a t i o n
* pointed b y r8 . T r y t h e t y p i c a l 0 x10 0 o f f s e t f r o m s t a r t
* of R A M a n d h o p e f o r t h e b e s t .
* /
cmp r0 , #1
sub r0 , r4 , #( T E X T _ O F F S E T - 0x100 )
mov r1 , r6
sub r2 , s p , r6
blne a t a g s _ t o _ f d t
ldmfd s p ! , { r0 - r3 , i p , l r }
sub s p , s p , #0x10000
# endif
2011-05-27 18:45:50 -04:00
mov r8 , r6 @ use the appended device tree
2011-06-12 01:07:33 -04:00
/ *
* Make s u r e t h a t t h e D T B d o e s n ' t e n d u p i n t h e f i n a l
* kernel' s . b s s a r e a . T o d o s o , w e a d j u s t t h e d e c o m p r e s s e d
* kernel s i z e t o c o m p e n s a t e i f t h a t . b s s s i z e i s l a r g e r
* than t h e r e l o c a t e d c o d e .
* /
ldr r5 , =_kernel_bss_size
adr r1 , w o n t _ o v e r w r i t e
sub r1 , r6 , r1
subs r1 , r5 , r1
addhi r9 , r9 , r1
2011-05-27 18:45:50 -04:00
/* Get the dtb's size */
ldr r5 , [ r6 , #4 ]
# ifndef _ _ A R M E B _ _
/* convert r5 (dtb size) to little endian */
eor r1 , r5 , r5 , r o r #16
bic r1 , r1 , #0x00ff0000
mov r5 , r5 , r o r #8
eor r5 , r5 , r1 , l s r #8
# endif
/* preserve 64-bit alignment */
add r5 , r5 , #7
bic r5 , r5 , #7
/* relocate some pointers past the appended dtb */
add r6 , r6 , r5
add r10 , r10 , r5
add s p , s p , r5
dtb_check_done :
# endif
2011-02-21 07:06:45 +01:00
/ *
* Check t o s e e i f w e w i l l o v e r w r i t e o u r s e l v e s .
* r4 = f i n a l k e r n e l a d d r e s s
* r9 = s i z e o f d e c o m p r e s s e d i m a g e
* r1 0 = e n d o f t h i s i m a g e , i n c l u d i n g b s s / s t a c k / m a l l o c s p a c e i f n o n X I P
* We b a s i c a l l y w a n t :
2011-04-21 22:52:06 -04:00
* r4 - 1 6 k p a g e d i r e c t o r y > = r10 - > O K
2011-06-12 01:07:33 -04:00
* r4 + i m a g e l e n g t h < = a d d r e s s o f w o n t _ o v e r w r i t e - > O K
2011-02-21 07:06:45 +01:00
* /
2011-04-21 22:52:06 -04:00
add r10 , r10 , #16384
2011-02-21 07:06:45 +01:00
cmp r4 , r10
bhs w o n t _ o v e r w r i t e
add r10 , r4 , r9
2011-06-12 01:07:33 -04:00
adr r9 , w o n t _ o v e r w r i t e
cmp r10 , r9
2011-02-21 07:06:45 +01:00
bls w o n t _ o v e r w r i t e
/ *
* Relocate o u r s e l v e s p a s t t h e e n d o f t h e d e c o m p r e s s e d k e r n e l .
* r6 = _ e d a t a
* r1 0 = e n d o f t h e d e c o m p r e s s e d k e r n e l
* Because w e a l w a y s c o p y a h e a d , w e n e e d t o d o i t f r o m t h e e n d a n d g o
* backward i n c a s e t h e s o u r c e a n d d e s t i n a t i o n o v e r l a p .
* /
2011-04-27 16:15:11 -04:00
/ *
* Bump t o t h e n e x t 2 5 6 - b y t e b o u n d a r y w i t h t h e s i z e o f
* the r e l o c a t i o n c o d e a d d e d . T h i s a v o i d s o v e r w r i t i n g
* ourself w h e n t h e o f f s e t i s s m a l l .
* /
add r10 , r10 , #( ( r e l o c _ c o d e _ e n d - r e s t a r t + 256 ) & ~ 2 5 5 )
2011-02-21 07:06:45 +01:00
bic r10 , r10 , #255
2011-04-27 16:15:11 -04:00
/* Get start of code we want to copy and align it down. */
adr r5 , r e s t a r t
bic r5 , r5 , #31
2011-02-21 07:06:45 +01:00
sub r9 , r6 , r5 @ size to copy
add r9 , r9 , #31 @ rounded up to a multiple
bic r9 , r9 , #31 @ ... of 32 bytes
add r6 , r9 , r5
add r9 , r9 , r10
1 : ldmdb r6 ! , { r0 - r3 , r10 - r12 , l r }
cmp r6 , r5
stmdb r9 ! , { r0 - r3 , r10 - r12 , l r }
bhi 1 b
/* Preserve offset to relocated code. */
sub r6 , r9 , r6
2011-04-26 05:37:46 -07:00
# ifndef C O N F I G _ Z B O O T _ R O M
/* cache_clean_flush may use the stack, so relocate it */
add s p , s p , r6
# endif
2011-02-21 07:06:45 +01:00
bl c a c h e _ c l e a n _ f l u s h
adr r0 , B S Y M ( r e s t a r t )
add r0 , r0 , r6
mov p c , r0
wont_overwrite :
/ *
* If d e l t a i s z e r o , w e a r e r u n n i n g a t t h e a d d r e s s w e w e r e l i n k e d a t .
* r0 = d e l t a
* r2 = B S S s t a r t
* r3 = B S S e n d
* r4 = k e r n e l e x e c u t i o n a d d r e s s
2011-05-27 18:45:50 -04:00
* r5 = a p p e n d e d d t b s i z e ( 0 i f n o t p r e s e n t )
2011-02-21 07:06:45 +01:00
* r7 = a r c h i t e c t u r e I D
* r8 = a t a g s p o i n t e r
* r1 1 = G O T s t a r t
* r1 2 = G O T e n d
* sp = s t a c k p o i n t e r
* /
2011-05-27 18:45:50 -04:00
orrs r1 , r0 , r5
2011-02-21 07:06:45 +01:00
beq n o t _ r e l o c a t e d
2011-05-27 18:45:50 -04:00
2010-02-25 23:56:38 +00:00
add r11 , r11 , r0
2011-02-21 07:06:45 +01:00
add r12 , r12 , r0
2005-04-16 15:20:36 -07:00
# ifndef C O N F I G _ Z B O O T _ R O M
/ *
* If w e ' r e r u n n i n g f u l l y P I C = = = C O N F I G _ Z B O O T _ R O M = n ,
* we n e e d t o f i x u p p o i n t e r s i n t o t h e B S S r e g i o n .
2011-02-21 07:06:45 +01:00
* Note t h a t t h e s t a c k p o i n t e r h a s a l r e a d y b e e n f i x e d u p .
2005-04-16 15:20:36 -07:00
* /
add r2 , r2 , r0
add r3 , r3 , r0
/ *
* Relocate a l l e n t r i e s i n t h e G O T t a b l e .
2011-05-27 18:45:50 -04:00
* Bump b s s e n t r i e s t o _ e d a t a + d t b s i z e
2005-04-16 15:20:36 -07:00
* /
2010-02-25 23:56:38 +00:00
1 : ldr r1 , [ r11 , #0 ] @ relocate entries in the GOT
2011-05-27 18:45:50 -04:00
add r1 , r1 , r0 @ This fixes up C references
cmp r1 , r2 @ if entry >= bss_start &&
cmphs r3 , r1 @ bss_end > entry
addhi r1 , r1 , r5 @ entry += dtb size
str r1 , [ r11 ] , #4 @ next entry
2011-02-21 07:06:45 +01:00
cmp r11 , r12
2005-04-16 15:20:36 -07:00
blo 1 b
2011-05-27 18:45:50 -04:00
/* bump our bss pointers too */
add r2 , r2 , r5
add r3 , r3 , r5
2005-04-16 15:20:36 -07:00
# else
/ *
* Relocate e n t r i e s i n t h e G O T t a b l e . W e o n l y r e l o c a t e
* the e n t r i e s t h a t a r e o u t s i d e t h e ( r e l o c a t e d ) B S S r e g i o n .
* /
2010-02-25 23:56:38 +00:00
1 : ldr r1 , [ r11 , #0 ] @ relocate entries in the GOT
2005-04-16 15:20:36 -07:00
cmp r1 , r2 @ entry < bss_start ||
cmphs r3 , r1 @ _end < entry
addlo r1 , r1 , r0 @ table. This fixes up the
2010-02-25 23:56:38 +00:00
str r1 , [ r11 ] , #4 @ C references.
2011-02-21 07:06:45 +01:00
cmp r11 , r12
2005-04-16 15:20:36 -07:00
blo 1 b
# endif
not_relocated : mov r0 , #0
1 : str r0 , [ r2 ] , #4 @ clear bss
str r0 , [ r2 ] , #4
str r0 , [ r2 ] , #4
str r0 , [ r2 ] , #4
cmp r2 , r3
blo 1 b
/ *
2011-02-21 07:06:45 +01:00
* The C r u n t i m e e n v i r o n m e n t s h o u l d n o w b e s e t u p s u f f i c i e n t l y .
* Set u p s o m e p o i n t e r s , a n d s t a r t d e c o m p r e s s i n g .
* r4 = k e r n e l e x e c u t i o n a d d r e s s
* r7 = a r c h i t e c t u r e I D
* r8 = a t a g s p o i n t e r
2005-04-16 15:20:36 -07:00
* /
2011-02-21 07:06:45 +01:00
mov r0 , r4
mov r1 , s p @ malloc space above stack
add r2 , s p , #0x10000 @ 64k max
2005-04-16 15:20:36 -07:00
mov r3 , r7
bl d e c o m p r e s s _ k e r n e l
bl c a c h e _ c l e a n _ f l u s h
2011-02-21 07:06:45 +01:00
bl c a c h e _ o f f
mov r0 , #0 @ must be zero
mov r1 , r7 @ restore architecture number
mov r2 , r8 @ restore atags pointer
2011-07-13 15:53:30 +01:00
ARM( m o v p c , r4 ) @ call kernel
THUMB( b x r4 ) @ entry point is always ARM
2005-04-16 15:20:36 -07:00
2009-07-24 12:32:52 +01:00
.align 2
2005-04-16 15:20:36 -07:00
.type LC0 , #o b j e c t
LC0 : .word L C 0 @ r1
.word __bss_start @ r2
.word _end @ r3
2011-02-21 07:06:45 +01:00
.word _edata @ r6
2011-04-19 15:42:43 -04:00
.word input_data_end - 4 @ r10 (inflated size location)
2010-02-25 23:56:38 +00:00
.word _got_start @ r11
2005-04-16 15:20:36 -07:00
.word _got_end @ ip
2011-04-27 14:54:39 -04:00
.word .L_user_stack_end @ sp
2005-04-16 15:20:36 -07:00
.size LC0 , . - L C 0
# ifdef C O N F I G _ A R C H _ R P C
.globl params
2010-06-03 15:36:49 +08:00
params : ldr r0 , =0x10000100 @ params_phys for RPC
2005-04-16 15:20:36 -07:00
mov p c , l r
.ltorg
.align
# endif
/ *
* Turn o n t h e c a c h e . W e n e e d t o s e t u p s o m e p a g e t a b l e s s o t h a t w e
* can h a v e b o t h t h e I a n d D c a c h e s o n .
*
* We p l a c e t h e p a g e t a b l e s 1 6 k d o w n f r o m t h e k e r n e l e x e c u t i o n a d d r e s s ,
* and w e h o p e t h a t n o t h i n g e l s e i s u s i n g i t . I f w e ' r e u s i n g i t , w e
* will g o p o p !
*
* On e n t r y ,
* r4 = k e r n e l e x e c u t i o n a d d r e s s
* r7 = a r c h i t e c t u r e n u m b e r
2006-01-12 17:17:57 +00:00
* r8 = a t a g s p o i n t e r
2005-04-16 15:20:36 -07:00
* On e x i t ,
2010-01-26 22:08:09 +01:00
* r0 , r1 , r2 , r3 , r9 , r10 , r12 c o r r u p t e d
2005-04-16 15:20:36 -07:00
* This r o u t i n e m u s t p r e s e r v e :
2011-02-21 07:06:45 +01:00
* r4 , r7 , r8
2005-04-16 15:20:36 -07:00
* /
.align 5
cache_on : mov r3 , #8 @ cache_on function
b c a l l _ c a c h e _ f n
2006-03-27 10:21:34 +01:00
/ *
* Initialize t h e h i g h e s t p r i o r i t y p r o t e c t i o n r e g i o n , P R 7
* to c o v e r a l l 3 2 b i t a d d r e s s a n d c a c h e a b l e a n d b u f f e r a b l e .
* /
__armv4_mpu_cache_on :
mov r0 , #0x3f @ 4G, the whole
mcr p15 , 0 , r0 , c6 , c7 , 0 @ PR7 Area Setting
mcr p15 , 0 , r0 , c6 , c7 , 1
mov r0 , #0x80 @ PR7
mcr p15 , 0 , r0 , c2 , c0 , 0 @ D-cache on
mcr p15 , 0 , r0 , c2 , c0 , 1 @ I-cache on
mcr p15 , 0 , r0 , c3 , c0 , 0 @ write-buffer on
mov r0 , #0xc000
mcr p15 , 0 , r0 , c5 , c0 , 1 @ I-access permission
mcr p15 , 0 , r0 , c5 , c0 , 0 @ D-access permission
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c10 , 4 @ drain write buffer
mcr p15 , 0 , r0 , c7 , c5 , 0 @ flush(inval) I-Cache
mcr p15 , 0 , r0 , c7 , c6 , 0 @ flush(inval) D-Cache
mrc p15 , 0 , r0 , c1 , c0 , 0 @ read control reg
@ ...I .... ..D. WC.M
orr r0 , r0 , #0x002d @ .... .... ..1. 11.1
orr r0 , r0 , #0x1000 @ ...1 .... .... ....
mcr p15 , 0 , r0 , c1 , c0 , 0 @ write control reg
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c5 , 0 @ flush(inval) I-Cache
mcr p15 , 0 , r0 , c7 , c6 , 0 @ flush(inval) D-Cache
mov p c , l r
__armv3_mpu_cache_on :
mov r0 , #0x3f @ 4G, the whole
mcr p15 , 0 , r0 , c6 , c7 , 0 @ PR7 Area Setting
mov r0 , #0x80 @ PR7
mcr p15 , 0 , r0 , c2 , c0 , 0 @ cache on
mcr p15 , 0 , r0 , c3 , c0 , 0 @ write-buffer on
mov r0 , #0xc000
mcr p15 , 0 , r0 , c5 , c0 , 0 @ access permission
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c0 , 0 @ invalidate whole cache v3
2010-01-26 22:14:23 +01:00
/ *
* ? ? ARMv3 M M U d o e s n o t a l l o w r e a d i n g t h e c o n t r o l r e g i s t e r ,
* does t h i s r e a l l y w o r k o n A R M v3 M P U ?
* /
2006-03-27 10:21:34 +01:00
mrc p15 , 0 , r0 , c1 , c0 , 0 @ read control reg
@ .... .... .... WC.M
orr r0 , r0 , #0x000d @ .... .... .... 11.1
2010-01-26 22:14:23 +01:00
/* ?? this overwrites the value constructed above? */
2006-03-27 10:21:34 +01:00
mov r0 , #0
mcr p15 , 0 , r0 , c1 , c0 , 0 @ write control reg
2010-01-26 22:14:23 +01:00
/* ?? invalidate for the second time? */
2006-03-27 10:21:34 +01:00
mcr p15 , 0 , r0 , c7 , c0 , 0 @ invalidate whole cache v3
mov p c , l r
2005-04-16 15:20:36 -07:00
__setup_mmu : sub r3 , r4 , #16384 @ Page directory size
bic r3 , r3 , #0xff @ Align the pointer
bic r3 , r3 , #0x3f00
/ *
* Initialise t h e p a g e t a b l e s , t u r n i n g o n t h e c a c h e a b l e a n d b u f f e r a b l e
* bits f o r t h e R A M a r e a o n l y .
* /
mov r0 , r3
2006-01-12 17:17:57 +00:00
mov r9 , r0 , l s r #18
mov r9 , r9 , l s l #18 @ start of RAM
add r10 , r9 , #0x10000000 @ a reasonable RAM size
2005-04-16 15:20:36 -07:00
mov r1 , #0x12
orr r1 , r1 , #3 < < 1 0
add r2 , r3 , #16384
2006-01-18 22:38:51 +00:00
1 : cmp r1 , r9 @ if virt > start of RAM
2011-04-01 15:41:26 +01:00
# ifdef C O N F I G _ C P U _ D C A C H E _ W R I T E T H R O U G H
orrhs r1 , r1 , #0x08 @ set cacheable
# else
2005-04-16 15:20:36 -07:00
orrhs r1 , r1 , #0x0c @ set cacheable, bufferable
2011-04-01 15:41:26 +01:00
# endif
2006-01-12 17:17:57 +00:00
cmp r1 , r10 @ if virt > end of RAM
2005-04-16 15:20:36 -07:00
bichs r1 , r1 , #0x0c @ clear cacheable, bufferable
str r1 , [ r0 ] , #4 @ 1:1 mapping
add r1 , r1 , #1048576
teq r0 , r2
bne 1 b
/ *
* If e v e r w e a r e r u n n i n g f r o m F l a s h , t h e n w e s u r e l y w a n t t h e c a c h e
* to b e e n a b l e d a l s o f o r o u r e x e c u t i o n i n s t a n c e . . . W e m a p 2 M B o f i t
* so t h e r e i s n o m a p o v e r l a p p r o b l e m f o r u p t o 1 M B c o m p r e s s e d k e r n e l .
* If t h e e x e c u t i o n i s i n R A M t h e n w e w o u l d o n l y b e d u p l i c a t i n g t h e a b o v e .
* /
mov r1 , #0x1e
orr r1 , r1 , #3 < < 1 0
2010-11-29 19:43:26 +01:00
mov r2 , p c
mov r2 , r2 , l s r #20
2005-04-16 15:20:36 -07:00
orr r1 , r1 , r2 , l s l #20
add r0 , r3 , r2 , l s l #2
str r1 , [ r0 ] , #4
add r1 , r1 , #1048576
str r1 , [ r0 ]
mov p c , l r
2008-08-28 11:22:32 +01:00
ENDPROC( _ _ s e t u p _ m m u )
2005-04-16 15:20:36 -07:00
2011-04-01 15:41:26 +01:00
__arm926ejs_mmu_cache_on :
# ifdef C O N F I G _ C P U _ D C A C H E _ W R I T E T H R O U G H
mov r0 , #4 @ put dcache in WT mode
mcr p15 , 7 , r0 , c15 , c0 , 0
# endif
2006-03-24 09:53:18 +00:00
__armv4_mmu_cache_on :
2005-04-16 15:20:36 -07:00
mov r12 , l r
2009-07-24 12:35:06 +01:00
# ifdef C O N F I G _ M M U
2005-04-16 15:20:36 -07:00
bl _ _ s e t u p _ m m u
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c10 , 4 @ drain write buffer
mcr p15 , 0 , r0 , c8 , c7 , 0 @ flush I,D TLBs
mrc p15 , 0 , r0 , c1 , c0 , 0 @ read control reg
orr r0 , r0 , #0x5000 @ I-cache enable, RR cache replacement
orr r0 , r0 , #0x0030
2009-05-30 14:00:18 +01:00
# ifdef C O N F I G _ C P U _ E N D I A N _ B E 8
orr r0 , r0 , #1 < < 2 5 @ big-endian page tables
# endif
2006-03-24 09:53:18 +00:00
bl _ _ c o m m o n _ m m u _ c a c h e _ o n
2005-04-16 15:20:36 -07:00
mov r0 , #0
mcr p15 , 0 , r0 , c8 , c7 , 0 @ flush I,D TLBs
2009-07-24 12:35:06 +01:00
# endif
2005-04-16 15:20:36 -07:00
mov p c , r12
2007-06-01 17:14:53 +01:00
__armv7_mmu_cache_on :
mov r12 , l r
2009-07-24 12:35:06 +01:00
# ifdef C O N F I G _ M M U
2007-06-01 17:14:53 +01:00
mrc p15 , 0 , r11 , c0 , c1 , 4 @ read ID_MMFR0
tst r11 , #0xf @ VMSA
blne _ _ s e t u p _ m m u
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c10 , 4 @ drain write buffer
tst r11 , #0xf @ VMSA
mcrne p15 , 0 , r0 , c8 , c7 , 0 @ flush I,D TLBs
2009-07-24 12:35:06 +01:00
# endif
2007-06-01 17:14:53 +01:00
mrc p15 , 0 , r0 , c1 , c0 , 0 @ read control reg
orr r0 , r0 , #0x5000 @ I-cache enable, RR cache replacement
orr r0 , r0 , #0x003c @ write buffer
2009-07-24 12:35:06 +01:00
# ifdef C O N F I G _ M M U
2009-05-30 14:00:18 +01:00
# ifdef C O N F I G _ C P U _ E N D I A N _ B E 8
orr r0 , r0 , #1 < < 2 5 @ big-endian page tables
# endif
2007-06-01 17:14:53 +01:00
orrne r0 , r0 , #1 @ MMU enabled
movne r1 , #- 1
mcrne p15 , 0 , r3 , c2 , c0 , 0 @ load page table pointer
mcrne p15 , 0 , r1 , c3 , c0 , 0 @ load domain access control
2009-07-24 12:35:06 +01:00
# endif
2007-06-01 17:14:53 +01:00
mcr p15 , 0 , r0 , c1 , c0 , 0 @ load control register
mrc p15 , 0 , r0 , c1 , c0 , 0 @ and read it back
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c5 , 4 @ ISB
mov p c , r12
2009-03-25 13:10:01 +02:00
__fa526_cache_on :
mov r12 , l r
bl _ _ s e t u p _ m m u
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c7 , 0 @ Invalidate whole cache
mcr p15 , 0 , r0 , c7 , c10 , 4 @ drain write buffer
mcr p15 , 0 , r0 , c8 , c7 , 0 @ flush UTLB
mrc p15 , 0 , r0 , c1 , c0 , 0 @ read control reg
orr r0 , r0 , #0x1000 @ I-cache enable
bl _ _ c o m m o n _ m m u _ c a c h e _ o n
mov r0 , #0
mcr p15 , 0 , r0 , c8 , c7 , 0 @ flush UTLB
mov p c , r12
2006-03-24 09:53:18 +00:00
__arm6_mmu_cache_on :
2005-04-16 15:20:36 -07:00
mov r12 , l r
bl _ _ s e t u p _ m m u
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c0 , 0 @ invalidate whole cache v3
mcr p15 , 0 , r0 , c5 , c0 , 0 @ invalidate whole TLB v3
mov r0 , #0x30
2006-03-24 09:53:18 +00:00
bl _ _ c o m m o n _ m m u _ c a c h e _ o n
2005-04-16 15:20:36 -07:00
mov r0 , #0
mcr p15 , 0 , r0 , c5 , c0 , 0 @ invalidate whole TLB v3
mov p c , r12
2006-03-24 09:53:18 +00:00
__common_mmu_cache_on :
2009-07-24 12:32:58 +01:00
# ifndef C O N F I G _ T H U M B 2 _ K E R N E L
2005-04-16 15:20:36 -07:00
# ifndef D E B U G
orr r0 , r0 , #0x000d @ Write buffer, mmu
# endif
mov r1 , #- 1
mcr p15 , 0 , r3 , c2 , c0 , 0 @ load page table pointer
mcr p15 , 0 , r1 , c3 , c0 , 0 @ load domain access control
2006-07-01 21:29:32 +01:00
b 1 f
.align 5 @ cache line aligned
1 : mcr p15 , 0 , r0 , c1 , c0 , 0 @ load control register
mrc p15 , 0 , r0 , c1 , c0 , 0 @ and read it back to
sub p c , l r , r0 , l s r #32 @ properly flush pipeline
2009-07-24 12:32:58 +01:00
# endif
2005-04-16 15:20:36 -07:00
2011-06-14 14:20:44 +01:00
# define P R O C _ E N T R Y _ S I Z E ( 4 * 5 )
2005-04-16 15:20:36 -07:00
/ *
* Here f o l l o w t h e r e l o c a t a b l e c a c h e s u p p o r t f u n c t i o n s f o r t h e
* various p r o c e s s o r s . T h i s i s a g e n e r i c h o o k f o r l o c a t i n g a n
* entry a n d j u m p i n g t o a n i n s t r u c t i o n a t t h e s p e c i f i e d o f f s e t
* from t h e s t a r t o f t h e b l o c k . P l e a s e n o t e t h i s i s a l l p o s i t i o n
* independent c o d e .
*
* r1 = c o r r u p t e d
* r2 = c o r r u p t e d
* r3 = b l o c k o f f s e t
2010-02-25 23:56:38 +00:00
* r9 = c o r r u p t e d
2005-04-16 15:20:36 -07:00
* r1 2 = c o r r u p t e d
* /
call_cache_fn : adr r12 , p r o c _ t y p e s
2006-09-26 17:36:37 +09:00
# ifdef C O N F I G _ C P U _ C P 1 5
2010-02-25 23:56:38 +00:00
mrc p15 , 0 , r9 , c0 , c0 @ get processor ID
2006-09-26 17:36:37 +09:00
# else
2010-02-25 23:56:38 +00:00
ldr r9 , =CONFIG_PROCESSOR_ID
2006-09-26 17:36:37 +09:00
# endif
2005-04-16 15:20:36 -07:00
1 : ldr r1 , [ r12 , #0 ] @ get value
ldr r2 , [ r12 , #4 ] @ get mask
2010-02-25 23:56:38 +00:00
eor r1 , r1 , r9 @ (real ^ match)
2005-04-16 15:20:36 -07:00
tst r1 , r2 @ & mask
2009-07-24 12:32:58 +01:00
ARM( a d d e q p c , r12 , r3 ) @ call cache function
THUMB( a d d e q r12 , r3 )
THUMB( m o v e q p c , r12 ) @ call cache function
2011-06-14 14:20:44 +01:00
add r12 , r12 , #P R O C _ E N T R Y _ S I Z E
2005-04-16 15:20:36 -07:00
b 1 b
/ *
* Table f o r c a c h e o p e r a t i o n s . T h i s i s b a s i c a l l y :
* - CPU I D m a t c h
* - CPU I D m a s k
* - ' cache o n ' m e t h o d i n s t r u c t i o n
* - ' cache o f f ' m e t h o d i n s t r u c t i o n
* - ' cache f l u s h ' m e t h o d i n s t r u c t i o n
*
* We m a t c h a n e n t r y u s i n g : ( ( r e a l _ i d ^ m a t c h ) & m a s k ) = = 0
*
* Writethrough c a c h e s g e n e r a l l y o n l y n e e d ' o n ' a n d ' o f f '
* methods. W r i t e b a c k c a c h e s _ m u s t _ h a v e t h e f l u s h m e t h o d
* defined.
* /
2009-07-24 12:32:52 +01:00
.align 2
2005-04-16 15:20:36 -07:00
.type proc_ t y p e s ,#o b j e c t
proc_types :
.word 0x41560600 @ ARM6/610
.word 0xffffffe0
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m 6 _ m m u _ c a c h e _ o f f @ works, but slow
W( b ) _ _ a r m 6 _ m m u _ c a c h e _ o f f
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2006-03-24 09:53:18 +00:00
@ b __arm6_mmu_cache_on @ untested
@ b __arm6_mmu_cache_off
@ b __armv3_mmu_cache_flush
2005-04-16 15:20:36 -07:00
.word 0x00000000 @ old ARM ID
.word 0x0000f000
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
.word 0x41007000 @ ARM7/710
.word 0xfff8fe00
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m 7 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m 7 _ m m u _ c a c h e _ o f f
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
.word 0x41807200 @ ARM720T (writethrough)
.word 0xffffff00
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
2006-03-27 10:21:34 +01:00
.word 0x41007400 @ ARM74x
.word 0xff00ff00
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v3 _ m p u _ c a c h e _ o n
W( b ) _ _ a r m v3 _ m p u _ c a c h e _ o f f
W( b ) _ _ a r m v3 _ m p u _ c a c h e _ f l u s h
2006-03-27 10:21:34 +01:00
.word 0x41009400 @ ARM94x
.word 0xff00ff00
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m p u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m p u _ c a c h e _ o f f
W( b ) _ _ a r m v4 _ m p u _ c a c h e _ f l u s h
2006-03-27 10:21:34 +01:00
2011-04-01 15:41:26 +01:00
.word 0x41069260 @ ARM926EJ-S (v5TEJ)
.word 0xff0ffff0
2011-06-09 05:05:27 +01:00
W( b ) _ _ a r m 9 2 6 e j s _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v5 t e j _ m m u _ c a c h e _ f l u s h
2006-03-27 10:21:34 +01:00
2005-04-16 15:20:36 -07:00
.word 0x00007000 @ ARM7 IDs
.word 0x0000f000
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
@ Everything from here on will be the new ID system.
.word 0x4401a100 @ sa110 / sa1100
.word 0xffffffe0
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ f l u s h
2005-04-16 15:20:36 -07:00
.word 0x6901b110 @ sa1110
.word 0xfffffff0
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ f l u s h
2005-04-16 15:20:36 -07:00
2010-03-12 05:47:55 -05:00
.word 0x56056900
.word 0xffffff00 @ PXA9xx
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ f l u s h
2009-01-20 14:15:18 +08:00
.word 0x56158000 @ PXA168
.word 0xfffff000
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v5 t e j _ m m u _ c a c h e _ f l u s h
2009-01-20 14:15:18 +08:00
2008-06-03 23:06:21 +02:00
.word 0x56050000 @ Feroceon
.word 0xff0f0000
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v5 t e j _ m m u _ c a c h e _ f l u s h
2007-10-31 15:31:48 -04:00
2009-06-16 20:05:57 +09:00
# ifdef C O N F I G _ C P U _ F E R O C E O N _ O L D _ I D
/* this conflicts with the standard ARMv5TE entry */
.long 0x41009260 @ Old Feroceon
.long 0xff00fff0
b _ _ a r m v4 _ m m u _ c a c h e _ o n
b _ _ a r m v4 _ m m u _ c a c h e _ o f f
b _ _ a r m v5 t e j _ m m u _ c a c h e _ f l u s h
# endif
2009-03-25 13:10:01 +02:00
.word 0x66015261 @ FA526
.word 0xff01fff1
2009-07-24 12:32:58 +01:00
W( b ) _ _ f a52 6 _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ f a52 6 _ c a c h e _ f l u s h
2009-03-25 13:10:01 +02:00
2005-04-16 15:20:36 -07:00
@ These match on the architecture ID
.word 0x00020000 @ ARMv4T
.word 0x000f0000
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ f l u s h
2005-04-16 15:20:36 -07:00
.word 0x00050000 @ ARMv5TE
.word 0x000f0000
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ f l u s h
2005-04-16 15:20:36 -07:00
.word 0x00060000 @ ARMv5TEJ
.word 0x000f0000
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
2010-03-15 15:14:50 +01:00
W( b ) _ _ a r m v5 t e j _ m m u _ c a c h e _ f l u s h
2005-04-16 15:20:36 -07:00
2006-06-18 16:21:50 +01:00
.word 0x0007b000 @ ARMv6
2007-06-01 17:14:53 +01:00
.word 0x000ff000
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v4 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v6 _ m m u _ c a c h e _ f l u s h
2005-04-16 15:20:36 -07:00
2007-06-01 17:14:53 +01:00
.word 0x000f0000 @ new CPU Id
.word 0x000f0000
2009-07-24 12:32:58 +01:00
W( b ) _ _ a r m v7 _ m m u _ c a c h e _ o n
W( b ) _ _ a r m v7 _ m m u _ c a c h e _ o f f
W( b ) _ _ a r m v7 _ m m u _ c a c h e _ f l u s h
2007-06-01 17:14:53 +01:00
2005-04-16 15:20:36 -07:00
.word 0 @ unrecognised type
.word 0
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
mov p c , l r
2009-07-24 12:32:58 +01:00
THUMB( n o p )
2005-04-16 15:20:36 -07:00
.size proc_ t y p e s , . - p r o c _ t y p e s
2011-06-14 14:20:44 +01:00
/ *
* If y o u g e t a " n o n - c o n s t a n t e x p r e s s i o n i n " . i f " s t a t e m e n t "
* error f r o m t h e a s s e m b l e r o n t h i s l i n e , c h e c k t h a t y o u h a v e
* not a c c i d e n t a l l y w r i t t e n a " b " i n s t r u c t i o n w h e r e y o u s h o u l d
* have w r i t t e n W ( b ) .
* /
.if ( . - proc_ t y p e s ) % P R O C _ E N T R Y _ S I Z E ! = 0
.error " The s i z e o f o n e o r m o r e p r o c _ t y p e s e n t r i e s i s w r o n g . "
.endif
2005-04-16 15:20:36 -07:00
/ *
* Turn o f f t h e C a c h e a n d M M U . A R M v3 d o e s n o t s u p p o r t
* reading t h e c o n t r o l r e g i s t e r , b u t A R M v4 d o e s .
*
2010-01-26 22:08:09 +01:00
* On e x i t ,
* r0 , r1 , r2 , r3 , r9 , r12 c o r r u p t e d
* This r o u t i n e m u s t p r e s e r v e :
2011-02-21 07:06:45 +01:00
* r4 , r7 , r8
2005-04-16 15:20:36 -07:00
* /
.align 5
cache_off : mov r3 , #12 @ cache_off function
b c a l l _ c a c h e _ f n
2006-03-27 10:21:34 +01:00
__armv4_mpu_cache_off :
mrc p15 , 0 , r0 , c1 , c0
bic r0 , r0 , #0x000d
mcr p15 , 0 , r0 , c1 , c0 @ turn MPU and cache off
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c10 , 4 @ drain write buffer
mcr p15 , 0 , r0 , c7 , c6 , 0 @ flush D-Cache
mcr p15 , 0 , r0 , c7 , c5 , 0 @ flush I-Cache
mov p c , l r
__armv3_mpu_cache_off :
mrc p15 , 0 , r0 , c1 , c0
bic r0 , r0 , #0x000d
mcr p15 , 0 , r0 , c1 , c0 , 0 @ turn MPU and cache off
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c0 , 0 @ invalidate whole cache v3
mov p c , l r
2006-03-24 09:53:18 +00:00
__armv4_mmu_cache_off :
2009-07-24 12:35:06 +01:00
# ifdef C O N F I G _ M M U
2005-04-16 15:20:36 -07:00
mrc p15 , 0 , r0 , c1 , c0
bic r0 , r0 , #0x000d
mcr p15 , 0 , r0 , c1 , c0 @ turn MMU and cache off
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c7 @ invalidate whole cache v4
mcr p15 , 0 , r0 , c8 , c7 @ invalidate whole TLB v4
2009-07-24 12:35:06 +01:00
# endif
2005-04-16 15:20:36 -07:00
mov p c , l r
2007-06-01 17:14:53 +01:00
__armv7_mmu_cache_off :
mrc p15 , 0 , r0 , c1 , c0
2009-07-24 12:35:06 +01:00
# ifdef C O N F I G _ M M U
2007-06-01 17:14:53 +01:00
bic r0 , r0 , #0x000d
2009-07-24 12:35:06 +01:00
# else
bic r0 , r0 , #0x000c
# endif
2007-06-01 17:14:53 +01:00
mcr p15 , 0 , r0 , c1 , c0 @ turn MMU and cache off
mov r12 , l r
bl _ _ a r m v7 _ m m u _ c a c h e _ f l u s h
mov r0 , #0
2009-07-24 12:35:06 +01:00
# ifdef C O N F I G _ M M U
2007-06-01 17:14:53 +01:00
mcr p15 , 0 , r0 , c8 , c7 , 0 @ invalidate whole TLB
2009-07-24 12:35:06 +01:00
# endif
2008-11-06 13:23:07 +00:00
mcr p15 , 0 , r0 , c7 , c5 , 6 @ invalidate BTC
mcr p15 , 0 , r0 , c7 , c10 , 4 @ DSB
mcr p15 , 0 , r0 , c7 , c5 , 4 @ ISB
2007-06-01 17:14:53 +01:00
mov p c , r12
2006-03-24 09:53:18 +00:00
__arm6_mmu_cache_off :
2005-04-16 15:20:36 -07:00
mov r0 , #0x00000030 @ ARM6 control reg.
2006-03-24 09:53:18 +00:00
b _ _ a r m v3 _ m m u _ c a c h e _ o f f
2005-04-16 15:20:36 -07:00
2006-03-24 09:53:18 +00:00
__arm7_mmu_cache_off :
2005-04-16 15:20:36 -07:00
mov r0 , #0x00000070 @ ARM7 control reg.
2006-03-24 09:53:18 +00:00
b _ _ a r m v3 _ m m u _ c a c h e _ o f f
2005-04-16 15:20:36 -07:00
2006-03-24 09:53:18 +00:00
__armv3_mmu_cache_off :
2005-04-16 15:20:36 -07:00
mcr p15 , 0 , r0 , c1 , c0 , 0 @ turn MMU and cache off
mov r0 , #0
mcr p15 , 0 , r0 , c7 , c0 , 0 @ invalidate whole cache v3
mcr p15 , 0 , r0 , c5 , c0 , 0 @ invalidate whole TLB v3
mov p c , l r
/ *
* Clean a n d f l u s h t h e c a c h e t o m a i n t a i n c o n s i s t e n c y .
*
* On e x i t ,
2010-01-26 22:08:09 +01:00
* r1 , r2 , r3 , r9 , r10 , r11 , r12 c o r r u p t e d
2005-04-16 15:20:36 -07:00
* This r o u t i n e m u s t p r e s e r v e :
2011-02-21 07:06:45 +01:00
* r4 , r6 , r7 , r8
2005-04-16 15:20:36 -07:00
* /
.align 5
cache_clean_flush :
mov r3 , #16
b c a l l _ c a c h e _ f n
2006-03-27 10:21:34 +01:00
__armv4_mpu_cache_flush :
mov r2 , #1
mov r3 , #0
mcr p15 , 0 , i p , c7 , c6 , 0 @ invalidate D cache
mov r1 , #7 < < 5 @ 8 segments
1 : orr r3 , r1 , #63 < < 2 6 @ 64 entries
2 : mcr p15 , 0 , r3 , c7 , c14 , 2 @ clean & invalidate D index
subs r3 , r3 , #1 < < 2 6
bcs 2 b @ entries 63 to 0
subs r1 , r1 , #1 < < 5
bcs 1 b @ segments 7 to 0
teq r2 , #0
mcrne p15 , 0 , i p , c7 , c5 , 0 @ invalidate I cache
mcr p15 , 0 , i p , c7 , c10 , 4 @ drain WB
mov p c , l r
2009-03-25 13:10:01 +02:00
__fa526_cache_flush :
mov r1 , #0
mcr p15 , 0 , r1 , c7 , c14 , 0 @ clean and invalidate D cache
mcr p15 , 0 , r1 , c7 , c5 , 0 @ flush I cache
mcr p15 , 0 , r1 , c7 , c10 , 4 @ drain WB
mov p c , l r
2006-03-27 10:21:34 +01:00
2006-03-24 09:53:18 +00:00
__armv6_mmu_cache_flush :
2005-04-16 15:20:36 -07:00
mov r1 , #0
mcr p15 , 0 , r1 , c7 , c14 , 0 @ clean+invalidate D
mcr p15 , 0 , r1 , c7 , c5 , 0 @ invalidate I+BTB
mcr p15 , 0 , r1 , c7 , c15 , 0 @ clean+invalidate unified
mcr p15 , 0 , r1 , c7 , c10 , 4 @ drain WB
mov p c , l r
2007-06-01 17:14:53 +01:00
__armv7_mmu_cache_flush :
mrc p15 , 0 , r10 , c0 , c1 , 5 @ read ID_MMFR1
tst r10 , #0xf < < 1 6 @ hierarchical cache (ARMv7)
mov r10 , #0
2008-11-06 13:23:07 +00:00
beq h i e r a r c h i c a l
2007-06-01 17:14:53 +01:00
mcr p15 , 0 , r10 , c7 , c14 , 0 @ clean+invalidate D
b i f l u s h
hierarchical :
2008-11-06 13:23:07 +00:00
mcr p15 , 0 , r10 , c7 , c10 , 5 @ DMB
2009-07-24 12:32:58 +01:00
stmfd s p ! , { r0 - r7 , r9 - r11 }
2007-06-01 17:14:53 +01:00
mrc p15 , 1 , r0 , c0 , c0 , 1 @ read clidr
ands r3 , r0 , #0x7000000 @ extract loc from clidr
mov r3 , r3 , l s r #23 @ left align loc bit field
beq f i n i s h e d @ if loc is 0, then no need to clean
mov r10 , #0 @ start clean at cache level 0
loop1 :
add r2 , r10 , r10 , l s r #1 @ work out 3x current cache level
mov r1 , r0 , l s r r2 @ extract cache type bits from clidr
and r1 , r1 , #7 @ mask of the bits for current cache only
cmp r1 , #2 @ see what cache we have at this level
blt s k i p @ skip if no cache, or just i-cache
mcr p15 , 2 , r10 , c0 , c0 , 0 @ select current cache level in cssr
mcr p15 , 0 , r10 , c7 , c5 , 4 @ isb to sych the new cssr&csidr
mrc p15 , 1 , r1 , c0 , c0 , 0 @ read the new csidr
and r2 , r1 , #7 @ extract the length of the cache lines
add r2 , r2 , #4 @ add 4 (line length offset)
ldr r4 , =0x3ff
ands r4 , r4 , r1 , l s r #3 @ find maximum number on the way size
2008-10-03 11:09:10 +01:00
clz r5 , r4 @ find bit position of way size increment
2007-06-01 17:14:53 +01:00
ldr r7 , =0x7fff
ands r7 , r7 , r1 , l s r #13 @ extract max number of the index size
loop2 :
mov r9 , r4 @ create working copy of max way size
loop3 :
2009-07-24 12:32:58 +01:00
ARM( o r r r11 , r10 , r9 , l s l r5 ) @ factor way and cache number into r11
ARM( o r r r11 , r11 , r7 , l s l r2 ) @ factor index number into r11
THUMB( l s l r6 , r9 , r5 )
THUMB( o r r r11 , r10 , r6 ) @ factor way and cache number into r11
THUMB( l s l r6 , r7 , r2 )
THUMB( o r r r11 , r11 , r6 ) @ factor index number into r11
2007-06-01 17:14:53 +01:00
mcr p15 , 0 , r11 , c7 , c14 , 2 @ clean & invalidate by set/way
subs r9 , r9 , #1 @ decrement the way
bge l o o p3
subs r7 , r7 , #1 @ decrement the index
bge l o o p2
skip :
add r10 , r10 , #2 @ increment cache number
cmp r3 , r10
bgt l o o p1
finished :
2009-07-24 12:32:58 +01:00
ldmfd s p ! , { r0 - r7 , r9 - r11 }
2007-06-01 17:14:53 +01:00
mov r10 , #0 @ swith back to cache level 0
mcr p15 , 2 , r10 , c0 , c0 , 0 @ select current cache level in cssr
iflush :
2008-11-06 13:23:07 +00:00
mcr p15 , 0 , r10 , c7 , c10 , 4 @ DSB
2007-06-01 17:14:53 +01:00
mcr p15 , 0 , r10 , c7 , c5 , 0 @ invalidate I+BTB
2008-11-06 13:23:07 +00:00
mcr p15 , 0 , r10 , c7 , c10 , 4 @ DSB
mcr p15 , 0 , r10 , c7 , c5 , 4 @ ISB
2007-06-01 17:14:53 +01:00
mov p c , l r
2007-10-31 15:15:29 -04:00
__armv5tej_mmu_cache_flush :
1 : mrc p15 , 0 , r15 , c7 , c14 , 3 @ test,clean,invalidate D cache
bne 1 b
mcr p15 , 0 , r0 , c7 , c5 , 0 @ flush I cache
mcr p15 , 0 , r0 , c7 , c10 , 4 @ drain WB
mov p c , l r
2006-03-24 09:53:18 +00:00
__armv4_mmu_cache_flush :
2005-04-16 15:20:36 -07:00
mov r2 , #64 * 1 0 2 4 @ default: 32K dcache size (*2)
mov r11 , #32 @ default: 32 byte line size
mrc p15 , 0 , r3 , c0 , c0 , 1 @ read cache type
2010-02-25 23:56:38 +00:00
teq r3 , r9 @ cache ID register present?
2005-04-16 15:20:36 -07:00
beq n o _ c a c h e _ i d
mov r1 , r3 , l s r #18
and r1 , r1 , #7
mov r2 , #1024
mov r2 , r2 , l s l r1 @ base dcache size *2
tst r3 , #1 < < 1 4 @ test M bit
addne r2 , r2 , r2 , l s r #1 @ +1/2 size if M == 1
mov r3 , r3 , l s r #12
and r3 , r3 , #3
mov r11 , #8
mov r11 , r11 , l s l r3 @ cache line size in bytes
no_cache_id :
2009-07-24 12:32:58 +01:00
mov r1 , p c
bic r1 , r1 , #63 @ align to longest cache line
2005-04-16 15:20:36 -07:00
add r2 , r1 , r2
2009-07-24 12:32:58 +01:00
1 :
ARM( l d r r3 , [ r1 ] , r11 ) @ s/w flush D cache
THUMB( l d r r3 , [ r1 ] ) @ s/w flush D cache
THUMB( a d d r1 , r1 , r11 )
2005-04-16 15:20:36 -07:00
teq r1 , r2
bne 1 b
mcr p15 , 0 , r1 , c7 , c5 , 0 @ flush I cache
mcr p15 , 0 , r1 , c7 , c6 , 0 @ flush D cache
mcr p15 , 0 , r1 , c7 , c10 , 4 @ drain WB
mov p c , l r
2006-03-24 09:53:18 +00:00
__armv3_mmu_cache_flush :
2006-03-27 10:21:34 +01:00
__armv3_mpu_cache_flush :
2005-04-16 15:20:36 -07:00
mov r1 , #0
2010-01-26 22:18:09 +01:00
mcr p15 , 0 , r1 , c7 , c0 , 0 @ invalidate whole cache v3
2005-04-16 15:20:36 -07:00
mov p c , l r
/ *
* Various d e b u g g i n g r o u t i n e s f o r p r i n t i n g h e x c h a r a c t e r s a n d
* memory, w h i c h a g a i n m u s t b e r e l o c a t a b l e .
* /
# ifdef D E B U G
2009-07-24 12:32:52 +01:00
.align 2
2005-04-16 15:20:36 -07:00
.type phexbuf,#o b j e c t
phexbuf : .space 12
.size phexbuf, . - p h e x b u f
2010-01-26 22:22:20 +01:00
@ phex corrupts {r0, r1, r2, r3}
2005-04-16 15:20:36 -07:00
phex : adr r3 , p h e x b u f
mov r2 , #0
strb r2 , [ r3 , r1 ]
1 : subs r1 , r1 , #1
movmi r0 , r3
bmi p u t s
and r2 , r0 , #15
mov r0 , r0 , l s r #4
cmp r2 , #10
addge r2 , r2 , #7
add r2 , r2 , #' 0 '
strb r2 , [ r3 , r1 ]
b 1 b
2010-01-26 22:22:20 +01:00
@ puts corrupts {r0, r1, r2, r3}
2010-02-01 23:26:53 +01:00
puts : loadsp r3 , r1
2005-04-16 15:20:36 -07:00
1 : ldrb r2 , [ r0 ] , #1
teq r2 , #0
moveq p c , l r
2005-05-03 12:18:46 +01:00
2 : writeb r2 , r3
2005-04-16 15:20:36 -07:00
mov r1 , #0x00020000
3 : subs r1 , r1 , #1
bne 3 b
teq r2 , #' \n '
moveq r2 , #' \r '
beq 2 b
teq r0 , #0
bne 1 b
mov p c , l r
2010-01-26 22:22:20 +01:00
@ putc corrupts {r0, r1, r2, r3}
2005-04-16 15:20:36 -07:00
putc :
mov r2 , r0
mov r0 , #0
2010-02-01 23:26:53 +01:00
loadsp r3 , r1
2005-04-16 15:20:36 -07:00
b 2 b
2010-01-26 22:22:20 +01:00
@ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr}
2005-04-16 15:20:36 -07:00
memdump : mov r12 , r0
mov r10 , l r
mov r11 , #0
2 : mov r0 , r11 , l s l #2
add r0 , r0 , r12
mov r1 , #8
bl p h e x
mov r0 , #' : '
bl p u t c
1 : mov r0 , #' '
bl p u t c
ldr r0 , [ r12 , r11 , l s l #2 ]
mov r1 , #8
bl p h e x
and r0 , r11 , #7
teq r0 , #3
moveq r0 , #' '
bleq p u t c
and r0 , r11 , #7
add r11 , r11 , #1
teq r0 , #7
bne 1 b
mov r0 , #' \n '
bl p u t c
cmp r11 , #64
blt 2 b
mov p c , r10
# endif
2007-06-22 14:27:50 +01:00
.ltorg
2011-04-27 16:15:11 -04:00
reloc_code_end :
2005-04-16 15:20:36 -07:00
.align
2010-11-22 12:00:59 +00:00
.section " .stack " , " aw" , % n o b i t s
2011-04-27 14:54:39 -04:00
.L_user_stack : .space 4096
.L_user_stack_end :