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 - n o m m u . 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 - 2 0 0 6 H y o k S . C h o i
*
* 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 .
*
* Common k e r n e l s t a r t u p c o d e ( n o n - p a g e d M M )
*
* /
# 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 / p t r a c e . h >
2006-05-05 18:11:14 +04:00
# include < a s m / a s m - o f f s e t s . h >
2013-02-22 21:48:56 +04:00
# include < a s m / m e m o r y . h >
2012-03-28 21:30:01 +04:00
# include < a s m / c p15 . h >
2006-04-24 12:45:35 +04:00
# include < a s m / t h r e a d _ i n f o . h >
2010-05-21 21:06:41 +04:00
# include < a s m / v7 m . h >
2013-02-22 21:48:56 +04:00
# include < a s m / m p u . h >
2013-04-18 21:37:24 +04:00
# include < a s m / p a g e . h >
2006-03-27 17:58:25 +04:00
/ *
* 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 .
*
* 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 .
*
* /
2011-07-13 18:53:30 +04:00
2009-10-03 00:32:46 +04:00
_ _ HEAD
2011-12-09 23:52:10 +04:00
# ifdef C O N F I G _ C P U _ T H U M B O N L Y
.thumb
ENTRY( s t e x t )
# else
.arm
2006-03-27 17:58:25 +04:00
ENTRY( s t e x t )
2011-07-13 18:53:30 +04:00
THUMB( a d r r9 , B S Y M ( 1 f ) ) @ Kernel is always entered in ARM.
THUMB( b x r9 ) @ If this is a Thumb-2 kernel,
THUMB( . t h u m b ) @ switch to Thumb now.
THUMB( 1 : )
2011-12-09 23:52:10 +04:00
# endif
2011-07-13 18:53:30 +04:00
2009-07-24 15:32:54 +04: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
2006-03-27 17:58:25 +04:00
@ and irqs disabled
2010-05-21 21:06:41 +04:00
# if d e f i n e d ( C O N F I G _ C P U _ C P 1 5 )
2006-03-27 17:58:25 +04:00
mrc p15 , 0 , r9 , c0 , c0 @ get processor id
2010-05-21 21:06:41 +04:00
# elif d e f i n e d ( C O N F I G _ C P U _ V 7 M )
ldr r9 , =BASEADDR_V7M_SCB
ldr r9 , [ r9 , V 7 M _ S C B _ C P U I D ]
# else
ldr r9 , =CONFIG_PROCESSOR_ID
2006-09-26 12:36:37 +04:00
# endif
2006-03-27 17:58:25 +04: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)?
beq _ _ e r r o r _ p @ yes, error 'p'
2013-02-22 21:48:56 +04:00
# ifdef C O N F I G _ A R M _ M P U
/* Calculate the size of a region covering just the kernel */
ldr r5 , =PHYS_OFFSET @ Region start: PHYS_OFFSET
ldr r6 , = ( _ e n d ) @ Cover whole kernel
sub r6 , r6 , r5 @ Minimum size of region to map
clz r6 , r6 @ Region size must be 2^N...
rsb r6 , r6 , #31 @ ...so round up region size
lsl r6 , r6 , #M P U _ R S R _ S Z @ P u t s i z e i n r i g h t f i e l d
orr r6 , r6 , #( 1 < < M P U _ R S R _ E N ) @ Set region enabled bit
bl _ _ s e t u p _ m p u
# endif
2012-02-28 15:50:32 +04:00
ldr r13 , =__mmap_switched @ address to jump to after
@ initialising sctlr
adr l r , B S Y M ( 1 f ) @ return (PIC) address
2009-07-24 15:32:54 +04:00
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 )
2012-02-28 15:50:32 +04:00
1 : b _ _ a f t e r _ p r o c _ i n i t
2008-08-28 14:22:32 +04:00
ENDPROC( s t e x t )
2006-03-27 17:58:25 +04:00
2012-02-28 15:50:32 +04:00
# ifdef C O N F I G _ S M P
2013-07-31 14:37:17 +04:00
.text
2012-02-28 15:50:32 +04:00
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 .
* /
setmode P S R _ F _ B I T | P S R _ I _ B I T | S V C _ M O D E , r9
# ifndef C O N F I G _ C P U _ C P 1 5
ldr r9 , =CONFIG_PROCESSOR_ID
# else
mrc p15 , 0 , r9 , c0 , c0 @ get processor id
# endif
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?
beq _ _ e r r o r _ p @ yes, error 'p'
adr r4 , _ _ s e c o n d a r y _ d a t a
ldmia r4 , { r7 , r12 }
2013-02-22 22:51:30 +04:00
# ifdef C O N F I G _ A R M _ M P U
/* Use MPU region info supplied by __cpu_up */
ldr r6 , [ r7 ] @ get secondary_data.mpu_szr
bl _ _ s e t u p _ m p u @ Initialize the MPU
# endif
2012-02-28 15:50:32 +04:00
adr l r , B S Y M ( _ _ a f t e r _ p r o c _ i n i t ) @ 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 )
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 )
ENDPROC( s e c o n d a r y _ s t a r t u p )
ENTRY( _ _ s e c o n d a r y _ s w i t c h e d )
ldr s p , [ r7 , #8 ] @ set up the stack pointer
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
ENDPROC( _ _ s e c o n d a r y _ s w i t c h e d )
.type _ _ secondary_ d a t a , % o b j e c t
__secondary_data :
.long secondary_data
.long __secondary_switched
# endif / * C O N F I G _ S M P * /
2006-03-27 17:58:25 +04:00
/ *
* Set t h e C o n t r o l R e g i s t e r a n d R e a d t h e p r o c e s s I D .
* /
__after_proc_init :
2006-09-26 12:36:37 +04:00
# ifdef C O N F I G _ C P U _ C P 1 5
2009-07-24 15:34:59 +04:00
/ *
* CP1 5 s y s t e m c o n t r o l r e g i s t e r v a l u e r e t u r n e d i n r0 f r o m
* the C P U i n i t f u n c t i o n .
* /
2012-12-04 13:34:39 +04:00
# if d e f i n e d ( C O N F I G _ A L I G N M E N T _ T R A P ) & & _ _ L I N U X _ A R M _ A R C H _ _ < 6
2006-03-27 17:58:25 +04:00
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
2006-09-28 16:46:34 +04:00
# endif
# ifdef C O N F I G _ C P U _ H I G H _ V E C T O R
orr r0 , r0 , #C R _ V
# else
bic r0 , r0 , #C R _ V
2006-03-27 17:58:25 +04:00
# endif
mcr p15 , 0 , r0 , c1 , c0 , 0 @ write control reg
2006-09-26 12:36:37 +04:00
# endif / * C O N F I G _ C P U _ C P 1 5 * /
2012-02-28 15:50:32 +04:00
mov p c , r13
2008-08-28 14:22:32 +04:00
ENDPROC( _ _ a f t e r _ p r o c _ i n i t )
2006-04-24 12:45:35 +04:00
.ltorg
2006-03-27 17:58:25 +04:00
2013-02-22 21:48:56 +04:00
# ifdef C O N F I G _ A R M _ M P U
/* Set which MPU region should be programmed */
.macro set_region_nr tmp, r g n r
mov \ t m p , \ r g n r @ Use static region numbers
mcr p15 , 0 , \ t m p , c6 , c2 , 0 @ Write RGNR
.endm
/* Setup a single MPU region, either D or I side (D-side for unified) */
.macro setup_region bar, a c r , s r , s i d e = M P U _ D A T A _ S I D E
mcr p15 , 0 , \ b a r , c6 , c1 , ( 0 + \ s i d e ) @ I/DRBAR
mcr p15 , 0 , \ a c r , c6 , c1 , ( 4 + \ s i d e ) @ I/DRACR
mcr p15 , 0 , \ s r , c6 , c1 , ( 2 + \ s i d e ) @ I/DRSR
.endm
/ *
* Setup t h e M P U a n d i n i t i a l M P U R e g i o n s . W e c r e a t e t h e f o l l o w i n g r e g i o n s :
* Region 0 : U s e t h i s f o r p r o b i n g t h e M P U d e t a i l s , s o l e a v e d i s a b l e d .
* Region 1 : B a c k g r o u n d r e g i o n - c o v e r s t h e w h o l e o f R A M a s s t r o n g l y o r d e r e d
* Region 2 : N o r m a l , S h a r e d , c a c h e a b l e f o r R A M . F r o m P H Y S _ O F F S E T , s i z e f r o m r6
2013-04-18 21:37:24 +04:00
* Region 3 : N o r m a l , s h a r e d , i n a c c e s s i b l e f r o m P L 0 t o p r o t e c t t h e v e c t o r s p a g e
2013-02-22 21:48:56 +04:00
*
* r6 : Value t o b e w r i t t e n t o D R S R ( a n d I R S R i f r e q u i r e d ) f o r M P U _ R A M _ R E G I O N
* /
ENTRY( _ _ s e t u p _ m p u )
/* Probe for v7 PMSA compliance */
mrc p15 , 0 , r0 , c0 , c1 , 4 @ Read ID_MMFR0
and r0 , r0 , #( M M F R 0 _ P M S A ) @ PMSA field
teq r0 , #( M M F R 0 _ P M S A v7 ) @ PMSA v7
bne _ _ e r r o r _ p @ Fail: ARM_MPU on NOT v7 PMSA
/ * Determine w h e t h e r t h e D / I - s i d e m e m o r y m a p i s u n i f i e d . W e s e t t h e
* flags h e r e a n d c o n t i n u e t o u s e t h e m f o r t h e r e s t o f t h i s f u n c t i o n * /
mrc p15 , 0 , r0 , c0 , c0 , 4 @ MPUIR
ands r5 , r0 , #M P U I R _ D R E G I O N _ S Z M A S K @ 0 s i z e d r e g i o n = > N o M P U
beq _ _ e r r o r _ p @ Fail: ARM_MPU and no MPU
tst r0 , #M P U I R _ n U @ M P U I R _ n U = 0 f o r u n i f i e d
/* Setup second region first to free up r6 */
set_ r e g i o n _ n r r0 , #M P U _ R A M _ R E G I O N
isb
/* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
ldr r0 , =PHYS_OFFSET @ RAM starts at PHYS_OFFSET
ldr r5 ,= ( M P U _ A P _ P L 1 R W _ P L 0 R W | M P U _ R G N _ N O R M A L )
setup_ r e g i o n r0 , r5 , r6 , M P U _ D A T A _ S I D E @ PHYS_OFFSET, shared, enabled
beq 1 f @ Memory-map not unified
setup_ r e g i o n r0 , r5 , r6 , M P U _ I N S T R _ S I D E @ PHYS_OFFSET, shared, enabled
1 : isb
/* First/background region */
set_ r e g i o n _ n r r0 , #M P U _ B G _ R E G I O N
isb
/* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */
mov r0 , #0 @ BG region starts at 0x0
ldr r5 ,= ( M P U _ A C R _ X N | M P U _ R G N _ S T R O N G L Y _ O R D E R E D | M P U _ A P _ P L 1 R W _ P L 0 N A )
mov r6 , #M P U _ R S R _ A L L _ M E M @ 4 G B r e g i o n , e n a b l e d
setup_ r e g i o n r0 , r5 , r6 , M P U _ D A T A _ S I D E @ 0x0, BG region, enabled
beq 2 f @ Memory-map not unified
setup_ r e g i o n r0 , r5 , r6 , M P U _ I N S T R _ S I D E @ 0x0, BG region, enabled
2 : isb
2013-04-18 21:37:24 +04:00
/* Vectors region */
set_ r e g i o n _ n r r0 , #M P U _ V E C T O R S _ R E G I O N
isb
/* Shared, inaccessible to PL0, rw PL1 */
mov r0 , #C O N F I G _ V E C T O R S _ B A S E @ C o v e r f r o m V E C T O R S _ B A S E
ldr r5 ,= ( M P U _ A P _ P L 1 R W _ P L 0 N A | M P U _ R G N _ N O R M A L )
/* Writing N to bits 5:1 (RSR_SZ) --> region size 2^N+1 */
mov r6 , #( ( ( P A G E _ S H I F T - 1 ) < < M P U _ R S R _ S Z ) | 1 < < M P U _ R S R _ E N )
setup_ r e g i o n r0 , r5 , r6 , M P U _ D A T A _ S I D E @ VECTORS_BASE, PL0 NA, enabled
beq 3 f @ Memory-map not unified
setup_ r e g i o n r0 , r5 , r6 , M P U _ I N S T R _ S I D E @ VECTORS_BASE, PL0 NA, enabled
3 : isb
2013-02-22 21:48:56 +04:00
/* Enable the MPU */
mrc p15 , 0 , r0 , c1 , c0 , 0 @ Read SCTLR
bic r0 , r0 , #C R _ B R @ D i s a b l e t h e ' d e f a u l t m e m - m a p '
orr r0 , r0 , #C R _ M @ S e t S C T R L . M ( M P U o n )
mcr p15 , 0 , r0 , c1 , c0 , 0 @ Enable MPU
isb
mov p c ,l r
ENDPROC( _ _ s e t u p _ m p u )
# endif
2006-03-27 17:58:25 +04:00
# include " h e a d - c o m m o n . S "