2006-03-27 14:58:25 +01: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 >
2017-10-16 12:54:05 +01:00
# include < l i n u x / e r r n o . h >
2006-03-27 14:58:25 +01:00
# 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 15:11:14 +01:00
# include < a s m / a s m - o f f s e t s . h >
2013-02-22 17:48:56 +00:00
# include < a s m / m e m o r y . h >
2012-03-28 18:30:01 +01:00
# include < a s m / c p15 . h >
2006-04-24 09:45:35 +01:00
# include < a s m / t h r e a d _ i n f o . h >
2010-05-21 18:06:41 +01:00
# include < a s m / v7 m . h >
2013-02-22 17:48:56 +00:00
# include < a s m / m p u . h >
2013-04-18 18:37:24 +01:00
# include < a s m / p a g e . h >
2006-03-27 14:58:25 +01: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 15:53:30 +01:00
2009-10-02 16:32:46 -04:00
_ _ HEAD
2011-12-09 20:52:10 +01: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 14:58:25 +01:00
ENTRY( s t e x t )
2011-07-13 15:53:30 +01:00
2015-04-21 14:17:25 +01:00
THUMB( b a d r r9 , 1 f ) @ Kernel is always entered in ARM.
2011-07-13 15:53:30 +01:00
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 20:52:10 +01:00
# endif
2011-07-13 15:53:30 +01:00
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
2006-03-27 14:58:25 +01:00
@ and irqs disabled
2010-05-21 18:06:41 +01: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 14:58:25 +01:00
mrc p15 , 0 , r9 , c0 , c0 @ get processor id
2010-05-21 18:06:41 +01: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 17:36:37 +09:00
# endif
2006-03-27 14:58:25 +01: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 17:48:56 +00:00
# ifdef C O N F I G _ A R M _ M P U
/* Calculate the size of a region covering just the kernel */
2013-12-10 19:21:08 +00:00
ldr r5 , =PLAT_PHYS_OFFSET @ Region start: PHYS_OFFSET
2013-02-22 17:48:56 +00:00
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
2015-06-02 20:43:24 +01:00
2015-04-21 14:17:25 +01:00
badr l r , 1 f @ return (PIC) address
2015-04-19 20:28:53 +01:00
ldr r12 , [ r10 , #P R O C I N F O _ I N I T F U N C ]
add r12 , r12 , r10
ret r12
2015-06-02 20:43:24 +01:00
1 : bl _ _ a f t e r _ p r o c _ i n i t
b _ _ m m a p _ s w i t c h e d
2008-08-28 11:22:32 +01:00
ENDPROC( s t e x t )
2006-03-27 14:58:25 +01:00
2012-02-28 11:50:32 +00:00
# ifdef C O N F I G _ S M P
2013-07-31 11:37:17 +01:00
.text
2012-02-28 11:50:32 +00: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'
2015-06-02 20:43:24 +01:00
ldr r7 , _ _ s e c o n d a r y _ d a t a
2013-02-22 18:51:30 +00:00
# ifdef C O N F I G _ A R M _ M P U
/* Use MPU region info supplied by __cpu_up */
2017-10-16 12:54:05 +01:00
ldr r6 , [ r7 ] @ get secondary_data.mpu_rgn_info
bl _ _ s e c o n d a r y _ s e t u p _ m p u @ Initialize the MPU
2013-02-22 18:51:30 +00:00
# endif
2015-06-02 20:43:24 +01:00
badr l r , 1 f @ return (PIC) address
2015-04-19 20:28:53 +01:00
ldr r12 , [ r10 , #P R O C I N F O _ I N I T F U N C ]
add r12 , r12 , r10
ret r12
2015-06-02 20:43:24 +01:00
1 : bl _ _ a f t e r _ p r o c _ i n i t
2015-04-04 20:09:46 +01:00
ldr s p , [ r7 , #12 ] @ set up the stack pointer
2012-02-28 11:50:32 +00: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
2015-06-02 20:43:24 +01:00
ENDPROC( s e c o n d a r y _ s t a r t u p )
2012-02-28 11:50:32 +00:00
.type _ _ secondary_ d a t a , % o b j e c t
__secondary_data :
.long secondary_data
# endif / * C O N F I G _ S M P * /
2006-03-27 14:58:25 +01: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 17:36:37 +09:00
# ifdef C O N F I G _ C P U _ C P 1 5
2009-07-24 12:34:59 +01: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 10:34:39 +01: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 14:58:25 +01: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
# endif
mcr p15 , 0 , r0 , c1 , c0 , 0 @ write control reg
2016-08-30 17:31:22 +01:00
# elif d e f i n e d ( C O N F I G _ C P U _ V 7 M )
/* For V7M systems we want to modify the CCR similarly to the SCTLR */
# 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 , #V 7 M _ S C B _ C C R _ D 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 , #V 7 M _ S C B _ C C R _ B P
# 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 , #V 7 M _ S C B _ C C R _ I C
# endif
movw r3 , #: l o w e r 16 : ( B A S E A D D R _ V 7 M _ S C B + V 7 M _ S C B _ C C R )
movt r3 , #: u p p e r 16 : ( B A S E A D D R _ V 7 M _ S C B + V 7 M _ S C B _ C C R )
str r0 , [ r3 ]
# endif / * C O N F I G _ C P U _ C P 1 5 e l i f C O N F I G _ C P U _ V 7 M * /
2015-06-02 20:43:24 +01:00
ret l r
2008-08-28 11:22:32 +01:00
ENDPROC( _ _ a f t e r _ p r o c _ i n i t )
2006-04-24 09:45:35 +01:00
.ltorg
2006-03-27 14:58:25 +01:00
2013-02-22 17:48:56 +00:00
# ifdef C O N F I G _ A R M _ M P U
2017-10-16 12:57:48 +01:00
# ifndef C O N F I G _ C P U _ V 7 M
2013-02-22 17:48:56 +00:00
/* Set which MPU region should be programmed */
2017-10-16 12:57:48 +01:00
.macro set_region_nr tmp, r g n r , u n u s e d
2013-02-22 17:48:56 +00:00
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) */
2017-10-16 12:57:48 +01:00
.macro setup_region bar, a c r , s r , s i d e = M P U _ D A T A _ S I D E , u n u s e d
2013-02-22 17:48:56 +00:00
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
2017-10-16 12:57:48 +01:00
# else
.macro set_region_nr tmp, r g n r , b a s e
mov \ t m p , \ r g n r
str \ t m p , [ \ b a s e , #M P U _ R N R ]
.endm
.macro setup_region bar, a c r , s r , u n u s e d , b a s e
lsl \ a c r , \ a c r , #16
orr \ a c r , \ a c r , \ s r
str \ b a r , [ \ b a s e , #M P U _ R B A R ]
str \ a c r , [ \ b a s e , #M P U _ R A S R ]
.endm
2013-02-22 17:48:56 +00:00
2017-10-16 12:57:48 +01:00
# endif
2013-02-22 17:48:56 +00:00
/ *
* 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 18:37:24 +01: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 17:48:56 +00: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 */
2017-10-16 12:57:48 +01:00
M_ C L A S S ( m o v w r12 , #: l o w e r 16 : B A S E A D D R _ V 7 M _ S C B )
M_ C L A S S ( m o v t r12 , #: u p p e r 16 : B A S E A D D R _ V 7 M _ S C B )
AR_ C L A S S ( m r c p15 , 0 , r0 , c0 , c1 , 4 ) @ Read ID_MMFR0
M_ C L A S S ( l d r r0 , [ r12 , 0 x50 ] )
2013-02-22 17:48:56 +00:00
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
2017-10-16 12:54:05 +01:00
bxne l r
2013-02-22 17:48:56 +00:00
/ * 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 * /
2017-10-16 12:57:48 +01:00
AR_ C L A S S ( m r c p15 , 0 , r0 , c0 , c0 , 4 ) @ MPUIR
M_ C L A S S ( l d r r0 , [ r12 , #M P U _ T Y P E ] )
2013-02-22 17:48:56 +00:00
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
2017-10-16 12:54:05 +01:00
bxeq l r
2013-02-22 17:48:56 +00:00
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 */
2017-10-16 12:57:48 +01:00
set_ r e g i o n _ n r r0 , #M P U _ R A M _ R E G I O N , r 12
2013-02-22 17:48:56 +00:00
isb
/* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
2013-12-10 19:21:08 +00:00
ldr r0 , =PLAT_PHYS_OFFSET @ RAM starts at PHYS_OFFSET
2013-02-22 17:48:56 +00:00
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 )
2017-10-16 12:57:48 +01:00
setup_ r e g i o n r0 , r5 , r6 , M P U _ D A T A _ S I D E , r12 @ 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 , r12 @ PHYS_OFFSET, shared, enabled
2013-02-22 17:48:56 +00:00
1 : isb
/* First/background region */
2017-10-16 12:57:48 +01:00
set_ r e g i o n _ n r r0 , #M P U _ B G _ R E G I O N , r 12
2013-02-22 17:48:56 +00:00
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
2017-10-16 12:57:48 +01:00
setup_ r e g i o n r0 , r5 , r6 , M P U _ D A T A _ S I D E , r12 @ 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 r12 @ 0x0, BG region, enabled
2013-02-22 17:48:56 +00:00
2 : isb
2017-10-16 13:00:45 +01:00
# ifdef C O N F I G _ X I P _ K E R N E L
set_ r e g i o n _ n r r0 , #M P U _ R O M _ R E G I O N , r 12
isb
ldr r5 ,= ( M P U _ A P _ P L 1 R O _ P L 0 N A | M P U _ R G N _ N O R M A L )
ldr r0 , =CONFIG_XIP_PHYS_ADDR @ ROM start
ldr r6 , = ( _ e x i p r o m ) @ ROM end
sub r6 , r6 , r0 @ 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
setup_ r e g i o n r0 , r5 , r6 , M P U _ D A T A _ S I D E , r12 @ XIP_PHYS_ADDR, shared, 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 , r12 @ XIP_PHYS_ADDR, shared, enabled
3 : isb
# endif
2017-10-16 12:54:05 +01:00
/* Enable the MPU */
2017-10-16 12:57:48 +01:00
AR_ C L A S S ( m r c p15 , 0 , r0 , c1 , c0 , 0 ) @ Read SCTLR
AR_ C L A S S ( b i c 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 '
AR_ C L A S S ( o r r r0 , r0 , #C R _ M ) @ S e t S C T R L . M ( M P U o n )
AR_ C L A S S ( m c r p15 , 0 , r0 , c1 , c0 , 0 ) @ Enable MPU
M_ C L A S S ( l d r r0 , [ r12 , #M P U _ C T R L ] )
M_ C L A S S ( b i c r0 , #M P U _ C T R L _ P R I V D E F E N A )
M_ C L A S S ( o r r r0 , #M P U _ C T R L _ E N A B L E )
M_ C L A S S ( s t r r0 , [ r12 , #M P U _ C T R L ] )
2017-10-16 12:54:05 +01:00
isb
ret l r
ENDPROC( _ _ s e t u p _ m p u )
# ifdef C O N F I G _ S M P
/ *
* r6 : pointer a t m p u _ r g n _ i n f o
* /
ENTRY( _ _ s e c o n d a r y _ 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
/ * 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
ldr r4 , [ r6 , #M P U _ R N G _ I N F O _ U S E D ]
mov r5 , #M P U _ R N G _ S I Z E
add r3 , r6 , #M P U _ R N G _ I N F O _ R N G S
mla r3 , r4 , r5 , r3
1 :
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
sub r3 , r3 , #M P U _ R N G _ S I Z E
sub r4 , r4 , #1
set_ r e g i o n _ n r r0 , r4
2013-04-18 18:37:24 +01:00
isb
2017-10-16 12:54:05 +01:00
ldr r0 , [ r3 , #M P U _ R G N _ D R B A R ]
ldr r6 , [ r3 , #M P U _ R G N _ D R S R ]
ldr r5 , [ r3 , #M P U _ R G N _ D R A C R ]
setup_ r e g i o n r0 , r5 , r6 , M P U _ D A T A _ S I D E
beq 2 f
setup_ r e g i o n r0 , r5 , r6 , M P U _ I N S T R _ S I D E
2 : isb
mrc p15 , 0 , r0 , c0 , c0 , 4 @ Reevaluate the MPUIR
cmp r4 , #0
bgt 1 b
2013-04-18 18:37:24 +01:00
2013-02-22 17:48:56 +00:00
/* Enable the MPU */
mrc p15 , 0 , r0 , c1 , c0 , 0 @ Read SCTLR
2017-10-16 12:54:05 +01:00
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 '
2013-02-22 17:48:56 +00:00
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
2017-10-16 12:54:05 +01:00
2014-06-30 16:29:12 +01:00
ret l r
2017-10-16 12:54:05 +01:00
ENDPROC( _ _ s e c o n d a r y _ s e t u p _ m p u )
# endif / * C O N F I G _ S M P * /
# endif / * C O N F I G _ A R M _ M P U * /
2006-03-27 14:58:25 +01:00
# include " h e a d - c o m m o n . S "