2019-06-04 11:11:33 +03:00
/* SPDX-License-Identifier: GPL-2.0-only */
2014-10-28 16:26:48 +03:00
# include < a s m / a s s e m b l e r . h >
# include < a s m / f t r a c e . h >
# include < a s m / u n w i n d . h >
# include " e n t r y - h e a d e r . S "
/ *
* When c o m p i l i n g w i t h - p g , g c c i n s e r t s a c a l l t o t h e m c o u n t r o u t i n e a t t h e
* start o f e v e r y f u n c t i o n . I n m c o u n t , a p a r t f r o m t h e f u n c t i o n ' s a d d r e s s ( i n
* lr) , w e n e e d t o g e t h o l d o f t h e f u n c t i o n ' s c a l l e r ' s a d d r e s s .
*
2018-09-11 06:31:49 +03:00
* Newer G C C s ( 4 . 4 + ) s o l v e t h i s p r o b l e m b y u s i n g a v e r s i o n o f m c o u n t w i t h c a l l
* sites l i k e :
2014-10-28 16:26:48 +03:00
*
* push { l r }
* bl _ _ g n u _ m c o u n t _ n c
*
* With t h e s e c o m p i l e r s , f r a m e p o i n t e r s a r e n o t n e c e s s a r y .
*
* mcount c a n b e t h o u g h t o f a s a f u n c t i o n c a l l e d i n t h e m i d d l e o f a s u b r o u t i n e
* call. A s s u c h , i t n e e d s t o b e t r a n s p a r e n t f o r b o t h t h e c a l l e r a n d t h e
* callee : the o r i g i n a l l r n e e d s t o b e r e s t o r e d w h e n l e a v i n g m c o u n t , a n d n o
2022-01-23 22:18:33 +03:00
* registers s h o u l d b e c l o b b e r e d .
2014-10-28 16:26:48 +03:00
*
2021-12-08 10:42:03 +03:00
* When u s i n g d y n a m i c f t r a c e , w e p a t c h o u t t h e m c o u n t c a l l b y a " a d d s p , #4 "
2018-09-11 06:31:49 +03:00
* instead o f t h e _ _ g n u _ m c o u n t _ n c c a l l ( s e e a r c h / a r m / k e r n e l / f t r a c e . c ) .
2014-10-28 16:26:48 +03:00
* /
.macro mcount_adjust_addr rd, r n
bic \ r d , \ r n , #1 @ clear the Thumb bit if present
sub \ r d , \ r d , #M C O U N T _ I N S N _ S I Z E
.endm
.macro __mcount suffix
mcount_ e n t e r
2021-12-07 21:50:35 +03:00
ldr_ v a r2 , f t r a c e _ t r a c e _ f u n c t i o n
2022-01-24 12:38:15 +03:00
badr r0 , . L f t r a c e _ s t u b
2014-10-28 16:26:48 +03:00
cmp r0 , r2
bne 1 f
# 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
2021-12-07 21:50:35 +03:00
ldr_ v a r2 , f t r a c e _ g r a p h _ r e t u r n
cmp r0 , r2
bne f t r a c e _ g r a p h _ c a l l e r \ s u f f i x
ldr_ v a r2 , f t r a c e _ g r a p h _ e n t r y
mov_ l r0 , f t r a c e _ g r a p h _ e n t r y _ s t u b
cmp r0 , r2
bne f t r a c e _ g r a p h _ c a l l e r \ s u f f i x
2014-10-28 16:26:48 +03:00
# endif
mcount_ e x i t
1 : mcount_ g e t _ l r r1 @ lr of instrumented func
mcount_ a d j u s t _ a d d r r0 , l r @ instrumented function
2015-04-21 16:17:25 +03:00
badr l r , 2 f
2014-10-28 16:26:48 +03:00
mov p c , r2
2 : mcount_ e x i t
.endm
2017-05-26 23:49:47 +03:00
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E _ W I T H _ R E G S
.macro __ftrace_regs_caller
2022-01-23 22:18:33 +03:00
str l r , [ s p , #- 8 ] ! @ store LR as PC and make space for CPSR/OLD_R0,
2017-05-26 23:49:47 +03:00
@ OLD_R0 will overwrite previous LR
2022-01-23 22:18:33 +03:00
ldr l r , [ s p , #8 ] @ get previous LR
2017-05-26 23:49:47 +03:00
2022-01-23 22:18:33 +03:00
str r0 , [ s p , #8 ] @ write r0 as OLD_R0 over previous LR
2017-05-26 23:49:47 +03:00
2022-01-23 22:18:33 +03:00
str l r , [ s p , #- 4 ] ! @ store previous LR as LR
2017-05-26 23:49:47 +03:00
2022-01-23 22:18:33 +03:00
add l r , s p , #16 @ move in LR the value of SP as it was
@ before the push {lr} of the mcount mechanism
2017-05-26 23:49:47 +03:00
2022-01-23 22:18:33 +03:00
push { r0 - r11 , i p , l r }
2017-05-26 23:49:47 +03:00
@ stack content at this point:
@ 0 4 48 52 56 60 64 68 72
2022-01-23 22:18:33 +03:00
@ R0 | R1 | ... | IP | SP + 4 | previous LR | LR | PSR | OLD_R0 |
2017-05-26 23:49:47 +03:00
2022-01-23 22:18:33 +03:00
mov r3 , s p @ struct pt_regs*
2017-05-26 23:49:47 +03:00
2021-12-07 21:50:35 +03:00
ldr_ v a r2 , f u n c t i o n _ t r a c e _ o p @ pointer to the current
2017-05-26 23:49:47 +03:00
@ function tracing op
ldr r1 , [ s p , #S _ L R ] @ l r o f i n s t r u m e n t e d f u n c
ldr l r , [ s p , #S _ P C ] @ g e t L R
mcount_ a d j u s t _ a d d r r0 , l r @ instrumented function
.globl ftrace_regs_call
ftrace_regs_call :
bl 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
.globl ftrace_graph_regs_call
ftrace_graph_regs_call :
mov r0 , r0
# endif
@ pop saved regs
2022-01-23 22:18:33 +03:00
pop { r0 - r11 , i p , l r } @ restore r0 through r12
ldr l r , [ s p ] , #4 @ restore LR
ldr p c , [ s p ] , #12
2017-05-26 23:49:47 +03:00
.endm
# 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
.macro __ftrace_graph_regs_caller
sub r0 , f p , #4 @ lr of instrumented routine (parent)
@ called from __ftrace_regs_caller
ldr r1 , [ s p , #S _ P C ] @ i n s t r u m e n t e d r o u t i n e ( f u n c )
mcount_ a d j u s t _ a d d r r1 , r1
mov r2 , f p @ frame pointer
bl p r e p a r e _ f t r a c e _ r e t u r n
@ pop registers saved in ftrace_regs_caller
2022-01-23 22:18:33 +03:00
pop { r0 - r11 , i p , l r } @ restore r0 through r12
ldr l r , [ s p ] , #4 @ restore LR
ldr p c , [ s p ] , #12
2017-05-26 23:49:47 +03:00
.endm
# endif
# endif
2014-10-28 16:26:48 +03:00
.macro __ftrace_caller suffix
mcount_ e n t e r
mcount_ g e t _ l r r1 @ lr of instrumented func
mcount_ a d j u s t _ a d d r r0 , l r @ instrumented function
2017-05-26 23:49:47 +03:00
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E _ W I T H _ R E G S
2021-12-07 21:50:35 +03:00
ldr_ v a r2 , f u n c t i o n _ t r a c e _ o p @ pointer to the current
2017-05-26 23:49:47 +03:00
@ function tracing op
mov r3 , #0 @ regs is NULL
# endif
2014-10-28 16:26:48 +03:00
.globl ftrace_ c a l l \ s u f f i x
ftrace_ c a l l \ s u f f i x :
bl 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
.globl ftrace_ g r a p h _ c a l l \ s u f f i x
ftrace_ g r a p h _ c a l l \ s u f f i x :
mov r0 , r0
# endif
mcount_ e x i t
.endm
.macro __ftrace_graph_caller
sub r0 , f p , #4 @ &lr of instrumented routine (&parent)
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E
@ called from __ftrace_caller, saved in mcount_enter
ldr r1 , [ s p , #16 ] @ instrumented routine (func)
mcount_ a d j u s t _ a d d r r1 , r1
# else
@ called from __mcount, untouched in lr
mcount_ a d j u s t _ a d d r r1 , l r @ instrumented routine (func)
# endif
mov r2 , f p @ frame pointer
bl p r e p a r e _ f t r a c e _ r e t u r n
mcount_ e x i t
.endm
/ *
* _ _ gnu_ m c o u n t _ n c
* /
.macro mcount_enter
/ *
* This p a d c o m p e n s a t e s f o r t h e p u s h { l r } a t t h e c a l l s i t e . N o t e t h a t w e a r e
* unable t o u n w i n d t h r o u g h a f u n c t i o n w h i c h d o e s n o t o t h e r w i s e s a v e i t s l r .
* /
UNWIND( . p a d #4 )
stmdb s p ! , { r0 - r3 , l r }
UNWIND( . s a v e { r0 - r3 , l r } )
.endm
.macro mcount_get_lr reg
ldr \ r e g , [ s p , #20 ]
.endm
.macro mcount_exit
2022-01-23 22:18:33 +03:00
ldmia s p ! , { r0 - r3 }
ldr l r , [ s p , #4 ]
ldr p c , [ s p ] , #8
2014-10-28 16:26:48 +03:00
.endm
ENTRY( _ _ g n u _ m c o u n t _ n c )
UNWIND( . f n s t a r t )
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E
2022-01-23 22:18:33 +03:00
push { l r }
ldr l r , [ s p , #4 ]
ldr p c , [ s p ] , #8
2014-10-28 16:26:48 +03:00
# else
_ _ mcount
# endif
UNWIND( . f n e n d )
ENDPROC( _ _ g n u _ m c o u n t _ n c )
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E
ENTRY( f t r a c e _ c a l l e r )
UNWIND( . f n s t a r t )
_ _ ftrace_ c a l l e r
UNWIND( . f n e n d )
ENDPROC( f t r a c e _ c a l l e r )
2017-05-26 23:49:47 +03:00
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E _ W I T H _ R E G S
ENTRY( f t r a c e _ r e g s _ c a l l e r )
UNWIND( . f n s t a r t )
_ _ ftrace_ r e g s _ c a l l e r
UNWIND( . f n e n d )
ENDPROC( f t r a c e _ r e g s _ c a l l e r )
# endif
2014-10-28 16:26:48 +03:00
# endif
# 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
ENTRY( f t r a c e _ g r a p h _ c a l l e r )
UNWIND( . f n s t a r t )
_ _ ftrace_ g r a p h _ c a l l e r
UNWIND( . f n e n d )
ENDPROC( f t r a c e _ g r a p h _ c a l l e r )
2017-05-26 23:49:47 +03:00
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E _ W I T H _ R E G S
ENTRY( f t r a c e _ g r a p h _ r e g s _ c a l l e r )
UNWIND( . f n s t a r t )
_ _ ftrace_ g r a p h _ r e g s _ c a l l e r
UNWIND( . f n e n d )
ENDPROC( f t r a c e _ g r a p h _ r e g s _ c a l l e r )
# endif
2014-10-28 16:26:48 +03:00
# endif
.purgem mcount_enter
.purgem mcount_get_lr
.purgem mcount_exit
# 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
.globl return_to_handler
return_to_handler :
stmdb s p ! , { r0 - r3 }
mov r0 , f p @ frame pointer
bl f t r a c e _ r e t u r n _ t o _ h a n d l e r
mov l r , r0 @ r0 has real ret addr
ldmia s p ! , { r0 - r3 }
ret l r
# endif
ENTRY( f t r a c e _ s t u b )
.Lftrace_stub :
ret l r
ENDPROC( f t r a c e _ s t u b )
2022-01-23 22:28:39 +03:00
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E
_ _ INIT
.macro init_ t r a m p , d s t : r e q
ENTRY( \ d s t \ ( ) _ f r o m _ i n i t )
ldr p c , = \ d s t
ENDPROC( \ d s t \ ( ) _ f r o m _ i n i t )
.endm
init_ t r a m p f t r a c e _ c a l l e r
# ifdef C O N F I G _ D Y N A M I C _ F T R A C E _ W I T H _ R E G S
init_ t r a m p f t r a c e _ r e g s _ c a l l e r
# endif
# endif