.macro mcount_adjust_addr rd, rn
bic \rd, \rn,
sub \rd, \rd,
.endm
.macro __mcount suffix
mcount_enter
ldr_va r2, ftrace_trace_function
badr r0, .Lftrace_stub
cmp r0, r2
bne 1f
ldr_va r2, ftrace_graph_return
cmp r0, r2
bne ftrace_graph_caller\suffix
ldr_va r2, ftrace_graph_entry
mov_l r0, ftrace_graph_entry_stub
cmp r0, r2
bne ftrace_graph_caller\suffix
mcount_exit
1: mcount_get_lr r1 @ lr of instrumented func
mcount_adjust_addr r0, lr @ instrumented function
badr lr, 2f
mov pc, r2
2: mcount_exit
.endm
.macro __ftrace_regs_caller
str lr, [sp,
@ OLD_R0 will overwrite previous LR
ldr lr, [sp,
str r0, [sp,
str lr, [sp,
add lr, sp,
@ before the push {lr} of the mcount mechanism
push {r0-r11, ip, lr}
@ stack content at this point:
@ 0 4 48 52 56 60 64 68 72
@ R0 | R1 | ... | IP | SP + 4 | previous LR | LR | PSR | OLD_R0 |
mov r3, sp @ struct pt_regs*
ldr_va r2, function_trace_op @ pointer to the current
@ function tracing op
ldr r1, [sp,
ldr lr, [sp,
mcount_adjust_addr r0, lr @ instrumented function
.globl ftrace_regs_call
ftrace_regs_call:
bl ftrace_stub
.globl ftrace_graph_regs_call
ftrace_graph_regs_call:
ARM( mov r0, r0 )
THUMB( nop.w )
@ pop saved regs
pop {r0-r11, ip, lr} @ restore r0 through r12
ldr lr, [sp],
ldr pc, [sp],
.endm
.macro __ftrace_graph_regs_caller
sub r0, fp,
add r0, sp,
@ called from __ftrace_regs_caller
ldr r1, [sp,
mcount_adjust_addr r1, r1
mov r2, fpreg @ frame pointer
add r3, sp,
bl prepare_ftrace_return
@ pop registers saved in ftrace_regs_caller
pop {r0-r11, ip, lr} @ restore r0 through r12
ldr lr, [sp],
ldr pc, [sp],
.endm
.macro __ftrace_caller suffix
mcount_enter
mcount_get_lr r1 @ lr of instrumented func
mcount_adjust_addr r0, lr @ instrumented function
ldr_va r2, function_trace_op @ pointer to the current
@ function tracing op
mov r3,
.globl ftrace_call\suffix
ftrace_call\suffix:
bl ftrace_stub
.globl ftrace_graph_call\suffix
ftrace_graph_call\suffix:
ARM( mov r0, r0 )
THUMB( nop.w )
mcount_exit
.endm
.macro __ftrace_graph_caller
sub r0, fp,
add r0, sp,
@ called from __ftrace_caller, saved in mcount_enter
ldr r1, [sp,
mcount_adjust_addr r1, r1
@ called from __mcount, untouched in lr
mcount_adjust_addr r1, lr @ instrumented routine (func)
mov r2, fpreg @ frame pointer
add r3, sp,
bl prepare_ftrace_return
mcount_exit
.endm
.macro mcount_enter
UNWIND(.pad
stmdb sp!, {r0-r3, lr}
UNWIND(.save {r0-r3, lr})
.endm
.macro mcount_get_lr reg
ldr \reg, [sp,
.endm
.macro mcount_exit
ldmia sp!, {r0-r3}
ldr lr, [sp,
ldr pc, [sp],
.endm
ENTRY(__gnu_mcount_nc)
UNWIND(.fnstart)
push {lr}
ldr lr, [sp,
ldr pc, [sp],
__mcount
UNWIND(.fnend)
ENDPROC(__gnu_mcount_nc)
ENTRY(ftrace_caller)
UNWIND(.fnstart)
__ftrace_caller
UNWIND(.fnend)
ENDPROC(ftrace_caller)
ENTRY(ftrace_regs_caller)
UNWIND(.fnstart)
__ftrace_regs_caller
UNWIND(.fnend)
ENDPROC(ftrace_regs_caller)
ENTRY(ftrace_graph_caller)
UNWIND(.fnstart)
__ftrace_graph_caller
UNWIND(.fnend)
ENDPROC(ftrace_graph_caller)
ENTRY(ftrace_graph_regs_caller)
UNWIND(.fnstart)
__ftrace_graph_regs_caller
UNWIND(.fnend)
ENDPROC(ftrace_graph_regs_caller)
.purgem mcount_enter
.purgem mcount_get_lr
.purgem mcount_exit
ENTRY(return_to_handler)
mov ip, sp @ sp at exit of instrumented routine
sub sp,
str r0, [sp,
str r1, [sp,
str r2, [sp,
str r3, [sp,
str ip, [sp,
mov r0, sp
bl ftrace_return_to_handler
mov lr, r0 @ r0 has real ret addr
ldr r3, [sp,
ldr r2, [sp,
ldr r1, [sp,
ldr r0, [sp,
add sp, sp,
ret lr
ENDPROC(return_to_handler)
ENTRY(ftrace_stub)
.Lftrace_stub:
ret lr
ENDPROC(ftrace_stub)
ENTRY(ftrace_stub_graph)
ret lr
ENDPROC(ftrace_stub_graph)
__INIT
.macro init_tramp, dst:req
ENTRY(\dst\()_from_init)
ldr pc, =\dst
ENDPROC(\dst\()_from_init)
.endm
init_tramp ftrace_caller
init_tramp ftrace_regs_caller