2019-05-29 17:12:41 +03:00
/* SPDX-License-Identifier: GPL-2.0-only */
2011-11-01 03:42:28 +04:00
/ *
* Early k e r n e l s t a r t u p c o d e f o r H e x a g o n
*
2013-03-29 05:45:40 +04:00
* Copyright ( c ) 2 0 1 0 - 2 0 1 3 , T h e L i n u x F o u n d a t i o n . A l l r i g h t s r e s e r v e d .
2011-11-01 03:42:28 +04:00
* /
# 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 m - o f f s e t s . h >
# include < a s m / m e m - l a y o u t . h >
# include < a s m / v m _ m m u . h >
# include < a s m / p a g e . h >
2012-12-01 00:53:56 +04:00
# include < a s m / h e x a g o n _ v m . h >
# define S E G T A B L E _ E N T R I E S #0x0e0
2011-11-01 03:42:28 +04:00
_ _ INIT
ENTRY( s t e x t )
/ *
* VMM w i l l a l r e a d y h a v e s e t u p t r u e v e c t o r p a g e , M M U , e t c .
* To s e t u p i n i t i a l k e r n e l i d e n t i t y m a p , w e h a v e t o p a s s
* the V M M a p o i n t e r t o s o m e c a n o n i c a l p a g e t a b l e s . I n
* this i m p l e m e n t a t i o n , w e ' r e a s s u m i n g t h a t w e ' v e g o t
* them p r e c o m p i l e d . G e n e r a t e v a l u e i n R 2 4 , a s w e ' l l n e e d
* it a g a i n s h o r t l y .
* /
r2 4 . L = #L O ( s w a p p e r _ p g _ d i r )
r2 4 . H = #H I ( s w a p p e r _ p g _ d i r )
/ *
* Symbol i s k e r n e l s e g m e n t a d d r e s s , b u t w e n e e d
* the l o g i c a l / p h y s i c a l a d d r e s s .
* /
2013-03-23 01:05:40 +04:00
r2 5 = p c ;
r2 . h = #0xffc0 ;
r2 . l = #0x0000 ;
r2 5 = a n d ( r2 ,r25 ) ; /* R25 holds PHYS_OFFSET now */
r1 . h = #H I ( P A G E _ O F F S E T ) ;
r1 . l = #L O ( P A G E _ O F F S E T ) ;
r2 4 = s u b ( r24 ,r1 ) ; /* swapper_pg_dir - PAGE_OFFSET */
r2 4 = a d d ( r24 ,r25 ) ; /* + PHYS_OFFSET */
2011-11-01 03:42:28 +04:00
2013-03-23 01:05:40 +04:00
r0 = r24 ; /* aka __pa(swapper_pg_dir) */
2011-11-01 03:42:28 +04:00
/ *
2013-03-23 01:05:40 +04:00
* Initialize p a g e d i r t o m a k e t h e v i r t u a l a n d p h y s i c a l
2011-11-01 03:42:28 +04:00
* addresses w h e r e t h e k e r n e l w a s l o a d e d b e i d e n t i c a l .
2013-03-23 01:05:40 +04:00
* Done i n 4 M B c h u n k s .
2011-11-01 03:42:28 +04:00
* /
# define P T E _ B I T S ( _ _ H V M _ P T E _ R | _ _ H V M _ P T E _ W | _ _ H V M _ P T E _ X \
| _ _ HEXAGON_ C _ W B _ L 2 < < 6 \
| _ _ HVM_ P D E _ S _ 4 M B )
2012-12-01 00:53:56 +04:00
/ *
* Get n u m b e r o f V A =PA e n t r i e s ; only really needed for jump
* to h y p e r s p a c e ; gets blown away immediately after
* /
{
r1 . l = #L O ( _ e n d ) ;
r2 . l = #L O ( s t e x t ) ;
r3 = #1 ;
}
{
r1 . h = #H I ( _ e n d ) ;
r2 . h = #H I ( s t e x t ) ;
r3 = a s l ( r3 , #22 ) ;
}
{
r1 = s u b ( r1 , r2 ) ;
r3 = a d d ( r3 , #- 1 ) ;
} /* r1 = _end - stext */
r1 = a d d ( r1 , r3 ) ; /* + (4M-1) */
r2 6 = l s r ( r1 , #22 ) ; /* / 4M = # of entries */
r1 = r25 ;
r2 . h = #0xffc0 ;
r2 . l = #0x0000 ; /* round back down to 4MB boundary */
r1 = a n d ( r1 ,r2 ) ;
2011-11-01 03:42:28 +04:00
r2 = l s r ( r1 , #22 ) / * 4 M B p a g e n u m b e r * /
r2 = a s l ( r2 , #2 ) / * t i m e s s i z e o f ( P T E ) ( 4 b y t e s ) * /
r0 = a d d ( r0 ,r2 ) / * r0 = a d d r e s s o f c o r r e c t P T E * /
r2 = #P T E _ B I T S
r1 = a d d ( r1 ,r2 ) / * r1 = 4 M B P T E f o r t h e f i r s t e n t r y * /
r2 . h = #0x0040
2012-12-01 00:53:56 +04:00
r2 . l = #0x0000 / * 4 M B i n c r e m e n t s * /
loop0 ( 1 f ,r26 ) ;
1 :
2011-11-01 03:42:28 +04:00
memw( r0 + + #4 ) = r1
2012-12-01 00:53:56 +04:00
{ r1 = a d d ( r1 , r2 ) ; } :endloop0
2011-11-01 03:42:28 +04:00
2012-12-01 00:53:56 +04:00
/* Also need to overwrite the initial 0xc0000000 entries */
/* PAGE_OFFSET >> (4MB shift - 4 bytes per entry shift) */
R1 . H = #H I ( P A G E _ O F F S E T > > ( 22 - 2 ) )
R1 . L = #L O ( P A G E _ O F F S E T > > ( 22 - 2 ) )
r0 = a d d ( r1 , r24 ) ; /* advance to 0xc0000000 entry */
r1 = r25 ;
r2 . h = #0xffc0 ;
r2 . l = #0x0000 ; /* round back down to 4MB boundary */
r1 = a n d ( r1 ,r2 ) ; /* for huge page */
r2 = #P T E _ B I T S
r1 = a d d ( r1 ,r2 ) ;
r2 . h = #0x0040
r2 . l = #0x0000 / * 4 M B i n c r e m e n t s * /
loop0 ( 1 f ,S E G T A B L E _ E N T R I E S ) ;
1 :
memw( r0 + + #4 ) = r1 ;
{ r1 = a d d ( r1 ,r2 ) ; } :endloop0
r0 = r24 ;
2011-11-01 03:42:28 +04:00
/ *
* The s u b r o u t i n e w r a p p e r a r o u n d t h e v i r t u a l i n s t r u c t i o n t o u c h e s
* no m e m o r y , s o w e s h o u l d b e a b l e t o u s e i t e v e n h e r e .
2012-12-01 00:53:56 +04:00
* Note t h a t i n t h i s v e r s i o n , R 1 a n d R 2 g e t " c l o b b e r e d " ; see
* vm_ o p s . S
2011-11-01 03:42:28 +04:00
* /
2012-12-01 00:53:56 +04:00
r1 = #V M _ T R A N S _ T Y P E _ T A B L E
2011-11-01 03:42:28 +04:00
call _ _ v m n e w m a p ;
/* Jump into virtual address range. */
r3 1 . h = #h i ( _ _ h e a d _ s _ v a d d r _ t a r g e t )
r3 1 . l = #l o ( _ _ h e a d _ s _ v a d d r _ t a r g e t )
jumpr r31
/* Insert trippy space effects. */
__head_s_vaddr_target :
/ *
* Tear d o w n V A =PA t r a n s l a t i o n n o w t h a t w e a r e r u n n i n g
2012-12-01 00:53:56 +04:00
* in k e r n e l v i r t u a l s p a c e .
2011-11-01 03:42:28 +04:00
* /
r0 = #_ _ H V M _ P D E _ S _ I N V A L I D
2012-12-01 00:53:56 +04:00
r1 . h = #0xffc0 ;
r1 . l = #0x0000 ;
r2 = r25 ; /* phys_offset */
r2 = a n d ( r1 ,r2 ) ;
r1 . l = #l o ( s w a p p e r _ p g _ d i r )
r1 . h = #h i ( s w a p p e r _ p g _ d i r )
r2 = l s r ( r2 , #22 ) / * 4 M B p a g e n u m b e r * /
r2 = a s l ( r2 , #2 ) / * t i m e s s i z e o f ( P T E ) ( 4 b y t e s ) * /
r1 = a d d ( r1 ,r2 ) ;
loop0 ( 1 f ,r26 )
2011-11-01 03:42:28 +04:00
1 :
{
memw( R 1 + + #4 ) = R 0
} : endloop0
r0 = r24
2012-12-01 00:53:56 +04:00
r1 = #V M _ T R A N S _ T Y P E _ T A B L E
2011-11-01 03:42:28 +04:00
call _ _ v m n e w m a p
/* Go ahead and install the trap0 return so angel calls work */
r0 . h = #h i ( _ K _ p r o v i s i o n a l _ v e c )
r0 . l = #l o ( _ K _ p r o v i s i o n a l _ v e c )
call _ _ v m s e t v e c
/ *
* OK, a t t h i s p o i n t w e s h o u l d s t a r t t o b e m u c h m o r e c a r e f u l ,
* we' r e g o i n g t o e n t e r C c o d e a n d s t a r t t o u c h i n g m e m o r y
* in a l l s o r t s o f p l a c e s .
* This m e a n s :
* SGP n e e d s t o b e O K
* Need t o l o c k s h a r e d r e s o u r c e s
* A b u n c h o f o t h e r t h i n g s t h a t w i l l c a u s e
* all k i n d s o f p a i n f u l b u g s
* /
/ *
* Stack p o i n t e r s h o u l d b e p o i n t e d a t t h e i n i t t a s k ' s
* thread s t a c k , w h i c h s h o u l d h a v e b e e n d e c l a r e d i n a r c h / i n i t _ t a s k . c .
* So u h h h h h . . .
* It' s a c c e s s i b l e v i a t h e i n i t _ t h r e a d _ u n i o n , w h i c h i s a u n i o n
* of a t h r e a d _ i n f o s t r u c t a n d a s t a c k ; of course, the top
* of t h e s t a c k i s n o t f o r y o u . T h e e n d o f t h e s t a c k
* is s i m p l y i n i t _ t h r e a d _ u n i o n + T H R E A D _ S I Z E .
* /
{ r2 9 . H = #H I ( i n i t _ t h r e a d _ u n i o n ) ; r 0 . H = #H I ( _ T H R E A D _ S I Z E ) ; }
{ r2 9 . L = #L O ( i n i t _ t h r e a d _ u n i o n ) ; r 0 . L = #L O ( _ T H R E A D _ S I Z E ) ; }
/* initialize the register used to point to current_thread_info */
/* Fixme: THREADINFO_REG can't be R2 because of that memset thing. */
{ r2 9 = a d d ( r29 ,r0 ) ; THREADINFO_REG = r29; }
/* Hack: zero bss; */
{ r0 . L = #L O ( _ _ b s s _ s t a r t ) ; r 1 = #0 ; r2.l = #LO(__bss_stop); }
{ r0 . H = #H I ( _ _ b s s _ s t a r t ) ; r 2 . h = #H I ( _ _ b s s _ s t o p ) ; }
r2 = s u b ( r2 ,r0 ) ;
call m e m s e t ;
2012-12-01 00:53:56 +04:00
/* Set PHYS_OFFSET; should be in R25 */
2013-03-23 01:05:40 +04:00
# ifdef C O N F I G _ H E X A G O N _ P H Y S _ O F F S E T
r0 . l = #L O ( _ _ p h y s _ o f f s e t ) ;
r0 . h = #H I ( _ _ p h y s _ o f f s e t ) ;
memw( r0 ) = r25 ;
# endif
2011-11-01 03:42:28 +04:00
/* Time to make the doughnuts. */
call s t a r t _ k e r n e l
/ *
* Should n o t r e a c h h e r e .
* /
1 :
jump 1 b
.p2align PAGE_SHIFT
ENTRY( e x t e r n a l _ c m d l i n e _ b u f f e r )
.fill _ PAGE_ S I Z E ,1 ,0
.data
.p2align PAGE_SHIFT
ENTRY( e m p t y _ z e r o _ p a g e )
.fill _ PAGE_ S I Z E ,1 ,0