2026-01-21 18:59:54 +08:00

196 lines
3.7 KiB
ArmAsm

/* SPDX-License-Identifier: GPL-2.0 */
/*
* arch/sw_64/kernel/entry-ftrace.S
*
* Author: linyue
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/linkage.h>
.text
.set noat
.align 4
#define FTRACE_SP_OFF 0x50
.macro mcount_enter
subl $sp, FTRACE_SP_OFF, $sp
stl $16, 0($sp)
stl $17, 0x8($sp)
stl $18, 0x10($sp)
stl $26, 0x18($sp)
stl $27, 0x20($sp)
stl $28, 0x28($sp)
stl $29, 0x30($sp)
stl $19, 0x38($sp)
stl $20, 0x40($sp)
stl $21, 0x48($sp)
.endm
.macro mcount_end
ldl $16, 0($sp)
ldl $17, 0x8($sp)
ldl $18, 0x10($sp)
ldl $26, 0x18($sp)
ldl $27, 0x20($sp)
ldl $28, 0x28($sp)
ldl $29, 0x30($sp)
ldl $19, 0x38($sp)
ldl $20, 0x40($sp)
ldl $21, 0x48($sp)
addl $sp, FTRACE_SP_OFF, $sp
.endm
#ifdef CONFIG_DYNAMIC_FTRACE
.global _mcount
.ent _mcount
_mcount:
ret $31, ($28), 1
.end _mcount
.global ftrace_caller
.ent ftrace_caller
ftrace_caller:
mcount_enter
br $27, 2f
2: ldgp $29, 0($27)
bis $28, $31, $16
subl $16, 8, $16
bis $26, $31, $17
ldi $4, current_tracer
ldl $27, 0($4)
.global ftrace_call
ftrace_call: /* tracer(pc, lr); call 26, 27 , 1 */
nop
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
ldi $27, prepare_ftrace_return /* prepare_ftrace_return(&lr, pc, fp) */
.global ftrace_graph_call
ftrace_graph_call: /* ftrace_graph_caller(); */
nop /* If enabled, this will be replaced */
/* "br ftrace_graph_caller" */
#endif
mcount_end
ret $31, ($28), 1
.end ftrace_caller
#else /* !CONFIG_DYNAMIC_FTRACE */
.global _mcount
.ent _mcount
_mcount:
mcount_enter
br $27, 1f
1: ldgp $29, 0($27)
ldi $4, ftrace_trace_function
ldl $27, 0($4)
ldi $5, ftrace_stub
cmpeq $4, $5, $6
bne $6, skip_ftrace
bis $28, $31, $16
subl $16, 8, $16
bis $26, $31, $17
call $26, ($27), 1
skip_ftrace:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
ldi $4, ftrace_graph_return
ldl $4, 0($4)
ldi $5, ftrace_stub
cmpeq $4, $5, $6
beq $6, ftrace_graph_caller
ldi $4, ftrace_graph_entry
ldl $4, 0($4)
ldi $5, ftrace_graph_entry_stub
cmpeq $4, $5, $6
beq $6, ftrace_graph_caller
#endif
mcount_end
ret $31, ($28), 1
.end _mcount
#endif /* CONFIG_DYNAMIC_FTRACE */
.global ftrace_stub
.ent ftrace_stub
ftrace_stub:
ret $31, ($26), 1
.end ftrace_stub
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.macro RESTORE_GRAPH_ARGS
ldl $26, 0x18($sp)
ldl $28, 0x28($sp)
.endm
/* save return value regs*/
.macro save_return_regs
subl $sp, 0x8, $sp
stl $0, 0x0($sp)
.endm
/* restore return value regs*/
.macro restore_return_regs
ldl $0, 0x0($sp)
addl $sp, 0x8, $sp
.endm
/*
* void ftrace_graph_caller(void)
*
* Called from _mcount() or ftrace_caller() when function_graph tracer is
* selected.
* This function w/ prepare_ftrace_return() fakes link register's value on
* the call stack in order to intercept instrumented function's return path
* and run return_to_handler() later on its exit.
*/
.global ftrace_graph_caller
.ent ftrace_graph_caller
ftrace_graph_caller:
memb /* need memb, otherwise it'll go wrong */
RESTORE_GRAPH_ARGS
addl $sp, 0x18, $16
bis $28, $31, $17
subl $17, 8, $17
bis $15, $31, $18 /* parent's fp */
call $26, ($27) /* prepare_ftrace_return() */
mcount_end
ret $31, ($28), 1
.end ftrace_graph_caller
/*
* void return_to_handler(void)
*
* Run ftrace_return_to_handler() before going back to parent.
* @fp is checked against the value passed by ftrace_graph_caller()
* only when HAVE_FUNCTION_GRAPH_FP_TEST is enabled.
*/
ENTRY(return_to_handler)
save_return_regs
br $27, 3f
3: ldgp $29, 0($27)
ldi $27, ftrace_return_to_handler
call $26, ($27)
bis $0, $31, $26
restore_return_regs
ret $31, ($26), 1
END(return_to_handler)
#endif