2014-04-30 13:54:33 +04:00
/ *
* arch/ a r m 6 4 / k e r n e l / e n t r y - f t r a c e . S
*
* Copyright ( C ) 2 0 1 3 L i n a r o L i m i t e d
* Author : AKASHI T a k a h i r o < t a k a h i r o . a k a s h i @linaro.org>
*
* 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 .
* /
# include < l i n u x / l i n k a g e . h >
2017-02-15 00:32:58 +03:00
# include < a s m / a s s e m b l e r . h >
2014-04-30 13:54:33 +04:00
# include < a s m / f t r a c e . h >
# include < a s m / i n s n . h >
/ *
* Gcc w i t h - p g w i l l p u t t h e f o l l o w i n g c o d e i n t h e b e g i n n i n g o f e a c h f u n c t i o n :
* mov x0 , x30
* bl _ m c o u n t
* [ function' s b o d y . . . ]
* " bl _ m c o u n t " m a y b e r e p l a c e d t o " b l f t r a c e _ c a l l e r " o r N O P i f d y n a m i c
* ftrace i s e n a b l e d .
*
* Please n o t e t h a t x0 a s a n a r g u m e n t w i l l n o t b e u s e d h e r e b e c a u s e w e c a n
* get l r ( x30 ) o f i n s t r u m e n t e d f u n c t i o n a t a n y t i m e b y w i n d i n g u p c a l l s t a c k
* as l o n g a s t h e k e r n e l i s c o m p i l e d w i t h o u t - f o m i t - f r a m e - p o i n t e r .
* ( or C O N F I G _ F R A M E _ P O I N T E R , t h i s i s f o r c e d o n a r m 6 4 )
*
* stack l a y o u t a f t e r m c o u n t _ e n t e r i n _ m c o u n t ( ) :
*
* current s p / f p = > 0 : + - - - - - +
* in _ m c o u n t ( ) | x29 | - > i n s t r u m e n t e d f u n c t i o n ' s f p
* + - - - - - +
* | x3 0 | - > _ m c o u n t ( ) ' s l r ( = i n s t r u m e n t e d f u n c t i o n ' s p c )
* old s p = > + 1 6 : + - - - - - +
* when i n s t r u m e n t e d | |
* function c a l l s | . . . |
* _ mcount( ) | |
* | |
* instrumented = > + x x : + - - - - - +
* function' s f p | x29 | - > p a r e n t ' s f p
* + - - - - - +
* | x3 0 | - > i n s t r u m e n t e d f u n c t i o n ' s l r ( = p a r e n t ' s p c )
* + - - - - - +
* | . . . |
* /
.macro mcount_enter
stp x29 , x30 , [ s p , #- 16 ] !
mov x29 , s p
.endm
.macro mcount_exit
ldp x29 , x30 , [ s p ] , #16
ret
.endm
.macro mcount_adjust_addr rd, r n
sub \ r d , \ r n , #A A R C H 64 _ I N S N _ S I Z E
.endm
/* for instrumented function's parent */
.macro mcount_get_parent_fp reg
ldr \ r e g , [ x29 ]
ldr \ r e g , [ \ r e g ]
.endm
/* for instrumented function */
.macro mcount_get_pc0 reg
mcount_ a d j u s t _ a d d r \ r e g , x30
.endm
.macro mcount_get_pc reg
ldr \ r e g , [ x29 , #8 ]
mcount_ a d j u s t _ a d d r \ r e g , \ r e g
.endm
.macro mcount_get_lr reg
ldr \ r e g , [ x29 ]
ldr \ r e g , [ \ r e g , #8 ]
.endm
.macro mcount_get_lr_addr reg
ldr \ r e g , [ x29 ]
add \ r e g , \ r e g , #8
.endm
2014-04-30 13:54:34 +04:00
# ifndef C O N F I G _ D Y N A M I C _ F T R A C E
2014-04-30 13:54:33 +04:00
/ *
* void _ m c o u n t ( u n s i g n e d l o n g r e t u r n _ a d d r e s s )
* @return_address: return address to instrumented function
*
* This f u n c t i o n m a k e s c a l l s , i f e n a b l e d , t o :
* - tracer f u n c t i o n t o p r o b e i n s t r u m e n t e d f u n c t i o n ' s e n t r y ,
* - ftrace_ g r a p h _ c a l l e r t o s e t u p a n e x i t h o o k
* /
ENTRY( _ m c o u n t )
mcount_ e n t e r
2017-01-17 19:10:58 +03:00
ldr_ l x2 , f t r a c e _ t r a c e _ f u n c t i o n
2014-04-30 13:54:33 +04:00
adr x0 , f t r a c e _ s t u b
cmp x0 , x2 / / i f ( f t r a c e _ t r a c e _ f u n c t i o n
b. e q s k i p _ f t r a c e _ c a l l / / ! = f t r a c e _ s t u b ) {
mcount_ g e t _ p c x0 / / f u n c t i o n ' s p c
mcount_ g e t _ l r x1 / / f u n c t i o n ' s l r ( = p a r e n t ' s p c )
blr x2 / / ( * f t r a c e _ t r a c e _ f u n c t i o n ) ( p c , l r ) ;
2017-11-03 14:44:16 +03:00
skip_ftrace_call : / / }
# ifdef C O N F I G _ F U N C T I O N _ G R A P H _ T R A C E R
2017-01-17 19:10:58 +03:00
ldr_ l x2 , f t r a c e _ g r a p h _ r e t u r n
2014-11-07 17:12:33 +03:00
cmp x0 , x2 / / i f ( ( f t r a c e _ g r a p h _ r e t u r n
b. n e f t r a c e _ g r a p h _ c a l l e r / / ! = f t r a c e _ s t u b )
2017-01-17 19:10:58 +03:00
ldr_ l x2 , f t r a c e _ g r a p h _ e n t r y / / | | ( f t r a c e _ g r a p h _ e n t r y
adr_ l x0 , f t r a c e _ g r a p h _ e n t r y _ s t u b / / ! = f t r a c e _ g r a p h _ e n t r y _ s t u b ) )
2014-04-30 13:54:33 +04:00
cmp x0 , x2
b. n e f t r a c e _ g r a p h _ c a l l e r / / f t r a c e _ g r a p h _ c a l l e r ( ) ;
# endif / * C O N F I G _ F U N C T I O N _ G R A P H _ T R A C E R * /
2017-11-03 14:44:16 +03:00
mcount_ e x i t
2014-04-30 13:54:33 +04:00
ENDPROC( _ m c o u n t )
2014-04-30 13:54:34 +04:00
# else / * C O N F I G _ D Y N A M I C _ F T R A C E * /
/ *
* _ mcount( ) i s u s e d t o b u i l d t h e k e r n e l w i t h - p g o p t i o n , b u t a l l t h e b r a n c h
* instructions t o _ m c o u n t ( ) a r e r e p l a c e d t o N O P i n i t i a l l y a t k e r n e l s t a r t u p ,
* and l a t e r o n , N O P t o b r a n c h t o f t r a c e _ c a l l e r ( ) w h e n e n a b l e d o r b r a n c h t o
* NOP w h e n d i s a b l e d p e r - f u n c t i o n b a s e .
* /
ENTRY( _ m c o u n t )
ret
ENDPROC( _ m c o u n t )
/ *
* void f t r a c e _ c a l l e r ( u n s i g n e d l o n g r e t u r n _ a d d r e s s )
* @return_address: return address to instrumented function
*
* This f u n c t i o n i s a c o u n t e r p a r t o f _ m c o u n t ( ) i n ' s t a t i c ' f t r a c e , a n d
* makes c a l l s t o :
* - tracer f u n c t i o n t o p r o b e i n s t r u m e n t e d f u n c t i o n ' s e n t r y ,
* - ftrace_ g r a p h _ c a l l e r t o s e t u p a n e x i t h o o k
* /
ENTRY( f t r a c e _ c a l l e r )
mcount_ e n t e r
mcount_ g e t _ p c0 x0 / / f u n c t i o n ' s p c
mcount_ g e t _ l r x1 / / f u n c t i o n ' s l r
2018-11-16 01:41:59 +03:00
GLOBAL( f t r a c e _ c a l l ) / / t r a c e r ( p c , l r ) ;
2014-04-30 13:54:34 +04:00
nop / / T h i s w i l l b e r e p l a c e d w i t h " b l x x x "
/ / where x x x c a n b e a n y k i n d o f t r a c e r .
# ifdef C O N F I G _ F U N C T I O N _ G R A P H _ T R A C E R
2018-11-16 01:41:59 +03:00
GLOBAL( f t r a c e _ g r a p h _ c a l l ) / / f t r a c e _ g r a p h _ c a l l e r ( ) ;
2014-04-30 13:54:34 +04:00
nop / / I f e n a b l e d , t h i s w i l l b e r e p l a c e d
/ / " b f t r a c e _ g r a p h _ c a l l e r "
# endif
mcount_ e x i t
ENDPROC( f t r a c e _ c a l l e r )
# endif / * C O N F I G _ D Y N A M I C _ F T R A C E * /
2014-04-30 13:54:33 +04:00
ENTRY( f t r a c e _ s t u b )
ret
ENDPROC( f t r a c e _ s t u b )
# ifdef C O N F I G _ F U N C T I O N _ G R A P H _ T R A C E R
/ *
* void f t r a c e _ g r a p h _ c a l l e r ( v o i d )
*
* Called f r o m _ m c o u n t ( ) o r f t r a c e _ c a l l e r ( ) w h e n f u n c t i o n _ g r a p h t r a c e r i s
* selected.
* This f u n c t i o n w / p r e p a r e _ f t r a c e _ r e t u r n ( ) f a k e s l i n k r e g i s t e r ' s v a l u e o n
* the c a l l s t a c k i n o r d e r t o i n t e r c e p t i n s t r u m e n t e d f u n c t i o n ' s r e t u r n p a t h
* and r u n r e t u r n _ t o _ h a n d l e r ( ) l a t e r o n i t s e x i t .
* /
ENTRY( f t r a c e _ g r a p h _ c a l l e r )
mcount_ g e t _ l r _ a d d r x0 / / p o i n t e r t o f u n c t i o n ' s s a v e d l r
mcount_ g e t _ p c x1 / / f u n c t i o n ' s p c
mcount_ g e t _ p a r e n t _ f p x2 / / p a r e n t ' s f p
bl p r e p a r e _ f t r a c e _ r e t u r n / / p r e p a r e _ f t r a c e _ r e t u r n ( & l r , p c , f p )
mcount_ e x i t
ENDPROC( f t r a c e _ g r a p h _ c a l l e r )
/ *
* void r e t u r n _ t o _ h a n d l e r ( v o i d )
*
* Run f t r a c e _ r e t u r n _ t o _ h a n d l e r ( ) b e f o r e g o i n g b a c k t o p a r e n t .
2018-11-16 01:42:00 +03:00
* @fp is checked against the value passed by ftrace_graph_caller().
2014-04-30 13:54:33 +04:00
* /
ENTRY( r e t u r n _ t o _ h a n d l e r )
2018-11-16 01:42:02 +03:00
/* save return value regs */
sub s p , s p , #64
stp x0 , x1 , [ s p ]
stp x2 , x3 , [ s p , #16 ]
stp x4 , x5 , [ s p , #32 ]
stp x6 , x7 , [ s p , #48 ]
2014-04-30 13:54:33 +04:00
mov x0 , x29 / / p a r e n t ' s f p
bl f t r a c e _ r e t u r n _ t o _ h a n d l e r / / a d d r = f t r a c e _ r e t u r n _ t o _ h a n d e r ( f p ) ;
mov x30 , x0 / / r e s t o r e t h e o r i g i n a l r e t u r n a d d r e s s
2018-11-16 01:42:02 +03:00
/* restore return value regs */
ldp x0 , x1 , [ s p ]
ldp x2 , x3 , [ s p , #16 ]
ldp x4 , x5 , [ s p , #32 ]
ldp x6 , x7 , [ s p , #48 ]
add s p , s p , #64
2014-04-30 13:54:33 +04:00
ret
END( r e t u r n _ t o _ h a n d l e r )
# endif / * C O N F I G _ F U N C T I O N _ G R A P H _ T R A C E R * /