2011-05-04 14:38:26 -04:00
/ *
* Copyright 2 0 1 1 T i l e r a C o r p o r a t i o n . A l l 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 i t 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
* as p u b l i s h e d 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 , v e r s i o n 2 .
*
* This p r o g r a m i s d i s t r i b u t e d i n t h e h o p e t h a t i t w i l l b e u s e f u l , b u t
* WITHOUT A N Y W A R R A N T Y ; without even the implied warranty of
* MERCHANTABILITY O R F I T N E S S F O R A P A R T I C U L A R P U R P O S E , G O O D T I T L E o r
* NON I N F R I N G E M E N T . S e e 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 f o r
* more d e t a i l s .
*
* TILE s t a r t u p c o d e .
* /
# 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 / p a g e . h >
# include < a s m / p g t a b l e . h >
# include < a s m / t h r e a d _ i n f o . h >
# include < a s m / p r o c e s s o r . h >
# include < a s m / a s m - o f f s e t s . h >
# include < h v / h y p e r v i s o r . h >
# include < a r c h / c h i p . h >
# include < a r c h / s p r _ d e f . h >
2013-08-07 11:55:35 -04:00
/* Extract two 32-bit bit values that were read into one register. */
# ifdef _ _ B I G _ E N D I A N _ _
# define G E T _ F I R S T _ I N T ( r d , r s ) s h r s i r d , r s , 3 2
# define G E T _ S E C O N D _ I N T ( r d , r s ) a d d x i r d , r s , 0
# else
# define G E T _ F I R S T _ I N T ( r d , r s ) a d d x i r d , r s , 0
# define G E T _ S E C O N D _ I N T ( r d , r s ) s h r s i r d , r s , 3 2
# endif
2011-05-04 14:38:26 -04:00
/ *
* This m o d u l e c o n t a i n s t h e e n t r y c o d e f o r k e r n e l i m a g e s . I t p e r f o r m s t h e
* minimal s e t u p n e e d e d t o c a l l t h e g e n e r i c C r o u t i n e s .
* /
_ _ HEAD
ENTRY( _ s t a r t )
/* Notify the hypervisor of what version of the API we want */
{
2013-05-02 15:29:04 -04:00
# if K E R N E L _ P L = = 1 & & _ H V _ V E R S I O N = = 1 3
/* Support older hypervisors by asking for API version 12. */
movei r0 , _ H V _ V E R S I O N _ O L D _ H V _ I N I T
# else
movei r0 , _ H V _ V E R S I O N
# endif
2011-05-04 14:38:26 -04:00
movei r1 , T I L E _ C H I P
}
{
2013-05-02 15:29:04 -04:00
movei r2 , T I L E _ C H I P _ R E V
movei r3 , K E R N E L _ P L
2011-05-04 14:38:26 -04:00
}
2013-08-07 16:03:08 -04:00
jal _ h v _ i n i t
2011-05-04 14:38:26 -04:00
/* Get a reasonable default ASID in r0 */
{
move r0 , z e r o
2013-08-07 16:03:08 -04:00
jal _ h v _ i n q u i r e _ a s i d
2011-05-04 14:38:26 -04:00
}
/ *
* Install t h e d e f a u l t p a g e t a b l e . T h e r e l o c a t i o n r e q u i r e d t o
* statically d e f i n e t h e t a b l e i s a b i t t o o c o m p l e x , s o w e h a v e
* to p l u g i n t h e p o i n t e r f r o m t h e L 0 t o t h e L 1 t a b l e b y h a n d .
* We o n l y d o t h i s o n t h e f i r s t c p u t o b o o t , t h o u g h , s i n c e t h e
* other C P U s s h o u l d s e e a p r o p e r l y - c o n s t r u c t e d p a g e t a b l e .
* /
{
2013-08-07 11:55:35 -04:00
GET_ F I R S T _ I N T ( r2 , r0 ) / * A S I D f o r h v _ i n s t a l l _ c o n t e x t * /
2011-05-04 14:38:26 -04:00
moveli r4 , h w1 _ l a s t ( s w a p p e r _ p g p r o t - P A G E _ O F F S E T )
}
{
shl1 6 i n s l i r4 , r4 , h w0 ( s w a p p e r _ p g p r o t - P A G E _ O F F S E T )
}
{
ld r1 , r4 / * a c c e s s _ p t e f o r h v _ i n s t a l l _ c o n t e x t * /
}
{
moveli r0 , h w1 _ l a s t ( . L s v _ d a t a _ p m d - P A G E _ O F F S E T )
moveli r6 , h w1 _ l a s t ( t e m p _ d a t a _ p m d - P A G E _ O F F S E T )
}
{
/* After initializing swapper_pgprot, HV_PTE_GLOBAL is set. */
bfextu r7 , r1 , H V _ P T E _ I N D E X _ G L O B A L , H V _ P T E _ I N D E X _ G L O B A L
2013-07-23 17:32:04 -04:00
finv r4
2011-05-04 14:38:26 -04:00
}
bnez r7 , . L n o _ w r i t e
{
shl1 6 i n s l i r0 , r0 , h w0 ( . L s v _ d a t a _ p m d - P A G E _ O F F S E T )
shl1 6 i n s l i r6 , r6 , h w0 ( t e m p _ d a t a _ p m d - P A G E _ O F F S E T )
}
{
/* Cut off the low bits of the PT address. */
shrui r6 , r6 , H V _ L O G 2 _ P A G E _ T A B L E _ A L I G N
/* Start with our access pte. */
move r5 , r1
}
{
/* Stuff the address into the page table pointer slot of the PTE. */
bfins r5 , r6 , H V _ P T E _ I N D E X _ P T F N , \
HV_ P T E _ I N D E X _ P T F N + H V _ P T E _ P T F N _ B I T S - 1
}
{
/* Store the L0 data PTE. */
st r0 , r5
addli r6 , r6 , ( t e m p _ c o d e _ p m d - t e m p _ d a t a _ p m d ) > > \
HV_ L O G 2 _ P A G E _ T A B L E _ A L I G N
}
{
addli r0 , r0 , . L s v _ c o d e _ p m d - . L s v _ d a t a _ p m d
bfins r5 , r6 , H V _ P T E _ I N D E X _ P T F N , \
HV_ P T E _ I N D E X _ P T F N + H V _ P T E _ P T F N _ B I T S - 1
}
/* Store the L0 code PTE. */
st r0 , r5
.Lno_write :
moveli l r , h w2 _ l a s t ( 1 f )
{
shl1 6 i n s l i l r , l r , h w1 ( 1 f )
moveli r0 , h w1 _ l a s t ( s w a p p e r _ p g _ d i r - P A G E _ O F F S E T )
}
{
shl1 6 i n s l i l r , l r , h w0 ( 1 f )
shl1 6 i n s l i r0 , r0 , h w0 ( s w a p p e r _ p g _ d i r - P A G E _ O F F S E T )
}
{
2012-03-29 13:58:43 -04:00
moveli r3 , C T X _ P A G E _ F L A G
2013-08-07 16:03:08 -04:00
j _ h v _ i n s t a l l _ c o n t e x t
2011-05-04 14:38:26 -04:00
}
1 :
/* Install the interrupt base. */
2013-09-03 14:41:36 -04:00
moveli r0 , h w2 _ l a s t ( i n t r p t _ s t a r t )
shl1 6 i n s l i r0 , r0 , h w1 ( i n t r p t _ s t a r t )
shl1 6 i n s l i r0 , r0 , h w0 ( i n t r p t _ s t a r t )
2011-05-04 14:38:26 -04:00
mtspr S P R _ I N T E R R U P T _ V E C T O R _ B A S E _ K , r0
2013-08-07 11:55:35 -04:00
/* Get our processor number and save it away in SAVE_K_0. */
2013-08-07 16:03:08 -04:00
jal _ h v _ i n q u i r e _ t o p o l o g y
2011-05-04 14:38:26 -04:00
{
2013-08-07 11:55:35 -04:00
GET_ F I R S T _ I N T ( r5 , r1 ) / * r5 = w i d t h * /
GET_ S E C O N D _ I N T ( r4 , r0 ) / * r4 = y * /
2011-05-04 14:38:26 -04:00
}
{
2013-08-07 11:55:35 -04:00
GET_ F I R S T _ I N T ( r6 , r0 ) / * r6 = x * /
2011-05-04 14:38:26 -04:00
mul_ l u _ l u r4 , r4 , r5
}
{
add r4 , r4 , r6 / * r4 = = c p u = = y * w i d t h + x * /
}
# ifdef C O N F I G _ S M P
/ *
* Load u p o u r p e r - c p u o f f s e t . W h e n t h e f i r s t ( m a s t e r ) t i l e
* boots, t h i s v a l u e i s s t i l l z e r o , s o w e w i l l l o a d b o o t _ p c
2013-08-10 12:35:02 -04:00
* with s t a r t _ k e r n e l , a n d b o o t _ s p w i t h a t t h e t o p o f i n i t _ s t a c k .
2011-05-04 14:38:26 -04:00
* The m a s t e r t i l e i n i t i a l i z e s t h e p e r - c p u o f f s e t a r r a y , s o t h a t
* when s u b s e q u e n t ( s e c o n d a r y ) t i l e s b o o t , t h e y w i l l i n s t e a d l o a d
* from t h e i r p e r - c p u v e r s i o n s o f b o o t _ s p a n d b o o t _ p c .
* /
moveli r5 , h w2 _ l a s t ( _ _ p e r _ c p u _ o f f s e t )
shl1 6 i n s l i r5 , r5 , h w1 ( _ _ p e r _ c p u _ o f f s e t )
shl1 6 i n s l i r5 , r5 , h w0 ( _ _ p e r _ c p u _ o f f s e t )
shl3 a d d r5 , r4 , r5
ld r5 , r5
bnez r5 , 1 f
/ *
* Save t h e w i d t h a n d h e i g h t t o t h e s m p _ t o p o l o g y v a r i a b l e
* for l a t e r u s e .
* /
moveli r0 , h w2 _ l a s t ( s m p _ t o p o l o g y + H V _ T O P O L O G Y _ W I D T H _ O F F S E T )
shl1 6 i n s l i r0 , r0 , h w1 ( s m p _ t o p o l o g y + H V _ T O P O L O G Y _ W I D T H _ O F F S E T )
shl1 6 i n s l i r0 , r0 , h w0 ( s m p _ t o p o l o g y + H V _ T O P O L O G Y _ W I D T H _ O F F S E T )
st r0 , r1
1 :
# else
move r5 , z e r o
# endif
/* Load and go with the correct pc and sp. */
{
moveli r1 , h w2 _ l a s t ( b o o t _ s p )
moveli r0 , h w2 _ l a s t ( b o o t _ p c )
}
{
shl1 6 i n s l i r1 , r1 , h w1 ( b o o t _ s p )
shl1 6 i n s l i r0 , r0 , h w1 ( b o o t _ p c )
}
{
shl1 6 i n s l i r1 , r1 , h w0 ( b o o t _ s p )
shl1 6 i n s l i r0 , r0 , h w0 ( b o o t _ p c )
}
{
add r1 , r1 , r5
add r0 , r0 , r5
}
ld r0 , r0
ld s p , r1
2013-08-10 12:35:02 -04:00
shli r4 , r4 , C P U _ S H I F T
bfins r4 , s p , 0 , C P U _ S H I F T - 1
2011-05-04 14:38:26 -04:00
mtspr S P R _ S Y S T E M _ S A V E _ K _ 0 , r4 / * s a v e k s p0 + c p u * /
{
move l r , z e r o / * s t o p b a c k t r a c e s i n t h e c a l l e d f u n c t i o n * /
jr r0
}
ENDPROC( _ s t a r t )
_ _ PAGE_ A L I G N E D _ B S S
.align PAGE_SIZE
ENTRY( e m p t y _ z e r o _ p a g e )
.fill PAGE_ S I Z E ,1 ,0
END( e m p t y _ z e r o _ p a g e )
.macro PTE cpa, b i t s1
.quad HV_PTE_PAGE | HV_ P T E _ D I R T Y | H V _ P T E _ P R E S E N T | H V _ P T E _ A C C E S S E D | \
HV_ P T E _ G L O B A L | ( H V _ P T E _ M O D E _ C A C H E _ N O _ L 3 < < H V _ P T E _ I N D E X _ M O D E ) | \
2012-03-29 13:58:43 -04:00
( \ bits1 ) | ( H V _ C P A _ T O _ P T F N ( \ c p a ) < < H V _ P T E _ I N D E X _ P T F N )
2011-05-04 14:38:26 -04:00
.endm
_ _ PAGE_ A L I G N E D _ D A T A
.align PAGE_SIZE
ENTRY( s w a p p e r _ p g _ d i r )
2012-03-29 13:58:43 -04:00
.org swapper_pg_dir + PGD_ I N D E X ( P A G E _ O F F S E T ) * H V _ P T E _ S I Z E
2011-05-04 14:38:26 -04:00
.Lsv_data_pmd :
.quad 0 /* PTE temp_data_pmd - PAGE_OFFSET, 0 */
2012-03-29 13:58:43 -04:00
.org swapper_pg_dir + PGD_ I N D E X ( M E M _ S V _ S T A R T ) * H V _ P T E _ S I Z E
2011-05-04 14:38:26 -04:00
.Lsv_code_pmd :
.quad 0 /* PTE temp_code_pmd - PAGE_OFFSET, 0 */
2012-03-29 13:58:43 -04:00
.org swapper_pg_dir + SIZEOF_ P G D
2011-05-04 14:38:26 -04:00
END( s w a p p e r _ p g _ d i r )
.align HV_PAGE_TABLE_ALIGN
ENTRY( t e m p _ d a t a _ p m d )
/ *
* We f i l l t h e P A G E _ O F F S E T p m d w i t h h u g e p a g e s w i t h
* VA = P A + P A G E _ O F F S E T . W e r e m a p t h i n g s w i t h m o r e p r e c i s e a c c e s s
* permissions l a t e r .
* /
.set addr, 0
2012-03-29 13:58:43 -04:00
.rept PTRS_PER_PMD
2011-05-04 14:38:26 -04:00
PTE a d d r , H V _ P T E _ R E A D A B L E | H V _ P T E _ W R I T A B L E
2012-03-29 13:58:43 -04:00
.set addr, a d d r + H P A G E _ S I Z E
2011-05-04 14:38:26 -04:00
.endr
2012-03-29 13:58:43 -04:00
.org temp_data_pmd + SIZEOF_ P M D
2011-05-04 14:38:26 -04:00
END( t e m p _ d a t a _ p m d )
.align HV_PAGE_TABLE_ALIGN
ENTRY( t e m p _ c o d e _ p m d )
/ *
* We f i l l t h e M E M _ S V _ S T A R T p m d w i t h h u g e p a g e s w i t h
* VA = P A + P A G E _ O F F S E T . W e r e m a p t h i n g s w i t h m o r e p r e c i s e a c c e s s
* permissions l a t e r .
* /
.set addr, 0
2012-03-29 13:58:43 -04:00
.rept PTRS_PER_PMD
2011-05-04 14:38:26 -04:00
PTE a d d r , H V _ P T E _ R E A D A B L E | H V _ P T E _ E X E C U T A B L E
2012-03-29 13:58:43 -04:00
.set addr, a d d r + H P A G E _ S I Z E
2011-05-04 14:38:26 -04:00
.endr
2012-03-29 13:58:43 -04:00
.org temp_code_pmd + SIZEOF_ P M D
2011-05-04 14:38:26 -04:00
END( t e m p _ c o d e _ p m d )
/ *
* Isolate s w a p p e r _ p g p r o t t o i t s o w n c a c h e l i n e , s i n c e e a c h c p u
* starting u p w i l l r e a d i t u s i n g V A - i s - P A a n d l o c a l h o m i n g .
* This w o u l d o t h e r w i s e l i k e l y c o n f l i c t w i t h o t h e r d a t a o n t h e c a c h e
* line, o n c e w e h a v e s e t i t s p e r m a n e n t h o m e i n t h e p a g e t a b l e s .
* /
_ _ INITDATA
.align CHIP_ L 2 _ L I N E _ S I Z E ( )
ENTRY( s w a p p e r _ p g p r o t )
.quad HV_PTE_PRESENT | ( HV_ P T E _ M O D E _ C A C H E _ N O _ L 3 < < H V _ P T E _ I N D E X _ M O D E )
.align CHIP_ L 2 _ L I N E _ S I Z E ( )
END( s w a p p e r _ p g p r o t )