2011-05-04 22: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 .
*
* Linux i n t e r r u p t v e c t o r s .
* /
# include < l i n u x / l i n k a g e . h >
# include < l i n u x / e r r n o . h >
# include < l i n u x / u n i s t d . h >
2013-08-07 00:04:13 +04:00
# include < l i n u x / i n i t . h >
2011-05-04 22:38:26 +04:00
# include < a s m / p t r a c e . h >
# include < a s m / t h r e a d _ i n f o . h >
# include < a s m / i r q f l a g s . h >
# include < a s m / a s m - o f f s e t s . h >
# include < a s m / t y p e s . h >
2013-08-07 00:04:13 +04:00
# include < a s m / t r a p s . h >
2012-03-30 00:11:09 +04:00
# include < a s m / s i g n a l . h >
2011-05-04 22:38:26 +04:00
# include < h v / h y p e r v i s o r . h >
# include < a r c h / a b i . h >
# include < a r c h / i n t e r r u p t s . h >
# include < a r c h / s p r _ d e f . h >
# define P T R E G S _ P T R ( r e g , p t r e g ) a d d l i r e g , s p , C _ A B I _ S A V E _ A R E A _ S I Z E + ( p t r e g )
# define P T R E G S _ O F F S E T _ S Y S C A L L P T R E G S _ O F F S E T _ R E G ( T R E G _ S Y S C A L L _ N R )
2013-09-03 22:45:52 +04:00
# if C O N F I G _ K E R N E L _ P L = = 1 | | C O N F I G _ K E R N E L _ P L = = 2
/ *
* Set " r e s u l t " n o n - z e r o i f e x1 h o l d s t h e P L o f t h e k e r n e l
* ( with o r w i t h o u t I C S b e i n g s e t ) . N o t e t h i s w o r k s o n l y
* because w e n e v e r f i n d t h e P L a t l e v e l 3 .
* /
# define I S _ K E R N E L _ E X 1 ( r e s u l t , e x1 ) a n d i r e s u l t , e x1 , C O N F I G _ K E R N E L _ P L
# else
# error R e c o d e I S _ K E R N E L _ E X 1 f o r C O N F I G _ K E R N E L _ P L
# endif
2011-05-04 22:38:26 +04:00
.macro push_reg reg, p t r =sp , d e l t a = - 8
{
st \ p t r , \ r e g
addli \ p t r , \ p t r , \ d e l t a
}
.endm
.macro pop_reg reg, p t r =sp , d e l t a =8
{
ld \ r e g , \ p t r
addli \ p t r , \ p t r , \ d e l t a
}
.endm
.macro pop_reg_zero reg, z r e g , p t r =sp , d e l t a =8
{
move \ z r e g , z e r o
ld \ r e g , \ p t r
addi \ p t r , \ p t r , \ d e l t a
}
.endm
.macro push_extra_callee_saves reg
PTREGS_ P T R ( \ r e g , P T R E G S _ O F F S E T _ R E G ( 5 1 ) )
push_ r e g r51 , \ r e g
push_ r e g r50 , \ r e g
push_ r e g r49 , \ r e g
push_ r e g r48 , \ r e g
push_ r e g r47 , \ r e g
push_ r e g r46 , \ r e g
push_ r e g r45 , \ r e g
push_ r e g r44 , \ r e g
push_ r e g r43 , \ r e g
push_ r e g r42 , \ r e g
push_ r e g r41 , \ r e g
push_ r e g r40 , \ r e g
push_ r e g r39 , \ r e g
push_ r e g r38 , \ r e g
push_ r e g r37 , \ r e g
push_ r e g r36 , \ r e g
push_ r e g r35 , \ r e g
push_ r e g r34 , \ r e g , P T R E G S _ O F F S E T _ B A S E - P T R E G S _ O F F S E T _ R E G ( 3 4 )
.endm
.macro panic str
.pushsection .rodata , " a"
1 :
.asciz " \ str"
.popsection
{
moveli r0 , h w2 _ l a s t ( 1 b )
}
{
shl1 6 i n s l i r0 , r0 , h w1 ( 1 b )
}
{
shl1 6 i n s l i r0 , r0 , h w0 ( 1 b )
jal p a n i c
}
.endm
2013-08-07 00:04:13 +04:00
/ *
* Unalign d a t a e x c e p t i o n f a s t h a n d l i n g : I n o r d e r t o h a n d l e
* unaligned d a t a a c c e s s , a f a s t J I T v e r s i o n i s g e n e r a t e d a n d s t o r e d
* in a s p e c i f i c a r e a i n u s e r s p a c e . W e f i r s t n e e d t o d o a q u i c k p o k e
* to s e e i f t h e J I T i s a v a i l a b l e . W e u s e c e r t a i n b i t s i n t h e f a u l t
* PC ( 3 t o 9 i s u s e d f o r 1 6 K B p a g e s i z e ) a s i n d e x t o a d d r e s s t h e J I T
* code a r e a . T h e f i r s t 6 4 b i t w o r d i s t h e f a u l t P C , a n d t h e 2 n d o n e i s
* the f a u l t b u n d l e i t s e l f . I f t h e s e 2 w o r d s b o t h m a t c h , t h e n w e
* directly " i r e t " t o J I T c o d e . I f n o t , a s l o w p a t h i s i n v o k e d t o
* generate n e w J I T c o d e . N o t e : t h e c u r r e n t J I T c o d e W I L L b e
* overwritten i f i t e x i s t e d . S o , i d e a l l y w e c a n h a n d l e 1 2 8 u n a l i g n
* fixups v i a J I T . F o r l o o k u p e f f i c i e n c y a n d t o e f f e c t i v e l y s u p p o r t
* tight l o o p s w i t h m u l t i p l e u n a l i g n e d r e f e r e n c e , a s i m p l e
* direct- m a p p e d c a c h e i s u s e d .
*
* SPR_ E X _ C O N T E X T _ K _ 0 i s m o d i f i e d t o r e t u r n t o J I T c o d e .
* SPR_ E X _ C O N T E X T _ K _ 1 h a s I C S s e t .
* SPR_ E X _ C O N T E X T _ 0 _ 0 i s s e t u p t o u s e r p r o g r a m ' s n e x t P C .
* SPR_ E X _ C O N T E X T _ 0 _ 1 = 0 .
* /
.macro int_hand_unalign_fast vecnum, v e c n a m e
.org ( \ vecnum < < 8 )
intvec_ \ v e c n a m e :
/* Put r3 in SPR_SYSTEM_SAVE_K_1. */
mtspr S P R _ S Y S T E M _ S A V E _ K _ 1 , r3
mfspr r3 , S P R _ E X _ C O N T E X T _ K _ 1
/ *
* Examine i f e x c e p t i o n c o m e s f r o m u s e r w i t h o u t I C S s e t .
* If n o t , j u s t g o d i r e c t l y t o t h e s l o w p a t h .
* /
bnez r3 , h a n d _ u n a l i g n _ s l o w _ n o n u s e r
mfspr r3 , S P R _ S Y S T E M _ S A V E _ K _ 0
/* Get &thread_info->unalign_jit_tmp[0] in r3. */
2013-08-10 20:35:02 +04:00
bfexts r3 , r3 , 0 , C P U _ S H I F T - 1
2013-08-07 00:04:13 +04:00
mm r3 , z e r o , L O G 2 _ T H R E A D _ S I Z E , 6 3
2013-08-10 20:35:02 +04:00
addli r3 , r3 , T H R E A D _ I N F O _ U N A L I G N _ J I T _ T M P _ O F F S E T
2013-08-07 00:04:13 +04:00
/ *
* Save r0 , r1 , r2 i n t o t h r e a d _ i n f o a r r a y r3 p o i n t s t o
* from l o w t o h i g h m e m o r y i n o r d e r .
* /
st_ a d d r3 , r0 , 8
st_ a d d r3 , r1 , 8
{
st_ a d d r3 , r2 , 8
andi r2 , s p , 7
}
/* Save stored r3 value so we can revert it on a page fault. */
mfspr r1 , S P R _ S Y S T E M _ S A V E _ K _ 1
st r3 , r1
{
/* Generate a SIGBUS if sp is not 8-byte aligned. */
bnez r2 , h a n d _ u n a l i g n _ s l o w _ b a d s p
}
/ *
* Get t h e t h r e a d _ i n f o i n r0 ; load r1 with pc. Set the low bit of sp
* as a n i n d i c a t o r t o t h e p a g e f a u l t c o d e i n c a s e w e f a u l t .
* /
{
ori s p , s p , 1
mfspr r1 , S P R _ E X _ C O N T E X T _ K _ 0
}
/* Add the jit_info offset in thread_info; extract r1 [3:9] into r2. */
{
addli r0 , r3 , T H R E A D _ I N F O _ U N A L I G N _ J I T _ B A S E _ O F F S E T - \
( THREAD_ I N F O _ U N A L I G N _ J I T _ T M P _ O F F S E T + ( 3 * 8 ) )
bfextu r2 , r1 , 3 , ( 2 + P A G E _ S H I F T - U N A L I G N _ J I T _ S H I F T )
}
/* Load the jit_info; multiply r2 by 128. */
{
ld r0 , r0
shli r2 , r2 , U N A L I G N _ J I T _ S H I F T
}
/ *
* If r0 i s N U L L , t h e J I T p a g e i s n o t m a p p e d , s o g o t o s l o w p a t h ;
* add o f f s e t r2 t o r0 a t t h e s a m e t i m e .
* /
{
beqz r0 , h a n d _ u n a l i g n _ s l o w
add r2 , r0 , r2
}
/ *
* We a r e l o a d i n g f r o m u s e r s p a c e ( b o t h t h e J I T i n f o P C a n d
* instruction w o r d , a n d t h e i n s t r u c t i o n w o r d w e e x e c u t e d )
* and s i n c e e i t h e r c o u l d f a u l t w h i l e h o l d i n g t h e i n t e r r u p t
* critical s e c t i o n , w e m u s t t a g t h i s r e g i o n a n d c h e c k i t i n
* do_ p a g e _ f a u l t ( ) t o h a n d l e i t p r o p e r l y .
* /
ENTRY( _ _ s t a r t _ u n a l i g n _ a s m _ c o d e )
/* Load first word of JIT in r0 and increment r2 by 8. */
ld_ a d d r0 , r2 , 8
/ *
* Compare t h e P C w i t h t h e 1 s t w o r d i n J I T ; load the fault bundle
* into r1 .
* /
{
cmpeq r0 , r0 , r1
ld r1 , r1
}
/* Go to slow path if PC doesn't match. */
beqz r0 , h a n d _ u n a l i g n _ s l o w
/ *
* Load t h e 2 n d w o r d o f J I T , w h i c h i s s u p p o s e d t o b e t h e f a u l t
* bundle f o r a c a c h e h i t . I n c r e m e n t r2 ; after this bundle r2 will
* point t o t h e p o t e n t i a l s t a r t o f t h e J I T c o d e w e w a n t t o r u n .
* /
ld_ a d d r0 , r2 , 8
/* No further accesses to userspace are done after this point. */
ENTRY( _ _ e n d _ u n a l i g n _ a s m _ c o d e )
/* Compare the real bundle with what is saved in the JIT area. */
{
cmpeq r0 , r1 , r0
mtspr S P R _ E X _ C O N T E X T _ 0 _ 1 , z e r o
}
/* Go to slow path if the fault bundle does not match. */
beqz r0 , h a n d _ u n a l i g n _ s l o w
/ *
* A c a c h e h i t i s f o u n d .
* r2 p o i n t s t o s t a r t o f J I T c o d e ( 3 r d w o r d ) .
* r0 i s t h e f a u l t p c .
* r1 i s t h e f a u l t b u n d l e .
* Reset t h e l o w b i t o f s p .
* /
{
mfspr r0 , S P R _ E X _ C O N T E X T _ K _ 0
andi s p , s p , ~ 1
}
/* Write r2 into EX_CONTEXT_K_0 and increment PC. */
{
mtspr S P R _ E X _ C O N T E X T _ K _ 0 , r2
addi r0 , r0 , 8
}
/ *
* Set I C S o n k e r n e l E X _ C O N T E X T _ K _ 1 i n o r d e r t o " i r e t " t o
* user w i t h I C S s e t . T h i s w a y , i f t h e J I T f i x u p c a u s e s a n o t h e r
* unalign e x c e p t i o n ( w h i c h s h o u l d n ' t b e p o s s i b l e ) t h e u s e r
* process w i l l b e t e r m i n a t e d w i t h S I G B U S . A l s o , o u r f i x u p w i l l
* run w i t h o u t i n t e r l e a v i n g w i t h e x t e r n a l i n t e r r u p t s .
* Each f i x u p i s a t m o s t 1 4 b u n d l e s , s o i t w o n ' t h o l d I C S f o r l o n g .
* /
{
movei r1 , P L _ I C S _ E X 1 ( U S E R _ P L , 1 )
mtspr S P R _ E X _ C O N T E X T _ 0 _ 0 , r0
}
{
mtspr S P R _ E X _ C O N T E X T _ K _ 1 , r1
addi r3 , r3 , - ( 3 * 8 )
}
/* Restore r0..r3. */
ld_ a d d r0 , r3 , 8
ld_ a d d r1 , r3 , 8
ld_ a d d r2 , r3 , 8
ld r3 , r3
iret
ENDPROC( i n t v e c _ \ v e c n a m e )
.endm
2011-05-04 22:38:26 +04:00
# ifdef _ _ C O L L E C T _ L I N K E R _ F E E D B A C K _ _
.pushsection .text .intvec_feedback , " ax"
intvec_feedback :
.popsection
# endif
/ *
* Default i n t e r r u p t h a n d l e r .
*
* vecnum i s w h e r e w e ' l l p u t t h i s c o d e .
* c_ r o u t i n e i s t h e C r o u t i n e w e ' l l c a l l .
*
* The C r o u t i n e i s p a s s e d t w o a r g u m e n t s :
* - A p o i n t e r t o t h e p t _ r e g s s t a t e .
* - The i n t e r r u p t v e c t o r n u m b e r .
*
* The " p r o c e s s i n g " a r g u m e n t s p e c i f i e s t h e c o d e f o r p r o c e s s i n g
* the i n t e r r u p t . D e f a u l t s t o " h a n d l e _ i n t e r r u p t " .
* /
2013-08-07 00:04:13 +04:00
.macro __int_hand vecnum, v e c n a m e , c _ r o u t i n e ,p r o c e s s i n g =handle_interrupt
2011-05-04 22:38:26 +04:00
intvec_ \ v e c n a m e :
/* Temporarily save a register so we have somewhere to work. */
mtspr S P R _ S Y S T E M _ S A V E _ K _ 1 , r0
mfspr r0 , S P R _ E X _ C O N T E X T _ K _ 1
2013-08-07 00:04:13 +04:00
/ *
* The u n a l i g n d a t a f a s t p a t h c o d e s e t s t h e l o w b i t i n s p t o
* force u s t o r e s e t i t h e r e o n f a u l t .
* /
{
blbs s p , 2 f
2013-09-03 22:45:52 +04:00
IS_ K E R N E L _ E X 1 ( r0 , r0 )
2013-08-07 00:04:13 +04:00
}
2011-05-04 22:38:26 +04:00
.ifc \ vecnum, I N T _ D O U B L E _ F A U L T
/ *
* For d o u b l e - f a u l t s f r o m u s e r - s p a c e , f a l l t h r o u g h t o t h e n o r m a l
* register s a v e a n d s t a c k s e t u p p a t h . O t h e r w i s e , i t ' s t h e
* hypervisor g i v i n g u s o n e l a s t c h a n c e t o d u m p d i a g n o s t i c s , a n d w e
* branch t o t h e k e r n e l _ d o u b l e _ f a u l t r o u t i n e t o d o s o .
* /
beqz r0 , 1 f
j _ k e r n e l _ d o u b l e _ f a u l t
1 :
.else
/ *
* If w e ' r e c o m i n g f r o m u s e r - s p a c e , t h e n s e t s p t o t h e t o p o f
* the k e r n e l s t a c k . O t h e r w i s e , a s s u m e s p i s a l r e a d y v a l i d .
* /
{
bnez r0 , 0 f
move r0 , s p
}
.endif
.ifc \ c_ r o u t i n e , d o _ p a g e _ f a u l t
/ *
* The p a g e _ f a u l t h a n d l e r m a y b e d o w n c a l l e d d i r e c t l y b y t h e
* hypervisor e v e n w h e n L i n u x i s r u n n i n g a n d h a s I C S s e t .
*
* In t h i s c a s e t h e c o n t e n t s o f E X _ C O N T E X T _ K _ 1 r e f l e c t t h e
* previous f a u l t a n d c a n ' t b e r e l i e d o n t o c h o o s e w h e t h e r o r
* not t o r e i n i t i a l i z e t h e s t a c k p o i n t e r . S o w e a d d a t e s t
* to s e e w h e t h e r S Y S T E M _ S A V E _ K _ 2 h a s t h e h i g h b i t s e t ,
* and i f s o w e d o n ' t r e i n i t i a l i z e s p , s i n c e w e m u s t b e c o m i n g
* from L i n u x . ( I n f a c t t h e p r e c i s e c a s e i s ! ( v a l & ~ 1 ) ,
* but a n y L i n u x P C h a s t o h a v e t h e h i g h b i t s e t . )
*
* Note t h a t t h e h y p e r v i s o r * a l w a y s * s e t s S Y S T E M _ S A V E _ K _ 2 f o r
* any p a t h t h a t t u r n s i n t o a d o w n c a l l t o o n e o f o u r T L B h a n d l e r s .
*
* FIXME : if w e e n d u p n e v e r u s i n g t h i s p a t h , p e r h a p s w e s h o u l d
* prevent t h e h y p e r v i s o r f r o m g e n e r a t i n g d o w n c a l l s i n t h i s c a s e .
* The a d v a n t a g e o f g e t t i n g a d o w n c a l l i s w e c a n p a n i c i n L i n u x .
* /
mfspr r0 , S P R _ S Y S T E M _ S A V E _ K _ 2
{
bltz r0 , 0 f / * h i g h b i t i n S _ S _ 1 _ 2 i s f o r a P C t o u s e * /
move r0 , s p
}
.endif
2013-08-07 00:04:13 +04:00
2 :
2011-05-04 22:38:26 +04:00
/ *
2013-08-10 20:35:02 +04:00
* SYSTEM_ S A V E _ K _ 0 h o l d s t h e c p u n u m b e r i n t h e h i g h b i t s , a n d
* the c u r r e n t s t a c k t o p i n t h e l o w e r b i t s . S o w e r e c o v e r
* our s t a r t i n g s t a c k v a l u e b y s i g n - e x t e n d i n g t h e l o w b i t s , t h e n
2011-05-04 22:38:26 +04:00
* point s p a t t h e t o p a l i g n e d a d d r e s s o n t h e a c t u a l s t a c k p a g e .
* /
mfspr r0 , S P R _ S Y S T E M _ S A V E _ K _ 0
2013-08-10 20:35:02 +04:00
bfexts r0 , r0 , 0 , C P U _ S H I F T - 1
2011-05-04 22:38:26 +04:00
0 :
/ *
* Align t h e s t a c k m o d 6 4 s o w e c a n p r o p e r l y p r e d i c t w h a t
* cache l i n e s w e n e e d t o w r i t e - h i n t t o r e d u c e m e m o r y f e t c h
* latency a s w e e n t e r t h e k e r n e l . T h e l a y o u t o f m e m o r y i s
* as f o l l o w s , w i t h c a c h e l i n e 0 a t t h e l o w e s t V A , a n d c a c h e
* line 8 j u s t b e l o w t h e r0 v a l u e t h i s " a n d i " c o m p u t e s .
* Note t h a t w e n e v e r w r i t e t o c a c h e l i n e 8 , a n d w e s k i p
* cache l i n e s 1 - 3 f o r s y s c a l l s .
*
* cache l i n e 8 : p t r e g s p a d d i n g ( t w o w o r d s )
* cache l i n e 7 : s p , l r , p c , e x1 , f a u l t n u m , o r i g _ r0 , f l a g s , c m p e x c h
* cache l i n e 6 : r46 . . . r53 ( t p )
* cache l i n e 5 : r38 . . . r45
* cache l i n e 4 : r30 . . . r37
* cache l i n e 3 : r22 . . . r29
* cache l i n e 2 : r14 . . . r21
* cache l i n e 1 : r6 . . . r13
* cache l i n e 0 : 2 x f r a m e , r0 . . r5
* /
2013-08-10 20:35:02 +04:00
# if S T A C K _ T O P _ D E L T A ! = 6 4
# error S T A C K _ T O P _ D E L T A m u s t b e 6 4 f o r a s s u m p t i o n s h e r e a n d i n t a s k _ p t _ r e g s ( )
# endif
2011-05-04 22:38:26 +04:00
andi r0 , r0 , - 6 4
/ *
* Push t h e f i r s t f o u r r e g i s t e r s o n t h e s t a c k , s o t h a t w e c a n s e t
* them t o v e c t o r - u n i q u e v a l u e s b e f o r e w e j u m p t o t h e c o m m o n c o d e .
*
* Registers a r e p u s h e d o n t h e s t a c k a s a s t r u c t p t _ r e g s ,
* with t h e s p i n i t i a l l y j u s t a b o v e t h e s t r u c t , a n d w h e n w e ' r e
* done, s p p o i n t s t o t h e b a s e o f t h e s t r u c t , m i n u s
* C_ A B I _ S A V E _ A R E A _ S I Z E , s o w e c a n d i r e c t l y j a l t o C c o d e .
*
* This r o u t i n e s a v e s j u s t t h e f i r s t f o u r r e g i s t e r s , p l u s t h e
* stack c o n t e x t s o w e c a n d o p r o p e r b a c k t r a c i n g r i g h t a w a y ,
* and d e f e r s t o h a n d l e _ i n t e r r u p t t o s a v e t h e r e s t .
2012-03-27 23:40:20 +04:00
* The b a c k t r a c e r n e e d s p c , e x1 , l r , s p , r52 , a n d f a u l t n u m ,
* and n e e d s s p s e t t o i t s f i n a l l o c a t i o n a t t h e b o t t o m o f
* the s t a c k f r a m e .
2011-05-04 22:38:26 +04:00
* /
addli r0 , r0 , P T R E G S _ O F F S E T _ L R - ( P T R E G S _ S I Z E + K S T K _ P T R E G S _ G A P )
wh6 4 r0 / * c a c h e l i n e 7 * /
{
st r0 , l r
addli r0 , r0 , P T R E G S _ O F F S E T _ S P - P T R E G S _ O F F S E T _ L R
}
{
st r0 , s p
addli s p , r0 , P T R E G S _ O F F S E T _ R E G ( 5 2 ) - P T R E G S _ O F F S E T _ S P
}
wh6 4 s p / * c a c h e l i n e 6 * /
{
st s p , r52
addli s p , s p , P T R E G S _ O F F S E T _ R E G ( 1 ) - P T R E G S _ O F F S E T _ R E G ( 5 2 )
}
wh6 4 s p / * c a c h e l i n e 0 * /
{
st s p , r1
addli s p , s p , P T R E G S _ O F F S E T _ R E G ( 2 ) - P T R E G S _ O F F S E T _ R E G ( 1 )
}
{
st s p , r2
addli s p , s p , P T R E G S _ O F F S E T _ R E G ( 3 ) - P T R E G S _ O F F S E T _ R E G ( 2 )
}
{
st s p , r3
addli s p , s p , P T R E G S _ O F F S E T _ P C - P T R E G S _ O F F S E T _ R E G ( 3 )
}
mfspr r0 , S P R _ E X _ C O N T E X T _ K _ 0
.ifc \ processing,h a n d l e _ s y s c a l l
/ *
* Bump t h e s a v e d P C b y o n e b u n d l e s o t h a t w h e n w e r e t u r n , w e w o n ' t
* execute t h e s a m e s w i n t i n s t r u c t i o n a g a i n . W e n e e d t o d o t h i s w h i l e
* we' r e i n t h e c r i t i c a l s e c t i o n .
* /
addi r0 , r0 , 8
.endif
{
st s p , r0
addli s p , s p , P T R E G S _ O F F S E T _ E X 1 - P T R E G S _ O F F S E T _ P C
}
mfspr r0 , S P R _ E X _ C O N T E X T _ K _ 1
{
st s p , r0
addi s p , s p , P T R E G S _ O F F S E T _ F A U L T N U M - P T R E G S _ O F F S E T _ E X 1
/ *
* Use r0 f o r s y s c a l l s s o i t ' s a t e m p o r a r y ; use r1 for interrupts
* so t h a t i t g e t s p a s s e d t h r o u g h u n c h a n g e d t o t h e h a n d l e r r o u t i n e .
* Note t h a t t h e . i f c o n d i t i o n a l c o n f u s i n g l y s p a n s b u n d l e s .
* /
.ifc \ processing,h a n d l e _ s y s c a l l
movei r0 , \ v e c n u m
}
{
st s p , r0
.else
movei r1 , \ v e c n u m
}
{
st s p , r1
.endif
addli s p , s p , P T R E G S _ O F F S E T _ R E G ( 0 ) - P T R E G S _ O F F S E T _ F A U L T N U M
}
mfspr r0 , S P R _ S Y S T E M _ S A V E _ K _ 1 / * O r i g i n a l r0 * /
{
st s p , r0
addi s p , s p , - P T R E G S _ O F F S E T _ R E G ( 0 ) - 8
}
{
st s p , z e r o / * w r i t e z e r o i n t o " N e x t S P " f r a m e p o i n t e r * /
addi s p , s p , - 8 / * l e a v e S P p o i n t i n g a t b o t t o m o f f r a m e * /
}
.ifc \ processing,h a n d l e _ s y s c a l l
j h a n d l e _ s y s c a l l
.else
/* Capture per-interrupt SPR context to registers. */
.ifc \ c_ r o u t i n e , d o _ p a g e _ f a u l t
mfspr r2 , S P R _ S Y S T E M _ S A V E _ K _ 3 / * a d d r e s s o f p a g e f a u l t * /
mfspr r3 , S P R _ S Y S T E M _ S A V E _ K _ 2 / * i n f o a b o u t p a g e f a u l t * /
.else
.ifc \ vecnum, I N T _ I L L _ T R A N S
2013-08-07 20:11:56 +04:00
mfspr r2 , I L L _ V A _ P C
2011-05-04 22:38:26 +04:00
.else
.ifc \ vecnum, I N T _ D O U B L E _ F A U L T
mfspr r2 , S P R _ S Y S T E M _ S A V E _ K _ 2 / * d o u b l e f a u l t i n f o f r o m H V * /
.else
.ifc \ c_ r o u t i n e , d o _ t r a p
mfspr r2 , G P V _ R E A S O N
.else
2014-01-27 11:11:07 +04:00
.ifc \ c_ r o u t i n e , h a n d l e _ p e r f _ i n t e r r u p t
2011-05-04 22:38:26 +04:00
mfspr r2 , P E R F _ C O U N T _ S T S
.else
2014-01-27 11:11:07 +04:00
.ifc \ c_ r o u t i n e , h a n d l e _ p e r f _ i n t e r r u p t
2011-05-04 22:38:26 +04:00
mfspr r2 , A U X _ P E R F _ C O U N T _ S T S
.endif
2015-05-05 00:26:35 +03:00
.ifc \ c_ r o u t i n e , d o _ n m i
mfspr r2 , S P R _ S Y S T E M _ S A V E _ K _ 2 / * n m i t y p e * /
.else
.endif
2011-05-04 22:38:26 +04:00
.endif
.endif
.endif
.endif
.endif
/* Put function pointer in r0 */
moveli r0 , h w2 _ l a s t ( \ c _ r o u t i n e )
shl1 6 i n s l i r0 , r0 , h w1 ( \ c _ r o u t i n e )
{
shl1 6 i n s l i r0 , r0 , h w0 ( \ c _ r o u t i n e )
j \ p r o c e s s i n g
}
.endif
ENDPROC( i n t v e c _ \ v e c n a m e )
# ifdef _ _ C O L L E C T _ L I N K E R _ F E E D B A C K _ _
.pushsection .text .intvec_feedback , " ax"
.org ( \ vecnum < < 5 )
2013-09-03 22:41:36 +04:00
FEEDBACK_ E N T E R _ E X P L I C I T ( i n t v e c _ \ v e c n a m e , . i n t r p t , 1 < < 8 )
2011-05-04 22:38:26 +04:00
jrp l r
.popsection
# endif
.endm
/ *
* Save t h e r e s t o f t h e r e g i s t e r s t h a t w e d i d n ' t s a v e i n t h e a c t u a l
* vector i t s e l f . W e c a n ' t u s e r0 - r10 i n c l u s i v e h e r e .
* /
.macro finish_ i n t e r r u p t _ s a v e , f u n c t i o n
/* If it's a syscall, save a proper orig_r0, otherwise just zero. */
PTREGS_ P T R ( r52 , P T R E G S _ O F F S E T _ O R I G _ R 0 )
{
.ifc \ function,h a n d l e _ s y s c a l l
st r52 , r0
.else
st r52 , z e r o
.endif
PTREGS_ P T R ( r52 , P T R E G S _ O F F S E T _ T P )
}
st r52 , t p
{
mfspr t p , C M P E X C H _ V A L U E
PTREGS_ P T R ( r52 , P T R E G S _ O F F S E T _ C M P E X C H )
}
/ *
* For o r d i n a r y s y s c a l l s , w e s a v e n e i t h e r c a l l e r - n o r c a l l e e -
* save r e g i s t e r s , s i n c e t h e s y s c a l l i n v o k e r d o e s n ' t e x p e c t t h e
* caller- s a v e s t o b e s a v e d , a n d t h e c a l l e d k e r n e l f u n c t i o n s w i l l
* take c a r e o f s a v i n g t h e c a l l e e - s a v e s f o r u s .
*
* For i n t e r r u p t s w e s a v e j u s t t h e c a l l e r - s a v e r e g i s t e r s . S a v i n g
* them i s r e q u i r e d ( s i n c e t h e " c a l l e r " c a n ' t s a v e t h e m ) . A g a i n ,
* the c a l l e d k e r n e l f u n c t i o n s w i l l r e s t o r e t h e c a l l e e - s a v e
* registers f o r u s a p p r o p r i a t e l y .
*
* On r e t u r n , w e n o r m a l l y r e s t o r e n o t h i n g s p e c i a l f o r s y s c a l l s ,
* and j u s t t h e c a l l e r - s a v e r e g i s t e r s f o r i n t e r r u p t s .
*
* However, t h e r e a r e s o m e i m p o r t a n t c a v e a t s t o a l l t h i s :
*
* - We a l w a y s s a v e a f e w c a l l e e - s a v e r e g i s t e r s t o g i v e u s
* some s c r a t c h p a d r e g i s t e r s t o c a r r y a c r o s s f u n c t i o n c a l l s .
*
* - fork/ v f o r k / e t c r e q u i r e u s t o s a v e a l l t h e c a l l e e - s a v e
* registers, w h i c h w e d o i n P T R E G S _ S Y S C A L L _ A L L _ R E G S , b e l o w .
*
* - We a l w a y s s a v e r0 . . r5 a n d r10 f o r s y s c a l l s , s i n c e w e n e e d
* to r e l o a d t h e m a b i t l a t e r f o r t h e a c t u a l k e r n e l c a l l , a n d
* since w e m i g h t n e e d t h e m f o r - E R E S T A R T N O I N T R , e t c .
*
* - Before i n v o k i n g a s i g n a l h a n d l e r , w e s a v e t h e u n s a v e d
* callee- s a v e r e g i s t e r s s o t h e y a r e v i s i b l e t o t h e
* signal h a n d l e r o r a n y p t r a c e r .
*
* - If t h e u n s a v e d c a l l e e - s a v e r e g i s t e r s a r e m o d i f i e d , w e s e t
* a b i t i n p t _ r e g s s o w e k n o w t o r e l o a d t h e m f r o m p t _ r e g s
* and n o t j u s t r e l y o n t h e k e r n e l f u n c t i o n u n w i n d i n g .
* ( Done f o r p t r a c e r e g i s t e r w r i t e s a n d S A _ S I G I N F O h a n d l e r . )
* /
{
st r52 , t p
PTREGS_ P T R ( r52 , P T R E G S _ O F F S E T _ R E G ( 3 3 ) )
}
wh6 4 r52 / * c a c h e l i n e 4 * /
push_ r e g r33 , r52
push_ r e g r32 , r52
push_ r e g r31 , r52
.ifc \ function,h a n d l e _ s y s c a l l
push_ r e g r30 , r52 , P T R E G S _ O F F S E T _ S Y S C A L L - P T R E G S _ O F F S E T _ R E G ( 3 0 )
push_ r e g T R E G _ S Y S C A L L _ N R _ N A M E , r52 , \
PTREGS_ O F F S E T _ R E G ( 5 ) - P T R E G S _ O F F S E T _ S Y S C A L L
.else
push_ r e g r30 , r52 , P T R E G S _ O F F S E T _ R E G ( 2 9 ) - P T R E G S _ O F F S E T _ R E G ( 3 0 )
wh6 4 r52 / * c a c h e l i n e 3 * /
push_ r e g r29 , r52
push_ r e g r28 , r52
push_ r e g r27 , r52
push_ r e g r26 , r52
push_ r e g r25 , r52
push_ r e g r24 , r52
push_ r e g r23 , r52
push_ r e g r22 , r52
wh6 4 r52 / * c a c h e l i n e 2 * /
push_ r e g r21 , r52
push_ r e g r20 , r52
push_ r e g r19 , r52
push_ r e g r18 , r52
push_ r e g r17 , r52
push_ r e g r16 , r52
push_ r e g r15 , r52
push_ r e g r14 , r52
wh6 4 r52 / * c a c h e l i n e 1 * /
push_ r e g r13 , r52
push_ r e g r12 , r52
push_ r e g r11 , r52
push_ r e g r10 , r52
push_ r e g r9 , r52
push_ r e g r8 , r52
push_ r e g r7 , r52
push_ r e g r6 , r52
.endif
push_ r e g r5 , r52
st r52 , r4
/ *
* If w e w i l l b e r e t u r n i n g t o t h e k e r n e l , w e w i l l n e e d t o
* reset t h e i n t e r r u p t m a s k s t o t h e s t a t e t h e y h a d b e f o r e .
2013-09-03 22:45:52 +04:00
* Set D I S A B L E _ I R Q i n f l a g s i f f w e c a m e f r o m k e r n e l p l w i t h
* irqs d i s a b l e d .
2011-05-04 22:38:26 +04:00
* /
mfspr r32 , S P R _ E X _ C O N T E X T _ K _ 1
{
2013-09-03 22:45:52 +04:00
IS_ K E R N E L _ E X 1 ( r22 , r22 )
2011-05-04 22:38:26 +04:00
PTREGS_ P T R ( r21 , P T R E G S _ O F F S E T _ F L A G S )
}
beqzt r32 , 1 f / * z e r o i f f r o m u s e r s p a c e * /
IRQS_ D I S A B L E D ( r32 ) / * z e r o i f i r q s e n a b l e d * /
# if P T _ F L A G S _ D I S A B L E _ I R Q ! = 1
# error V a l u e o f I R Q S _ D I S A B L E D u s e d t o s e t P T _ F L A G S _ D I S A B L E _ I R Q ; fix
# endif
1 :
.ifnc \ function,h a n d l e _ s y s c a l l
/* Record the fact that we saved the caller-save registers above. */
ori r32 , r32 , P T _ F L A G S _ C A L L E R _ S A V E S
.endif
st r21 , r32
2012-03-27 23:40:20 +04:00
/ *
* we' v e c a p t u r e d e n o u g h s t a t e t o t h e s t a c k ( i n c l u d i n g i n
* particular o u r E X _ C O N T E X T s t a t e ) t h a t w e c a n n o w r e l e a s e
* the i n t e r r u p t c r i t i c a l s e c t i o n a n d r e p l a c e i t w i t h o u r
* standard " i n t e r r u p t s d i s a b l e d " m a s k v a l u e . T h i s a l l o w s
* synchronous i n t e r r u p t s ( a n d p r o f i l e i n t e r r u p t s ) t o p u n c h
* through f r o m t h i s p o i n t o n w a r d s .
*
* It' s i m p o r t a n t t h a t n o c o d e b e f o r e t h i s p o i n t t o u c h m e m o r y
* other t h a n o u r o w n s t a c k ( t o k e e p t h e i n v a r i a n t t h a t t h i s
* is a l l t h a t g e t s t o u c h e d u n d e r I C S ) , a n d t h a t n o c o d e a f t e r
* this p o i n t r e f e r e n c e a n y i n t e r r u p t - s p e c i f i c S P R , i n p a r t i c u l a r
* the E X _ C O N T E X T _ K _ v a l u e s .
* /
.ifc \ function,h a n d l e _ n m i
IRQ_ D I S A B L E _ A L L ( r20 )
.else
IRQ_ D I S A B L E ( r20 , r21 )
.endif
mtspr I N T E R R U P T _ C R I T I C A L _ S E C T I O N , z e r o
/* Load tp with our per-cpu offset. */
# ifdef C O N F I G _ S M P
{
mfspr r20 , S P R _ S Y S T E M _ S A V E _ K _ 0
moveli r21 , 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 r21 , r21 , h w1 ( _ _ p e r _ c p u _ o f f s e t )
2013-08-10 20:35:02 +04:00
bfextu r20 , r20 , C P U _ S H I F T , 6 3
2012-03-27 23:40:20 +04:00
}
shl1 6 i n s l i r21 , r21 , h w0 ( _ _ p e r _ c p u _ o f f s e t )
shl3 a d d r20 , r20 , r21
ld t p , r20
# else
move t p , z e r o
# endif
2011-05-04 22:38:26 +04:00
# ifdef _ _ C O L L E C T _ L I N K E R _ F E E D B A C K _ _
/ *
* Notify t h e f e e d b a c k r o u t i n e s t h a t w e w e r e i n t h e
* appropriate f i x e d i n t e r r u p t v e c t o r a r e a . N o t e t h a t w e
* still h a v e I C S s e t a t t h i s p o i n t , s o w e c a n ' t i n v o k e a n y
* atomic o p e r a t i o n s o r w e w i l l p a n i c . T h e f e e d b a c k
* routines i n t e r n a l l y p r e s e r v e r0 . . r10 a n d r30 u p .
* /
.ifnc \ function,h a n d l e _ s y s c a l l
shli r20 , r1 , 5
.else
moveli r20 , I N T _ S W I N T _ 1 < < 5
.endif
moveli r21 , h w2 _ l a s t ( i n t v e c _ f e e d b a c k )
shl1 6 i n s l i r21 , r21 , h w1 ( i n t v e c _ f e e d b a c k )
shl1 6 i n s l i r21 , r21 , h w0 ( i n t v e c _ f e e d b a c k )
add r20 , r20 , r21
jalr r20
/* And now notify the feedback routines that we are here. */
FEEDBACK_ E N T E R ( \ f u n c t i o n )
# endif
/ *
* Prepare t h e f i r s t 2 5 6 s t a c k b y t e s t o b e r a p i d l y a c c e s s i b l e
* without h a v i n g t o f e t c h t h e b a c k g r o u n d d a t a .
* /
addi r52 , s p , - 6 4
{
wh6 4 r52
addi r52 , r52 , - 6 4
}
{
wh6 4 r52
addi r52 , r52 , - 6 4
}
{
wh6 4 r52
addi r52 , r52 , - 6 4
}
wh6 4 r52
# ifdef C O N F I G _ T R A C E _ I R Q F L A G S
.ifnc \ function,h a n d l e _ n m i
/ *
* We f i n a l l y h a v e e n o u g h s t a t e s e t u p t o n o t i f y t h e i r q
* tracing c o d e t h a t i r q s w e r e d i s a b l e d o n e n t r y t o t h e h a n d l e r .
* The T R A C E _ I R Q S _ O F F c a l l c l o b b e r s r e g i s t e r s r0 - r29 .
* For s y s c a l l s , w e a l r e a d y h a v e t h e r e g i s t e r s t a t e s a v e d a w a y
* on t h e s t a c k , s o w e d o n ' t b o t h e r t o d o a n y r e g i s t e r s a v e s h e r e ,
* and l a t e r w e p o p t h e r e g i s t e r s b a c k o f f t h e k e r n e l s t a c k .
* For i n t e r r u p t h a n d l e r s , s a v e r0 - r3 i n c a l l e e - s a v e d r e g i s t e r s .
* /
.ifnc \ function,h a n d l e _ s y s c a l l
{ move r30 , r0 ; move r31, r1 }
{ move r32 , r2 ; move r33, r3 }
.endif
TRACE_ I R Q S _ O F F
.ifnc \ function,h a n d l e _ s y s c a l l
{ move r0 , r30 ; move r1, r31 }
{ move r2 , r32 ; move r3, r33 }
.endif
.endif
# endif
.endm
/ *
* Redispatch a d o w n c a l l .
* /
.macro dc_dispatch vecnum, v e c n a m e
.org ( \ vecnum < < 8 )
intvec_ \ v e c n a m e :
2013-08-08 00:03:08 +04:00
j _ h v _ d o w n c a l l _ d i s p a t c h
2011-05-04 22:38:26 +04:00
ENDPROC( i n t v e c _ \ v e c n a m e )
.endm
/ *
* Common c o d e f o r m o s t i n t e r r u p t s . T h e C f u n c t i o n w e ' r e e v e n t u a l l y
* going t o i s i n r0 , a n d t h e f a u l t n u m i s i n r1 ; the original
* values f o r t h o s e r e g i s t e r s a r e o n t h e s t a c k .
* /
.pushsection .text .handle_interrupt , " ax"
handle_interrupt :
finish_ i n t e r r u p t _ s a v e h a n d l e _ i n t e r r u p t
/* Jump to the C routine; it should enable irqs as soon as possible. */
{
jalr r0
PTREGS_ P T R ( r0 , P T R E G S _ O F F S E T _ B A S E )
}
FEEDBACK_ R E E N T E R ( h a n d l e _ i n t e r r u p t )
{
movei r30 , 0 / * n o t a n N M I * /
j i n t e r r u p t _ r e t u r n
}
STD_ E N D P R O C ( h a n d l e _ i n t e r r u p t )
/ *
* This r o u t i n e t a k e s a b o o l e a n i n r30 i n d i c a t i n g i f t h i s i s a n N M I .
* If s o , w e a l s o e x p e c t a b o o l e a n i n r31 i n d i c a t i n g w h e t h e r t o
* re- e n a b l e t h e o p r o f i l e i n t e r r u p t s .
2012-03-31 00:29:06 +04:00
*
* Note t h a t . L r e s u m e _ u s e r s p a c e i s j u m p e d t o d i r e c t l y i n s e v e r a l
* places, a n d w e n e e d t o m a k e s u r e r30 i s s e t c o r r e c t l y i n t h o s e
* callers a s w e l l .
2011-05-04 22:38:26 +04:00
* /
STD_ E N T R Y ( i n t e r r u p t _ r e t u r n )
/* If we're resuming to kernel space, don't check thread flags. */
{
bnez r30 , . L r e s t o r e _ a l l / * N M I s d o n ' t s p e c i a l - c a s e u s e r - s p a c e * /
PTREGS_ P T R ( r29 , P T R E G S _ O F F S E T _ E X 1 )
}
ld r29 , r29
2013-09-03 22:45:52 +04:00
IS_ K E R N E L _ E X 1 ( r29 , r29 )
2011-05-04 22:38:26 +04:00
{
beqzt r29 , . L r e s u m e _ u s e r s p a c e
2013-08-07 19:36:54 +04:00
move r29 , s p
2011-05-04 22:38:26 +04:00
}
2013-08-07 19:36:54 +04:00
# ifdef C O N F I G _ P R E E M P T
/* Returning to kernel space. Check if we need preemption. */
EXTRACT_ T H R E A D _ I N F O ( r29 )
addli r28 , r29 , T H R E A D _ I N F O _ F L A G S _ O F F S E T
{
ld r28 , r28
addli r29 , r29 , T H R E A D _ I N F O _ P R E E M P T _ C O U N T _ O F F S E T
}
{
andi r28 , r28 , _ T I F _ N E E D _ R E S C H E D
ld4 s r29 , r29
}
beqzt r28 , 1 f
bnez r29 , 1 f
2013-09-26 21:22:40 +04:00
/* Disable interrupts explicitly for preemption. */
IRQ_ D I S A B L E ( r20 ,r21 )
TRACE_ I R Q S _ O F F
2013-08-07 19:36:54 +04:00
jal p r e e m p t _ s c h e d u l e _ i r q
FEEDBACK_ R E E N T E R ( i n t e r r u p t _ r e t u r n )
1 :
# endif
2011-05-04 22:38:26 +04:00
/* If we're resuming to _cpu_idle_nap, bump PC forward by 8. */
2013-08-07 19:36:54 +04:00
{
moveli r27 , h w2 _ l a s t ( _ c p u _ i d l e _ n a p )
PTREGS_ P T R ( r29 , P T R E G S _ O F F S E T _ P C )
}
2011-05-04 22:38:26 +04:00
{
ld r28 , r29
shl1 6 i n s l i r27 , r27 , h w1 ( _ c p u _ i d l e _ n a p )
}
{
shl1 6 i n s l i r27 , r27 , h w0 ( _ c p u _ i d l e _ n a p )
}
{
cmpeq r27 , r27 , r28
}
{
blbc r27 , . L r e s t o r e _ a l l
addi r28 , r28 , 8
}
st r29 , r28
j . L r e s t o r e _ a l l
.Lresume_userspace :
FEEDBACK_ R E E N T E R ( i n t e r r u p t _ r e t u r n )
arch/tile: fix up some issues in calling do_work_pending()
First, we were at risk of handling thread-info flags, in particular
do_signal(), when returning from kernel space. This could happen
after a failed kernel_execve(), or when forking a kernel thread.
The fix is to test in do_work_pending() for user_mode() and return
immediately if so; we already had this test for one of the flags,
so I just hoisted it to the top of the function.
Second, if a ptraced process updated the callee-saved registers
in the ptregs struct and then processed another thread-info flag, we
would overwrite the modifications with the original callee-saved
registers. To fix this, we add a register to note if we've already
saved the registers once, and skip doing it on additional passes
through the loop. To avoid a performance hit from the couple of
extra instructions involved, I modified the GET_THREAD_INFO() macro
to be guaranteed to be one instruction, then bundled it with adjacent
instructions, yielding an overall net savings.
Reported-By: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2012-04-29 02:51:43 +04:00
/ *
* Use r33 t o h o l d w h e t h e r w e h a v e a l r e a d y l o a d e d t h e c a l l e e - s a v e s
* into p t r e g s . W e d o n ' t w a n t t o d o i t t w i c e i n t h i s l o o p , s i n c e
* then w e ' d c l o b b e r w h a t e v e r c h a n g e s a r e m a d e b y p t r a c e , e t c .
* /
{
movei r33 , 0
move r32 , s p
}
/* Get base of stack in r32. */
EXTRACT_ T H R E A D _ I N F O ( r32 )
.Lretry_work_pending :
2011-05-04 22:38:26 +04:00
/ *
* Disable i n t e r r u p t s s o a s t o m a k e s u r e w e d o n ' t
* miss a n i n t e r r u p t t h a t s e t s a n y o f t h e t h r e a d f l a g s ( l i k e
* need_ r e s c h e d o r s i g p e n d i n g ) b e t w e e n s a m p l i n g a n d t h e i r e t .
* Routines l i k e s c h e d u l e ( ) o r d o _ s i g n a l ( ) m a y r e - e n a b l e
* interrupts b e f o r e r e t u r n i n g .
* /
IRQ_ D I S A B L E ( r20 , r21 )
TRACE_ I R Q S _ O F F / * N o t e : c l o b b e r s r e g i s t e r s r0 - r29 * /
/* Check to see if there is any work to do before returning to user. */
{
addi r29 , r32 , T H R E A D _ I N F O _ F L A G S _ O F F S E T
moveli r1 , h w1 _ l a s t ( _ T I F _ A L L W O R K _ M A S K )
}
{
ld r29 , r29
shl1 6 i n s l i r1 , r1 , h w0 ( _ T I F _ A L L W O R K _ M A S K )
}
and r1 , r29 , r1
beqzt r1 , . L r e s t o r e _ a l l
/ *
* Make s u r e w e h a v e a l l t h e r e g i s t e r s s a v e d f o r s i g n a l
arch/tile: fix up some issues in calling do_work_pending()
First, we were at risk of handling thread-info flags, in particular
do_signal(), when returning from kernel space. This could happen
after a failed kernel_execve(), or when forking a kernel thread.
The fix is to test in do_work_pending() for user_mode() and return
immediately if so; we already had this test for one of the flags,
so I just hoisted it to the top of the function.
Second, if a ptraced process updated the callee-saved registers
in the ptregs struct and then processed another thread-info flag, we
would overwrite the modifications with the original callee-saved
registers. To fix this, we add a register to note if we've already
saved the registers once, and skip doing it on additional passes
through the loop. To avoid a performance hit from the couple of
extra instructions involved, I modified the GET_THREAD_INFO() macro
to be guaranteed to be one instruction, then bundled it with adjacent
instructions, yielding an overall net savings.
Reported-By: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2012-04-29 02:51:43 +04:00
* handling o r n o t i f y - r e s u m e . C a l l o u t t o C c o d e t o f i g u r e o u t
2011-05-04 22:38:26 +04:00
* exactly w h a t w e n e e d t o d o f o r e a c h f l a g b i t , t h e n i f
* necessary, r e l o a d t h e f l a g s a n d r e c h e c k .
* /
{
PTREGS_ P T R ( r0 , P T R E G S _ O F F S E T _ B A S E )
arch/tile: fix up some issues in calling do_work_pending()
First, we were at risk of handling thread-info flags, in particular
do_signal(), when returning from kernel space. This could happen
after a failed kernel_execve(), or when forking a kernel thread.
The fix is to test in do_work_pending() for user_mode() and return
immediately if so; we already had this test for one of the flags,
so I just hoisted it to the top of the function.
Second, if a ptraced process updated the callee-saved registers
in the ptregs struct and then processed another thread-info flag, we
would overwrite the modifications with the original callee-saved
registers. To fix this, we add a register to note if we've already
saved the registers once, and skip doing it on additional passes
through the loop. To avoid a performance hit from the couple of
extra instructions involved, I modified the GET_THREAD_INFO() macro
to be guaranteed to be one instruction, then bundled it with adjacent
instructions, yielding an overall net savings.
Reported-By: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2012-04-29 02:51:43 +04:00
bnez r33 , 1 f
2011-05-04 22:38:26 +04:00
}
arch/tile: fix up some issues in calling do_work_pending()
First, we were at risk of handling thread-info flags, in particular
do_signal(), when returning from kernel space. This could happen
after a failed kernel_execve(), or when forking a kernel thread.
The fix is to test in do_work_pending() for user_mode() and return
immediately if so; we already had this test for one of the flags,
so I just hoisted it to the top of the function.
Second, if a ptraced process updated the callee-saved registers
in the ptregs struct and then processed another thread-info flag, we
would overwrite the modifications with the original callee-saved
registers. To fix this, we add a register to note if we've already
saved the registers once, and skip doing it on additional passes
through the loop. To avoid a performance hit from the couple of
extra instructions involved, I modified the GET_THREAD_INFO() macro
to be guaranteed to be one instruction, then bundled it with adjacent
instructions, yielding an overall net savings.
Reported-By: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2012-04-29 02:51:43 +04:00
push_ e x t r a _ c a l l e e _ s a v e s r0
movei r33 , 1
1 : jal d o _ w o r k _ p e n d i n g
bnez r0 , . L r e t r y _ w o r k _ p e n d i n g
2011-05-04 22:38:26 +04:00
/ *
* In t h e N M I c a s e w e
* omit t h e c a l l t o s i n g l e _ p r o c e s s _ c h e c k _ n o h z , w h i c h n o r m a l l y c h e c k s
* to s e e i f w e s h o u l d s t a r t o r s t o p t h e s c h e d u l e r t i c k , b e c a u s e
* we c a n ' t c a l l a r b i t r a r y L i n u x c o d e f r o m a n N M I c o n t e x t .
* We a l w a y s c a l l t h e h o m e c a c h e T L B d e f e r r a l c o d e t o r e - t r i g g e r
* the d e f e r r a l m e c h a n i s m .
*
* The o t h e r c h u n k o f r e s p o n s i b i l i t y t h i s c o d e h a s i s t o r e s e t t h e
* interrupt m a s k s a p p r o p r i a t e l y t o r e s e t i r q s a n d N M I s . W e h a v e
* to c a l l T R A C E _ I R Q S _ O F F a n d T R A C E _ I R Q S _ O N t o s u p p o r t a l l t h e
* lockdep- t y p e s t u f f , b u t w e c a n ' t s e t I C S u n t i l a f t e r w a r d s , s i n c e
* ICS c a n o n l y b e u s e d i n v e r y t i g h t c h u n k s o f c o d e t o a v o i d
* tripping o v e r v a r i o u s a s s e r t i o n s t h a t i t i s o f f .
* /
.Lrestore_all :
PTREGS_ P T R ( r0 , P T R E G S _ O F F S E T _ E X 1 )
{
ld r0 , r0
PTREGS_ P T R ( r32 , P T R E G S _ O F F S E T _ F L A G S )
}
{
2013-09-03 22:45:52 +04:00
IS_ K E R N E L _ E X 1 ( r0 , r0 )
2011-05-04 22:38:26 +04:00
ld r32 , r32
}
bnez r0 , 1 f
j 2 f
# if P T _ F L A G S _ D I S A B L E _ I R Q ! = 1
# error A s s u m i n g P T _ F L A G S _ D I S A B L E _ I R Q = = 1 s o w e c a n u s e b l b c t b e l o w
# endif
1 : blbct r32 , 2 f
IRQ_ D I S A B L E ( r20 ,r21 )
TRACE_ I R Q S _ O F F
movei r0 , 1
mtspr I N T E R R U P T _ C R I T I C A L _ S E C T I O N , r0
beqzt r30 , . L r e s t o r e _ r e g s
j 3 f
2 : TRACE_ I R Q S _ O N
2012-03-27 23:40:20 +04:00
IRQ_ E N A B L E _ L O A D ( r20 , r21 )
2011-05-04 22:38:26 +04:00
movei r0 , 1
mtspr I N T E R R U P T _ C R I T I C A L _ S E C T I O N , r0
2012-03-27 23:40:20 +04:00
IRQ_ E N A B L E _ A P P L Y ( r20 , r21 )
2011-05-04 22:38:26 +04:00
beqzt r30 , . L r e s t o r e _ r e g s
3 :
2014-01-27 12:25:28 +04:00
# if I N T _ P E R F _ C O U N T + 1 ! = I N T _ A U X _ P E R F _ C O U N T
# error B a d i n t e r r u p t a s s u m p t i o n
# endif
{
movei r0 , 3 / * t w o a d j a c e n t b i t s f o r t h e P E R F _ C O U N T m a s k * /
beqz r31 , . L r e s t o r e _ r e g s
}
shli r0 , r0 , I N T _ P E R F _ C O U N T
mtspr S P R _ I N T E R R U P T _ M A S K _ R E S E T _ K , r0
2011-05-04 22:38:26 +04:00
/ *
* We n o w c o m m i t t o r e t u r n i n g f r o m t h i s i n t e r r u p t , s i n c e w e w i l l b e
* doing t h i n g s l i k e s e t t i n g E X _ C O N T E X T S P R s a n d u n w i n d i n g t h e s t a c k
* frame. N o c a l l s s h o u l d b e m a d e t o a n y o t h e r c o d e a f t e r t h i s p o i n t .
* This c o d e s h o u l d o n l y b e e n t e r e d w i t h I C S s e t .
* r3 2 m u s t s t i l l b e s e t t o p t r e g s . f l a g s .
* We l a u n c h l o a d s t o e a c h c a c h e l i n e s e p a r a t e l y f i r s t , s o w e c a n
* get s o m e p a r a l l e l i s m o u t o f t h e m e m o r y s u b s y s t e m .
* We s t a r t z e r o i n g c a l l e r - s a v e d r e g i s t e r s t h r o u g h o u t , s i n c e
* that w i l l s a v e s o m e c y c l e s i f t h i s t u r n s o u t t o b e a s y s c a l l .
* /
.Lrestore_regs :
/ *
* Rotate s o w e h a v e o n e h i g h b i t a n d o n e l o w b i t t o t e s t .
* - low b i t s a y s w h e t h e r t o r e s t o r e a l l t h e c a l l e e - s a v e d r e g i s t e r s ,
* or j u s t r30 - r33 , a n d r52 u p .
* - high b i t ( i . e . s i g n b i t ) s a y s w h e t h e r t o r e s t o r e a l l t h e
* caller- s a v e d r e g i s t e r s , o r j u s t r0 .
* /
# if P T _ F L A G S _ C A L L E R _ S A V E S ! = 2 | | P T _ F L A G S _ R E S T O R E _ R E G S ! = 4
# error R o t a t e t r i c k d o e s n o t w o r k : - )
# endif
{
rotli r20 , r32 , 6 2
PTREGS_ P T R ( s p , P T R E G S _ O F F S E T _ R E G ( 0 ) )
}
/ *
* Load c a c h e l i n e s 0 , 4 , 6 a n d 7 , i n t h a t o r d e r , t h e n u s e
* the l a s t l o a d e d v a l u e , w h i c h m a k e s i t l i k e l y t h a t t h e o t h e r
* cache l i n e s h a v e a l s o l o a d e d , a t w h i c h p o i n t w e s h o u l d b e
* able t o s a f e l y r e a d a l l t h e r e m a i n i n g w o r d s o n t h o s e c a c h e
* lines w i t h o u t w a i t i n g f o r t h e m e m o r y s u b s y s t e m .
* /
pop_ r e g r0 , s p , P T R E G S _ O F F S E T _ R E G ( 3 0 ) - P T R E G S _ O F F S E T _ R E G ( 0 )
pop_ r e g r30 , s p , P T R E G S _ O F F S E T _ R E G ( 5 2 ) - P T R E G S _ O F F S E T _ R E G ( 3 0 )
pop_ r e g _ z e r o r52 , r3 , s p , P T R E G S _ O F F S E T _ C M P E X C H - P T R E G S _ O F F S E T _ R E G ( 5 2 )
pop_ r e g _ z e r o r21 , r27 , s p , P T R E G S _ O F F S E T _ E X 1 - P T R E G S _ O F F S E T _ C M P E X C H
pop_ r e g _ z e r o l r , r2 , s p , P T R E G S _ O F F S E T _ P C - P T R E G S _ O F F S E T _ E X 1
{
mtspr C M P E X C H _ V A L U E , r21
move r4 , z e r o
}
pop_ r e g r21 , s p , P T R E G S _ O F F S E T _ R E G ( 3 1 ) - P T R E G S _ O F F S E T _ P C
{
mtspr S P R _ E X _ C O N T E X T _ K _ 1 , l r
2013-09-03 22:45:52 +04:00
IS_ K E R N E L _ E X 1 ( l r , l r )
2011-05-04 22:38:26 +04:00
}
{
mtspr S P R _ E X _ C O N T E X T _ K _ 0 , r21
move r5 , z e r o
}
/* Restore callee-saveds that we actually use. */
pop_ r e g _ z e r o r31 , r6
pop_ r e g _ z e r o r32 , r7
pop_ r e g _ z e r o r33 , r8 , s p , P T R E G S _ O F F S E T _ R E G ( 2 9 ) - P T R E G S _ O F F S E T _ R E G ( 3 3 )
/ *
* If w e m o d i f i e d o t h e r c a l l e e - s a v e d s , r e s t o r e t h e m n o w .
* This i s r a r e , b u t c o u l d b e v i a p t r a c e o r s i g n a l h a n d l e r .
* /
{
move r9 , z e r o
blbs r20 , . L r e s t o r e _ c a l l e e s
}
.Lcontinue_restore_regs :
/* Check if we're returning from a syscall. */
{
move r10 , z e r o
bltzt r20 , 1 f / * n o , s o g o r e s t o r e c a l l e e - s a v e r e g i s t e r s * /
}
/ *
* Check i f w e ' r e r e t u r n i n g t o u s e r s p a c e .
* Note t h a t i f w e ' r e n o t , w e d o n ' t w o r r y a b o u t z e r o i n g e v e r y t h i n g .
* /
{
addli s p , s p , P T R E G S _ O F F S E T _ L R - P T R E G S _ O F F S E T _ R E G ( 2 9 )
bnez l r , . L k e r n e l _ r e t u r n
}
/ *
* On r e t u r n f r o m s y s c a l l , w e ' v e r e s t o r e d r0 f r o m p t _ r e g s , b u t w e
* clear t h e r e m a i n d e r o f t h e c a l l e r - s a v e d r e g i s t e r s . W e c o u l d
* restore t h e s y s c a l l a r g u m e n t s , b u t t h e r e ' s n o t m u c h p o i n t ,
* and i t e n s u r e s u s e r p r o g r a m s a r e n ' t t r y i n g t o u s e t h e
* caller- s a v e s i f w e c l e a r t h e m , a s w e l l a s a v o i d i n g l e a k i n g
* kernel p o i n t e r s i n t o u s e r s p a c e .
* /
pop_ r e g _ z e r o l r , r11 , s p , P T R E G S _ O F F S E T _ T P - P T R E G S _ O F F S E T _ L R
pop_ r e g _ z e r o t p , r12 , s p , P T R E G S _ O F F S E T _ S P - P T R E G S _ O F F S E T _ T P
{
ld s p , s p
move r13 , z e r o
move r14 , z e r o
}
{ move r15 , z e r o ; move r16, zero }
{ move r17 , z e r o ; move r18, zero }
{ move r19 , z e r o ; move r20, zero }
{ move r21 , z e r o ; move r22, zero }
{ move r23 , z e r o ; move r24, zero }
{ move r25 , z e r o ; move r26, zero }
/* Set r1 to errno if we are returning an error, otherwise zero. */
{
moveli r29 , 4 0 9 6
sub r1 , z e r o , r0
}
{
move r28 , z e r o
cmpltu r29 , r1 , r29
}
{
mnz r1 , r29 , r1
move r29 , z e r o
}
iret
/ *
* Not a s y s c a l l , s o r e s t o r e c a l l e r - s a v e d r e g i s t e r s .
* First k i c k o f f l o a d s f o r c a c h e l i n e s 1 - 3 , w h i c h w e ' r e t o u c h i n g
* for t h e f i r s t t i m e h e r e .
* /
.align 64
1 : pop_ r e g r29 , s p , P T R E G S _ O F F S E T _ R E G ( 2 1 ) - P T R E G S _ O F F S E T _ R E G ( 2 9 )
pop_ r e g r21 , s p , P T R E G S _ O F F S E T _ R E G ( 1 3 ) - P T R E G S _ O F F S E T _ R E G ( 2 1 )
pop_ r e g r13 , s p , P T R E G S _ O F F S E T _ R E G ( 1 ) - P T R E G S _ O F F S E T _ R E G ( 1 3 )
pop_ r e g r1
pop_ r e g r2
pop_ r e g r3
pop_ r e g r4
pop_ r e g r5
pop_ r e g r6
pop_ r e g r7
pop_ r e g r8
pop_ r e g r9
pop_ r e g r10
pop_ r e g r11
pop_ r e g r12 , s p , 1 6
/* r13 already restored above */
pop_ r e g r14
pop_ r e g r15
pop_ r e g r16
pop_ r e g r17
pop_ r e g r18
pop_ r e g r19
pop_ r e g r20 , s p , 1 6
/* r21 already restored above */
pop_ r e g r22
pop_ r e g r23
pop_ r e g r24
pop_ r e g r25
pop_ r e g r26
pop_ r e g r27
pop_ r e g r28 , s p , P T R E G S _ O F F S E T _ L R - P T R E G S _ O F F S E T _ R E G ( 2 8 )
/* r29 already restored above */
bnez l r , . L k e r n e l _ r e t u r n
pop_ r e g l r , s p , P T R E G S _ O F F S E T _ T P - P T R E G S _ O F F S E T _ L R
pop_ r e g t p , s p , P T R E G S _ O F F S E T _ S P - P T R E G S _ O F F S E T _ T P
ld s p , s p
iret
/ *
* We c a n ' t r e s t o r e t p w h e n i n k e r n e l m o d e , s i n c e a t h r e a d m i g h t
* have m i g r a t e d f r o m a n o t h e r c p u a n d b r o u g h t a s t a l e t p v a l u e .
* /
.Lkernel_return :
pop_ r e g l r , s p , P T R E G S _ O F F S E T _ S P - P T R E G S _ O F F S E T _ L R
ld s p , s p
iret
/* Restore callee-saved registers from r34 to r51. */
.Lrestore_callees :
addli s p , s p , P T R E G S _ O F F S E T _ R E G ( 3 4 ) - P T R E G S _ O F F S E T _ R E G ( 2 9 )
pop_ r e g r34
pop_ r e g r35
pop_ r e g r36
pop_ r e g r37
pop_ r e g r38
pop_ r e g r39
pop_ r e g r40
pop_ r e g r41
pop_ r e g r42
pop_ r e g r43
pop_ r e g r44
pop_ r e g r45
pop_ r e g r46
pop_ r e g r47
pop_ r e g r48
pop_ r e g r49
pop_ r e g r50
pop_ r e g r51 , s p , P T R E G S _ O F F S E T _ R E G ( 2 9 ) - P T R E G S _ O F F S E T _ R E G ( 5 1 )
j . L c o n t i n u e _ r e s t o r e _ r e g s
STD_ E N D P R O C ( i n t e r r u p t _ r e t u r n )
/ *
* " NMI" i n t e r r u p t s m a s k A L L i n t e r r u p t s b e f o r e c a l l i n g t h e
* handler, a n d d o n ' t c h e c k t h r e a d f l a g s , e t c . , o n t h e w a y
* back o u t . I n g e n e r a l , t h e o n l y t h i n g s w e d o h e r e f o r N M I s
* are r e g i s t e r s a v e / r e s t o r e a n d d a t a p l a n e k e r n e l - T L B m a n a g e m e n t .
* We d o n ' t ( f o r e x a m p l e ) d e a l w i t h s t a r t / s t o p o f t h e s c h e d t i c k .
* /
.pushsection .text .handle_nmi , " ax"
handle_nmi :
finish_ i n t e r r u p t _ s a v e h a n d l e _ n m i
{
jalr r0
PTREGS_ P T R ( r0 , P T R E G S _ O F F S E T _ B A S E )
}
FEEDBACK_ R E E N T E R ( h a n d l e _ n m i )
{
movei r30 , 1
2014-01-27 12:25:28 +04:00
cmpeq r31 , r0 , z e r o
2011-05-04 22:38:26 +04:00
}
j i n t e r r u p t _ r e t u r n
STD_ E N D P R O C ( h a n d l e _ n m i )
/ *
* Parallel c o d e f o r s y s c a l l s t o h a n d l e _ i n t e r r u p t .
* /
.pushsection .text .handle_syscall , " ax"
handle_syscall :
finish_ i n t e r r u p t _ s a v e h a n d l e _ s y s c a l l
/* Enable irqs. */
TRACE_ I R Q S _ O N
IRQ_ E N A B L E ( r20 , r21 )
/* Bump the counter for syscalls made on this tile. */
moveli r20 , h w2 _ l a s t ( i r q _ s t a t + I R Q _ C P U S T A T _ S Y S C A L L _ C O U N T _ O F F S E T )
shl1 6 i n s l i r20 , r20 , h w1 ( i r q _ s t a t + I R Q _ C P U S T A T _ S Y S C A L L _ C O U N T _ O F F S E T )
shl1 6 i n s l i r20 , r20 , h w0 ( i r q _ s t a t + I R Q _ C P U S T A T _ S Y S C A L L _ C O U N T _ O F F S E T )
add r20 , r20 , t p
ld4 s r21 , r20
arch/tile: fix up some issues in calling do_work_pending()
First, we were at risk of handling thread-info flags, in particular
do_signal(), when returning from kernel space. This could happen
after a failed kernel_execve(), or when forking a kernel thread.
The fix is to test in do_work_pending() for user_mode() and return
immediately if so; we already had this test for one of the flags,
so I just hoisted it to the top of the function.
Second, if a ptraced process updated the callee-saved registers
in the ptregs struct and then processed another thread-info flag, we
would overwrite the modifications with the original callee-saved
registers. To fix this, we add a register to note if we've already
saved the registers once, and skip doing it on additional passes
through the loop. To avoid a performance hit from the couple of
extra instructions involved, I modified the GET_THREAD_INFO() macro
to be guaranteed to be one instruction, then bundled it with adjacent
instructions, yielding an overall net savings.
Reported-By: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2012-04-29 02:51:43 +04:00
{
addi r21 , r21 , 1
move r31 , s p
}
{
st4 r20 , r21
EXTRACT_ T H R E A D _ I N F O ( r31 )
}
2011-05-04 22:38:26 +04:00
/* Trace syscalls, if requested. */
addi r31 , r31 , T H R E A D _ I N F O _ F L A G S _ O F F S E T
2013-01-22 04:54:57 +04:00
{
ld r30 , r31
moveli r32 , _ T I F _ S Y S C A L L _ E N T R Y _ W O R K
}
and r30 , r30 , r32
2011-05-04 22:38:26 +04:00
{
addi r30 , r31 , T H R E A D _ I N F O _ S T A T U S _ O F F S E T - T H R E A D _ I N F O _ F L A G S _ O F F S E T
beqzt r30 , . L r e s t o r e _ s y s c a l l _ r e g s
}
2012-12-22 09:21:10 +04:00
{
PTREGS_ P T R ( r0 , P T R E G S _ O F F S E T _ B A S E )
jal d o _ s y s c a l l _ t r a c e _ e n t e r
}
2011-05-04 22:38:26 +04:00
FEEDBACK_ R E E N T E R ( h a n d l e _ s y s c a l l )
/ *
* We a l w a y s r e l o a d o u r r e g i s t e r s f r o m t h e s t a c k a t t h i s
* point. T h e y m i g h t b e v a l i d , i f w e d i d n ' t b u i l d w i t h
* TRACE_ I R Q F L A G S , a n d t h i s i s n ' t a d a t a p l a n e t i l e , a n d w e ' r e n o t
* doing s y s c a l l t r a c i n g , b u t t h e r e a r e e n o u g h c a s e s n o w t h a t i t
* seems s i m p l e s t j u s t t o d o t h e r e l o a d u n c o n d i t i o n a l l y .
* /
.Lrestore_syscall_regs :
{
ld r30 , r30
PTREGS_ P T R ( r11 , P T R E G S _ O F F S E T _ R E G ( 0 ) )
}
pop_ r e g r0 , r11
pop_ r e g r1 , r11
pop_ r e g r2 , r11
pop_ r e g r3 , r11
pop_ r e g r4 , r11
pop_ r e g r5 , r11 , P T R E G S _ O F F S E T _ S Y S C A L L - P T R E G S _ O F F S E T _ R E G ( 5 )
{
ld T R E G _ S Y S C A L L _ N R _ N A M E , r11
moveli r21 , _ _ N R _ s y s c a l l s
}
/* Ensure that the syscall number is within the legal range. */
{
moveli r20 , h w2 ( s y s _ c a l l _ t a b l e )
2013-02-02 00:31:25 +04:00
# ifdef C O N F I G _ C O M P A T
2011-05-04 22:38:26 +04:00
blbs r30 , . L c o m p a t _ s y s c a l l
2013-02-02 00:31:25 +04:00
# endif
2011-05-04 22:38:26 +04:00
}
{
cmpltu r21 , T R E G _ S Y S C A L L _ N R _ N A M E , r21
shl1 6 i n s l i r20 , r20 , h w1 ( s y s _ c a l l _ t a b l e )
}
{
blbc r21 , . L i n v a l i d _ s y s c a l l
shl1 6 i n s l i r20 , r20 , h w0 ( s y s _ c a l l _ t a b l e )
}
.Lload_syscall_pointer :
shl3 a d d r20 , T R E G _ S Y S C A L L _ N R _ N A M E , r20
ld r20 , r20
/* Jump to syscall handler. */
jalr r20
.Lhandle_syscall_link : /* value of "lr" after "jalr r20" above */
/ *
* Write o u r r0 o n t o t h e s t a c k s o i t g e t s r e s t o r e d i n s t e a d
* of w h a t e v e r t h e u s e r h a d t h e r e b e f o r e .
* In c o m p a t m o d e , s i g n - e x t e n d r0 b e f o r e s t o r i n g i t .
* /
{
PTREGS_ P T R ( r29 , P T R E G S _ O F F S E T _ R E G ( 0 ) )
blbct r30 , 1 f
}
addxi r0 , r0 , 0
1 : st r29 , r0
.Lsyscall_sigreturn_skip :
FEEDBACK_ R E E N T E R ( h a n d l e _ s y s c a l l )
/* Do syscall trace again, if requested. */
2013-01-22 04:54:57 +04:00
{
ld r30 , r31
moveli r32 , _ T I F _ S Y S C A L L _ E X I T _ W O R K
}
and r0 , r30 , r32
2012-03-30 00:11:09 +04:00
{
andi r0 , r30 , _ T I F _ S I N G L E S T E P
beqzt r0 , 1 f
}
2012-12-22 09:21:10 +04:00
{
PTREGS_ P T R ( r0 , P T R E G S _ O F F S E T _ B A S E )
jal d o _ s y s c a l l _ t r a c e _ e x i t
}
2011-05-04 22:38:26 +04:00
FEEDBACK_ R E E N T E R ( h a n d l e _ s y s c a l l )
2012-03-30 00:11:09 +04:00
andi r0 , r30 , _ T I F _ S I N G L E S T E P
1 : beqzt r0 , 2 f
/* Single stepping -- notify ptrace. */
{
movei r0 , S I G T R A P
jal p t r a c e _ n o t i f y
}
FEEDBACK_ R E E N T E R ( h a n d l e _ s y s c a l l )
2012-03-31 00:29:06 +04:00
2 : {
movei r30 , 0 / * n o t a n N M I * /
j . L r e s u m e _ u s e r s p a c e / * j u m p i n t o m i d d l e o f i n t e r r u p t _ r e t u r n * /
}
2011-05-04 22:38:26 +04:00
2013-02-02 00:31:25 +04:00
# ifdef C O N F I G _ C O M P A T
2011-05-04 22:38:26 +04:00
.Lcompat_syscall :
/ *
* Load t h e b a s e o f t h e c o m p a t s y s c a l l t a b l e i n r20 , a n d
* range- c h e c k t h e s y s c a l l n u m b e r ( d u p l i c a t e d f r o m 6 4 - b i t p a t h ) .
* Sign- e x t e n d a l l t h e u s e r ' s p a s s e d a r g u m e n t s t o m a k e t h e m c o n s i s t e n t .
* Also s a v e t h e o r i g i n a l " r ( n ) " v a l u e s a w a y i n " r ( 1 1 + n ) " i n
* case t h e s y s c a l l t a b l e e n t r y w a n t s t o v a l i d a t e t h e m .
* /
moveli r20 , h w2 ( c o m p a t _ s y s _ c a l l _ t a b l e )
{
cmpltu r21 , T R E G _ S Y S C A L L _ N R _ N A M E , r21
shl1 6 i n s l i r20 , r20 , h w1 ( c o m p a t _ s y s _ c a l l _ t a b l e )
}
{
blbc r21 , . L i n v a l i d _ s y s c a l l
shl1 6 i n s l i r20 , r20 , h w0 ( c o m p a t _ s y s _ c a l l _ t a b l e )
}
{ move r11 , r0 ; addxi r0, r0, 0 }
{ move r12 , r1 ; addxi r1, r1, 0 }
{ move r13 , r2 ; addxi r2, r2, 0 }
{ move r14 , r3 ; addxi r3, r3, 0 }
{ move r15 , r4 ; addxi r4, r4, 0 }
{ move r16 , r5 ; addxi r5, r5, 0 }
j . L l o a d _ s y s c a l l _ p o i n t e r
2013-02-02 00:31:25 +04:00
# endif
2011-05-04 22:38:26 +04:00
.Linvalid_syscall :
/* Report an invalid syscall back to the user program */
{
PTREGS_ P T R ( r29 , P T R E G S _ O F F S E T _ R E G ( 0 ) )
movei r28 , - E N O S Y S
}
st r29 , r28
2012-03-31 00:29:06 +04:00
{
movei r30 , 0 / * n o t a n N M I * /
j . L r e s u m e _ u s e r s p a c e / * j u m p i n t o m i d d l e o f i n t e r r u p t _ r e t u r n * /
}
2011-05-04 22:38:26 +04:00
STD_ E N D P R O C ( h a n d l e _ s y s c a l l )
/* Return the address for oprofile to suppress in backtraces. */
STD_ E N T R Y _ S E C T I O N ( h a n d l e _ s y s c a l l _ l i n k _ a d d r e s s , . t e x t . h a n d l e _ s y s c a l l )
lnk r0
{
addli r0 , r0 , . L h a n d l e _ s y s c a l l _ l i n k - .
jrp l r
}
STD_ E N D P R O C ( h a n d l e _ s y s c a l l _ l i n k _ a d d r e s s )
STD_ E N T R Y ( r e t _ f r o m _ f o r k )
jal s i m _ n o t i f y _ f o r k
jal s c h e d u l e _ t a i l
FEEDBACK_ R E E N T E R ( r e t _ f r o m _ f o r k )
2012-03-31 00:29:06 +04:00
{
movei r30 , 0 / * n o t a n N M I * /
j . L r e s u m e _ u s e r s p a c e / * j u m p i n t o m i d d l e o f i n t e r r u p t _ r e t u r n * /
}
2011-05-04 22:38:26 +04:00
STD_ E N D P R O C ( r e t _ f r o m _ f o r k )
2012-10-20 00:25:12 +04:00
STD_ E N T R Y ( r e t _ f r o m _ k e r n e l _ t h r e a d )
jal s i m _ n o t i f y _ f o r k
jal s c h e d u l e _ t a i l
FEEDBACK_ R E E N T E R ( r e t _ f r o m _ f o r k )
{
move r0 , r31
jalr r30
}
FEEDBACK_ R E E N T E R ( r e t _ f r o m _ k e r n e l _ t h r e a d )
{
movei r30 , 0 / * n o t a n N M I * /
j . L r e s u m e _ u s e r s p a c e / * j u m p i n t o m i d d l e o f i n t e r r u p t _ r e t u r n * /
}
STD_ E N D P R O C ( r e t _ f r o m _ k e r n e l _ t h r e a d )
2011-05-04 22:38:26 +04:00
/* Various stub interrupt handlers and syscall handlers */
STD_ E N T R Y _ L O C A L ( _ k e r n e l _ d o u b l e _ f a u l t )
mfspr r1 , S P R _ E X _ C O N T E X T _ K _ 0
move r2 , l r
move r3 , s p
move r4 , r52
addi s p , s p , - C _ A B I _ S A V E _ A R E A _ S I Z E
j k e r n e l _ d o u b l e _ f a u l t
STD_ E N D P R O C ( _ k e r n e l _ d o u b l e _ f a u l t )
STD_ E N T R Y _ L O C A L ( b a d _ i n t r )
mfspr r2 , S P R _ E X _ C O N T E X T _ K _ 0
panic " U n h a n d l e d i n t e r r u p t % #x : P C % # l x "
STD_ E N D P R O C ( b a d _ i n t r )
/ *
* Special- c a s e s i g r e t u r n t o n o t w r i t e r0 t o t h e s t a c k o n r e t u r n .
* This i s t e c h n i c a l l y m o r e e f f i c i e n t , b u t i t a l s o a v o i d s d i f f i c u l t i e s
* in t h e 6 4 - b i t O S w h e n h a n d l i n g 3 2 - b i t c o m p a t c o d e , s i n c e w e m u s t n o t
* sign- e x t e n d r0 f o r t h e s i g r e t u r n r e t u r n - v a l u e c a s e .
* /
# define P T R E G S _ S Y S C A L L _ S I G R E T U R N ( x , r e g ) \
STD_ E N T R Y ( _ ## x ) ; \
addli l r , l r , . L s y s c a l l _ s i g r e t u r n _ s k i p - . L h a n d l e _ s y s c a l l _ l i n k ; \
{ \
PTREGS_ P T R ( r e g , P T R E G S _ O F F S E T _ B A S E ) ; \
j x \
} ; \
STD_ E N D P R O C ( _ ## x )
PTREGS_ S Y S C A L L _ S I G R E T U R N ( s y s _ r t _ s i g r e t u r n , r0 )
# ifdef C O N F I G _ C O M P A T
PTREGS_ S Y S C A L L _ S I G R E T U R N ( c o m p a t _ s y s _ r t _ s i g r e t u r n , r0 )
# endif
2012-10-23 21:30:54 +04:00
/* Save additional callee-saves to pt_regs and jump to standard function. */
2011-05-04 22:38:26 +04:00
STD_ E N T R Y ( _ s y s _ c l o n e )
push_ e x t r a _ c a l l e e _ s a v e s r4
j s y s _ c l o n e
STD_ E N D P R O C ( _ s y s _ c l o n e )
2013-08-07 00:04:13 +04:00
/ *
* Recover r3 , r2 , r1 a n d r0 h e r e s a v e d b y u n a l i g n f a s t v e c t o r .
* The v e c t o r a r e a l i m i t i s 3 2 b u n d l e s , s o w e h a n d l e t h e r e l o a d h e r e .
* r0 , r1 , r2 a r e i n t h r e a d _ i n f o f r o m l o w t o h i g h m e m o r y i n o r d e r .
* r3 p o i n t s t o l o c a t i o n t h e o r i g i n a l r3 w a s s a v e d .
* We p u t t h i s c o d e i n t h e _ _ H E A D s e c t i o n s o i t c a n b e r e a c h e d
* via a c o n d i t i o n a l b r a n c h f r o m t h e f a s t p a t h .
* /
_ _ HEAD
hand_unalign_slow :
andi s p , s p , ~ 1
hand_unalign_slow_badsp :
addi r3 , r3 , - ( 3 * 8 )
ld_ a d d r0 , r3 , 8
ld_ a d d r1 , r3 , 8
ld r2 , r3
hand_unalign_slow_nonuser :
mfspr r3 , S P R _ S Y S T E M _ S A V E _ K _ 1
_ _ int_ h a n d I N T _ U N A L I G N _ D A T A , U N A L I G N _ D A T A _ S L O W , i n t _ u n a l i g n
/* The unaligned data support needs to read all the registers. */
2011-05-04 22:38:26 +04:00
int_unalign :
push_ e x t r a _ c a l l e e _ s a v e s r0
2013-08-07 00:04:13 +04:00
j d o _ u n a l i g n e d
ENDPROC( h a n d _ u n a l i g n _ s l o w )
2011-05-04 22:38:26 +04:00
2012-03-29 22:52:00 +04:00
/* Fill the return address stack with nonzero entries. */
STD_ E N T R Y ( f i l l _ r a _ s t a c k )
{
move r0 , l r
jal 1 f
}
1 : jal 2 f
2 : jal 3 f
3 : jal 4 f
4 : jrp r0
STD_ E N D P R O C ( f i l l _ r a _ s t a c k )
2013-08-07 00:04:13 +04:00
.macro int_hand vecnum, v e c n a m e , c _ r o u t i n e , p r o c e s s i n g =handle_interrupt
.org ( \ vecnum < < 8 )
_ _ int_ h a n d \ v e c n u m , \ v e c n a m e , \ c _ r o u t i n e , \ p r o c e s s i n g
.endm
2013-09-03 22:41:36 +04:00
/* Include .intrpt array of interrupt vectors */
.section " .intrpt " , " ax"
.global intrpt_start
intrpt_start :
2011-05-04 22:38:26 +04:00
2014-01-27 11:11:07 +04:00
# ifndef C O N F I G _ U S E _ P M C
# define h a n d l e _ p e r f _ i n t e r r u p t b a d _ i n t r
# endif
2011-05-04 22:38:26 +04:00
# ifndef C O N F I G _ H A R D W A L L
# define d o _ h a r d w a l l _ t r a p b a d _ i n t r
# endif
2012-03-29 23:23:54 +04:00
int_ h a n d I N T _ M E M _ E R R O R , M E M _ E R R O R , d o _ t r a p
2011-05-04 22:38:26 +04:00
int_ h a n d I N T _ S I N G L E _ S T E P _ 3 , S I N G L E _ S T E P _ 3 , b a d _ i n t r
# if C O N F I G _ K E R N E L _ P L = = 2
int_ h a n d I N T _ S I N G L E _ S T E P _ 2 , S I N G L E _ S T E P _ 2 , g x _ s i n g l e s t e p _ h a n d l e
int_ h a n d I N T _ S I N G L E _ S T E P _ 1 , S I N G L E _ S T E P _ 1 , b a d _ i n t r
# else
int_ h a n d I N T _ S I N G L E _ S T E P _ 2 , S I N G L E _ S T E P _ 2 , b a d _ i n t r
int_ h a n d I N T _ S I N G L E _ S T E P _ 1 , S I N G L E _ S T E P _ 1 , g x _ s i n g l e s t e p _ h a n d l e
# endif
int_ h a n d I N T _ S I N G L E _ S T E P _ 0 , S I N G L E _ S T E P _ 0 , b a d _ i n t r
int_ h a n d I N T _ I D N _ C O M P L E T E , I D N _ C O M P L E T E , b a d _ i n t r
int_ h a n d I N T _ U D N _ C O M P L E T E , U D N _ C O M P L E T E , b a d _ i n t r
int_ h a n d I N T _ I T L B _ M I S S , I T L B _ M I S S , d o _ p a g e _ f a u l t
int_ h a n d I N T _ I L L , I L L , d o _ t r a p
int_ h a n d I N T _ G P V , G P V , d o _ t r a p
int_ h a n d I N T _ I D N _ A C C E S S , I D N _ A C C E S S , d o _ t r a p
int_ h a n d I N T _ U D N _ A C C E S S , U D N _ A C C E S S , d o _ t r a p
int_ h a n d I N T _ S W I N T _ 3 , S W I N T _ 3 , d o _ t r a p
int_ h a n d I N T _ S W I N T _ 2 , S W I N T _ 2 , d o _ t r a p
int_ h a n d I N T _ S W I N T _ 1 , S W I N T _ 1 , S Y S C A L L , h a n d l e _ s y s c a l l
int_ h a n d I N T _ S W I N T _ 0 , S W I N T _ 0 , d o _ t r a p
int_ h a n d I N T _ I L L _ T R A N S , I L L _ T R A N S , d o _ t r a p
2013-08-07 00:04:13 +04:00
int_ h a n d _ u n a l i g n _ f a s t I N T _ U N A L I G N _ D A T A , U N A L I G N _ D A T A
2011-05-04 22:38:26 +04:00
int_ h a n d I N T _ D T L B _ M I S S , D T L B _ M I S S , d o _ p a g e _ f a u l t
int_ h a n d I N T _ D T L B _ A C C E S S , D T L B _ A C C E S S , d o _ p a g e _ f a u l t
2012-03-31 00:01:48 +04:00
int_ h a n d I N T _ I D N _ F I R E W A L L , I D N _ F I R E W A L L , d o _ h a r d w a l l _ t r a p
2011-05-04 22:38:26 +04:00
int_ h a n d I N T _ U D N _ F I R E W A L L , U D N _ F I R E W A L L , d o _ h a r d w a l l _ t r a p
int_ h a n d I N T _ T I L E _ T I M E R , T I L E _ T I M E R , d o _ t i m e r _ i n t e r r u p t
int_ h a n d I N T _ I D N _ T I M E R , I D N _ T I M E R , b a d _ i n t r
int_ h a n d I N T _ U D N _ T I M E R , U D N _ T I M E R , b a d _ i n t r
int_ h a n d I N T _ I D N _ A V A I L , I D N _ A V A I L , b a d _ i n t r
int_ h a n d I N T _ U D N _ A V A I L , U D N _ A V A I L , b a d _ i n t r
int_ h a n d I N T _ I P I _ 3 , I P I _ 3 , b a d _ i n t r
# if C O N F I G _ K E R N E L _ P L = = 2
int_ h a n d I N T _ I P I _ 2 , I P I _ 2 , t i l e _ d e v _ i n t r
int_ h a n d I N T _ I P I _ 1 , I P I _ 1 , b a d _ i n t r
# else
int_ h a n d I N T _ I P I _ 2 , I P I _ 2 , b a d _ i n t r
int_ h a n d I N T _ I P I _ 1 , I P I _ 1 , t i l e _ d e v _ i n t r
# endif
int_ h a n d I N T _ I P I _ 0 , I P I _ 0 , b a d _ i n t r
int_ h a n d I N T _ P E R F _ C O U N T , P E R F _ C O U N T , \
2014-01-27 11:11:07 +04:00
handle_ p e r f _ i n t e r r u p t , h a n d l e _ n m i
2011-05-04 22:38:26 +04:00
int_ h a n d I N T _ A U X _ P E R F _ C O U N T , A U X _ P E R F _ C O U N T , \
2014-01-27 11:11:07 +04:00
handle_ p e r f _ i n t e r r u p t , h a n d l e _ n m i
2011-05-04 22:38:26 +04:00
int_ h a n d I N T _ I N T C T R L _ 3 , I N T C T R L _ 3 , b a d _ i n t r
# if C O N F I G _ K E R N E L _ P L = = 2
dc_ d i s p a t c h I N T _ I N T C T R L _ 2 , I N T C T R L _ 2
int_ h a n d I N T _ I N T C T R L _ 1 , I N T C T R L _ 1 , b a d _ i n t r
# else
int_ h a n d I N T _ I N T C T R L _ 2 , I N T C T R L _ 2 , b a d _ i n t r
dc_ d i s p a t c h I N T _ I N T C T R L _ 1 , I N T C T R L _ 1
# endif
int_ h a n d I N T _ I N T C T R L _ 0 , I N T C T R L _ 0 , b a d _ i n t r
int_ h a n d I N T _ M E S S A G E _ R C V _ D W N C L , M E S S A G E _ R C V _ D W N C L , \
hv_ m e s s a g e _ i n t r
int_ h a n d I N T _ D E V _ I N T R _ D W N C L , D E V _ I N T R _ D W N C L , b a d _ i n t r
int_ h a n d I N T _ I _ A S I D , I _ A S I D , b a d _ i n t r
int_ h a n d I N T _ D _ A S I D , D _ A S I D , b a d _ i n t r
int_ h a n d I N T _ D O U B L E _ F A U L T , D O U B L E _ F A U L T , d o _ t r a p
/* Synthetic interrupt delivered only by the simulator */
int_ h a n d I N T _ B R E A K P O I N T , B R E A K P O I N T , d o _ b r e a k p o i n t
2015-05-05 00:26:35 +03:00
/* Synthetic interrupt delivered by hv */
int_ h a n d I N T _ N M I _ D W N C L , N M I _ D W N C L , d o _ n m i , h a n d l e _ n m i