| /* SPDX-License-Identifier: GPL-2.0 */ | |
| // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. | |
| #include <linux/linkage.h> | |
| #include <asm/ftrace.h> | |
| #include <abi/entry.h> | |
| #include <asm/asm-offsets.h> | |
| /* | |
| * csky-gcc with -pg will put the following asm after prologue: | |
| * push r15 | |
| * jsri _mcount | |
| * | |
| * stack layout after mcount_enter in _mcount(): | |
| * | |
| * current sp => 0:+-------+ | |
| * | a0-a3 | -> must save all argument regs | |
| * +16:+-------+ | |
| * | lr | -> _mcount lr (instrumente function's pc) | |
| * +20:+-------+ | |
| * | fp=r8 | -> instrumented function fp | |
| * +24:+-------+ | |
| * | plr | -> instrumented function lr (parent's pc) | |
| * +-------+ | |
| */ | |
| .macro mcount_enter | |
| subi sp, 24 | |
| stw a0, (sp, 0) | |
| stw a1, (sp, 4) | |
| stw a2, (sp, 8) | |
| stw a3, (sp, 12) | |
| stw lr, (sp, 16) | |
| stw r8, (sp, 20) | |
| .endm | |
| .macro mcount_exit | |
| ldw a0, (sp, 0) | |
| ldw a1, (sp, 4) | |
| ldw a2, (sp, 8) | |
| ldw a3, (sp, 12) | |
| ldw t1, (sp, 16) | |
| ldw r8, (sp, 20) | |
| ldw lr, (sp, 24) | |
| addi sp, 28 | |
| jmp t1 | |
| .endm | |
| .macro mcount_enter_regs | |
| subi sp, 8 | |
| stw lr, (sp, 0) | |
| stw r8, (sp, 4) | |
| SAVE_REGS_FTRACE | |
| .endm | |
| .macro mcount_exit_regs | |
| RESTORE_REGS_FTRACE | |
| subi sp, 152 | |
| ldw t1, (sp, 4) | |
| addi sp, 152 | |
| ldw r8, (sp, 4) | |
| ldw lr, (sp, 8) | |
| addi sp, 12 | |
| jmp t1 | |
| .endm | |
| .macro save_return_regs | |
| subi sp, 16 | |
| stw a0, (sp, 0) | |
| stw a1, (sp, 4) | |
| stw a2, (sp, 8) | |
| stw a3, (sp, 12) | |
| .endm | |
| .macro restore_return_regs | |
| mov lr, a0 | |
| ldw a0, (sp, 0) | |
| ldw a1, (sp, 4) | |
| ldw a2, (sp, 8) | |
| ldw a3, (sp, 12) | |
| addi sp, 16 | |
| .endm | |
| .macro nop32_stub | |
| nop32 | |
| nop32 | |
| nop32 | |
| .endm | |
| ENTRY(ftrace_stub) | |
| jmp lr | |
| END(ftrace_stub) | |
| #ifndef CONFIG_DYNAMIC_FTRACE | |
| ENTRY(_mcount) | |
| mcount_enter | |
| /* r26 is link register, only used with jsri translation */ | |
| lrw r26, ftrace_trace_function | |
| ldw r26, (r26, 0) | |
| lrw a1, ftrace_stub | |
| cmpne r26, a1 | |
| bf skip_ftrace | |
| mov a0, lr | |
| subi a0, 4 | |
| ldw a1, (sp, 24) | |
| lrw a2, function_trace_op | |
| ldw a2, (a2, 0) | |
| jsr r26 | |
| #ifndef CONFIG_FUNCTION_GRAPH_TRACER | |
| skip_ftrace: | |
| mcount_exit | |
| #else | |
| skip_ftrace: | |
| lrw a0, ftrace_graph_return | |
| ldw a0, (a0, 0) | |
| lrw a1, ftrace_stub | |
| cmpne a0, a1 | |
| bt ftrace_graph_caller | |
| lrw a0, ftrace_graph_entry | |
| ldw a0, (a0, 0) | |
| lrw a1, ftrace_graph_entry_stub | |
| cmpne a0, a1 | |
| bt ftrace_graph_caller | |
| mcount_exit | |
| #endif | |
| END(_mcount) | |
| #else /* CONFIG_DYNAMIC_FTRACE */ | |
| ENTRY(_mcount) | |
| mov t1, lr | |
| ldw lr, (sp, 0) | |
| addi sp, 4 | |
| jmp t1 | |
| ENDPROC(_mcount) | |
| ENTRY(ftrace_caller) | |
| mcount_enter | |
| ldw a0, (sp, 16) | |
| subi a0, 4 | |
| ldw a1, (sp, 24) | |
| lrw a2, function_trace_op | |
| ldw a2, (a2, 0) | |
| nop | |
| GLOBAL(ftrace_call) | |
| nop32_stub | |
| #ifdef CONFIG_FUNCTION_GRAPH_TRACER | |
| nop | |
| GLOBAL(ftrace_graph_call) | |
| nop32_stub | |
| #endif | |
| mcount_exit | |
| ENDPROC(ftrace_caller) | |
| #endif /* CONFIG_DYNAMIC_FTRACE */ | |
| #ifdef CONFIG_FUNCTION_GRAPH_TRACER | |
| ENTRY(ftrace_graph_caller) | |
| mov a0, sp | |
| addi a0, 24 | |
| ldw a1, (sp, 16) | |
| subi a1, 4 | |
| mov a2, r8 | |
| lrw r26, prepare_ftrace_return | |
| jsr r26 | |
| mcount_exit | |
| END(ftrace_graph_caller) | |
| ENTRY(return_to_handler) | |
| save_return_regs | |
| mov a0, r8 | |
| jsri ftrace_return_to_handler | |
| restore_return_regs | |
| jmp lr | |
| END(return_to_handler) | |
| #endif | |
| #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | |
| ENTRY(ftrace_regs_caller) | |
| mcount_enter_regs | |
| lrw t1, PT_FRAME_SIZE | |
| add t1, sp | |
| ldw a0, (t1, 0) | |
| subi a0, 4 | |
| ldw a1, (t1, 8) | |
| lrw a2, function_trace_op | |
| ldw a2, (a2, 0) | |
| mov a3, sp | |
| nop | |
| GLOBAL(ftrace_regs_call) | |
| nop32_stub | |
| #ifdef CONFIG_FUNCTION_GRAPH_TRACER | |
| nop | |
| GLOBAL(ftrace_graph_regs_call) | |
| nop32_stub | |
| #endif | |
| mcount_exit_regs | |
| ENDPROC(ftrace_regs_caller) | |
| #endif /* CONFIG_DYNAMIC_FTRACE */ |