1230c77a5SGuo Ren/* SPDX-License-Identifier: GPL-2.0 */ 2230c77a5SGuo Ren// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 3230c77a5SGuo Ren 4230c77a5SGuo Ren#include <linux/linkage.h> 5d7950be1SGuo Ren#include <asm/ftrace.h> 6*89a3927aSGuo Ren#include <abi/entry.h> 7*89a3927aSGuo Ren#include <asm/asm-offsets.h> 8230c77a5SGuo Ren 9d7950be1SGuo Ren/* 10d7950be1SGuo Ren * csky-gcc with -pg will put the following asm after prologue: 11d7950be1SGuo Ren * push r15 12d7950be1SGuo Ren * jsri _mcount 13d7950be1SGuo Ren * 14d7950be1SGuo Ren * stack layout after mcount_enter in _mcount(): 15d7950be1SGuo Ren * 16d7950be1SGuo Ren * current sp => 0:+-------+ 17d7950be1SGuo Ren * | a0-a3 | -> must save all argument regs 18d7950be1SGuo Ren * +16:+-------+ 19d7950be1SGuo Ren * | lr | -> _mcount lr (instrumente function's pc) 20d7950be1SGuo Ren * +20:+-------+ 21d7950be1SGuo Ren * | fp=r8 | -> instrumented function fp 22d7950be1SGuo Ren * +24:+-------+ 23d7950be1SGuo Ren * | plr | -> instrumented function lr (parent's pc) 24d7950be1SGuo Ren * +-------+ 25d7950be1SGuo Ren */ 26d7950be1SGuo Ren 27d7950be1SGuo Ren.macro mcount_enter 28d7950be1SGuo Ren subi sp, 24 29230c77a5SGuo Ren stw a0, (sp, 0) 30230c77a5SGuo Ren stw a1, (sp, 4) 31230c77a5SGuo Ren stw a2, (sp, 8) 32230c77a5SGuo Ren stw a3, (sp, 12) 33230c77a5SGuo Ren stw lr, (sp, 16) 34d7950be1SGuo Ren stw r8, (sp, 20) 35d7950be1SGuo Ren.endm 36d7950be1SGuo Ren 37d7950be1SGuo Ren.macro mcount_exit 38230c77a5SGuo Ren ldw a0, (sp, 0) 39230c77a5SGuo Ren ldw a1, (sp, 4) 40230c77a5SGuo Ren ldw a2, (sp, 8) 41230c77a5SGuo Ren ldw a3, (sp, 12) 42230c77a5SGuo Ren ldw t1, (sp, 16) 43d7950be1SGuo Ren ldw r8, (sp, 20) 44d7950be1SGuo Ren ldw lr, (sp, 24) 45d7950be1SGuo Ren addi sp, 28 46230c77a5SGuo Ren jmp t1 47d7950be1SGuo Ren.endm 48d7950be1SGuo Ren 49*89a3927aSGuo Ren.macro mcount_enter_regs 50*89a3927aSGuo Ren subi sp, 8 51*89a3927aSGuo Ren stw lr, (sp, 0) 52*89a3927aSGuo Ren stw r8, (sp, 4) 53*89a3927aSGuo Ren SAVE_REGS_FTRACE 54*89a3927aSGuo Ren.endm 55*89a3927aSGuo Ren 56*89a3927aSGuo Ren.macro mcount_exit_regs 57*89a3927aSGuo Ren RESTORE_REGS_FTRACE 58*89a3927aSGuo Ren ldw t1, (sp, 0) 59*89a3927aSGuo Ren ldw r8, (sp, 4) 60*89a3927aSGuo Ren ldw lr, (sp, 8) 61*89a3927aSGuo Ren addi sp, 12 62*89a3927aSGuo Ren jmp t1 63*89a3927aSGuo Ren.endm 64*89a3927aSGuo Ren 65d7950be1SGuo Ren.macro save_return_regs 66d7950be1SGuo Ren subi sp, 16 67d7950be1SGuo Ren stw a0, (sp, 0) 68d7950be1SGuo Ren stw a1, (sp, 4) 69d7950be1SGuo Ren stw a2, (sp, 8) 70d7950be1SGuo Ren stw a3, (sp, 12) 71d7950be1SGuo Ren.endm 72d7950be1SGuo Ren 73d7950be1SGuo Ren.macro restore_return_regs 74d7950be1SGuo Ren mov lr, a0 75d7950be1SGuo Ren ldw a0, (sp, 0) 76d7950be1SGuo Ren ldw a1, (sp, 4) 77d7950be1SGuo Ren ldw a2, (sp, 8) 78d7950be1SGuo Ren ldw a3, (sp, 12) 79d7950be1SGuo Ren addi sp, 16 80d7950be1SGuo Ren.endm 81d7950be1SGuo Ren 8228bb030fSGuo Ren.macro nop32_stub 8328bb030fSGuo Ren nop32 8428bb030fSGuo Ren nop32 8528bb030fSGuo Ren nop32 8628bb030fSGuo Ren.endm 8728bb030fSGuo Ren 88d7950be1SGuo RenENTRY(ftrace_stub) 89d7950be1SGuo Ren jmp lr 90d7950be1SGuo RenEND(ftrace_stub) 91d7950be1SGuo Ren 9228bb030fSGuo Ren#ifndef CONFIG_DYNAMIC_FTRACE 93d7950be1SGuo RenENTRY(_mcount) 94d7950be1SGuo Ren mcount_enter 95d7950be1SGuo Ren 96d7950be1SGuo Ren /* r26 is link register, only used with jsri translation */ 97d7950be1SGuo Ren lrw r26, ftrace_trace_function 98d7950be1SGuo Ren ldw r26, (r26, 0) 99d7950be1SGuo Ren lrw a1, ftrace_stub 100d7950be1SGuo Ren cmpne r26, a1 101d7950be1SGuo Ren bf skip_ftrace 102d7950be1SGuo Ren 103d7950be1SGuo Ren mov a0, lr 10428bb030fSGuo Ren subi a0, 4 105d7950be1SGuo Ren ldw a1, (sp, 24) 106d7950be1SGuo Ren 107d7950be1SGuo Ren jsr r26 108d7950be1SGuo Ren 109d7950be1SGuo Ren#ifndef CONFIG_FUNCTION_GRAPH_TRACER 110d7950be1SGuo Renskip_ftrace: 111d7950be1SGuo Ren mcount_exit 112d7950be1SGuo Ren#else 113d7950be1SGuo Renskip_ftrace: 114d7950be1SGuo Ren lrw a0, ftrace_graph_return 115d7950be1SGuo Ren ldw a0, (a0, 0) 116d7950be1SGuo Ren lrw a1, ftrace_stub 117d7950be1SGuo Ren cmpne a0, a1 118d7950be1SGuo Ren bt ftrace_graph_caller 119d7950be1SGuo Ren 120d7950be1SGuo Ren lrw a0, ftrace_graph_entry 121d7950be1SGuo Ren ldw a0, (a0, 0) 122d7950be1SGuo Ren lrw a1, ftrace_graph_entry_stub 123d7950be1SGuo Ren cmpne a0, a1 124d7950be1SGuo Ren bt ftrace_graph_caller 125d7950be1SGuo Ren 126d7950be1SGuo Ren mcount_exit 127d7950be1SGuo Ren#endif 128230c77a5SGuo RenEND(_mcount) 12928bb030fSGuo Ren#else /* CONFIG_DYNAMIC_FTRACE */ 13028bb030fSGuo RenENTRY(_mcount) 13128bb030fSGuo Ren mov t1, lr 13228bb030fSGuo Ren ldw lr, (sp, 0) 13328bb030fSGuo Ren addi sp, 4 13428bb030fSGuo Ren jmp t1 13528bb030fSGuo RenENDPROC(_mcount) 13628bb030fSGuo Ren 13728bb030fSGuo RenENTRY(ftrace_caller) 13828bb030fSGuo Ren mcount_enter 13928bb030fSGuo Ren 14028bb030fSGuo Ren ldw a0, (sp, 16) 14128bb030fSGuo Ren subi a0, 4 14228bb030fSGuo Ren ldw a1, (sp, 24) 143*89a3927aSGuo Ren lrw a2, function_trace_op 144*89a3927aSGuo Ren ldw a2, (a2, 0) 14528bb030fSGuo Ren 14628bb030fSGuo Ren nop 14728bb030fSGuo RenGLOBAL(ftrace_call) 14828bb030fSGuo Ren nop32_stub 14928bb030fSGuo Ren 15028bb030fSGuo Ren#ifdef CONFIG_FUNCTION_GRAPH_TRACER 15128bb030fSGuo Ren nop 15228bb030fSGuo RenGLOBAL(ftrace_graph_call) 15328bb030fSGuo Ren nop32_stub 15428bb030fSGuo Ren#endif 15528bb030fSGuo Ren 15628bb030fSGuo Ren mcount_exit 15728bb030fSGuo RenENDPROC(ftrace_caller) 15828bb030fSGuo Ren#endif /* CONFIG_DYNAMIC_FTRACE */ 159d7950be1SGuo Ren 160d7950be1SGuo Ren#ifdef CONFIG_FUNCTION_GRAPH_TRACER 161d7950be1SGuo RenENTRY(ftrace_graph_caller) 162d7950be1SGuo Ren mov a0, sp 163d7950be1SGuo Ren addi a0, 24 164d7950be1SGuo Ren ldw a1, (sp, 16) 16528bb030fSGuo Ren subi a1, 4 166d7950be1SGuo Ren mov a2, r8 167d7950be1SGuo Ren lrw r26, prepare_ftrace_return 168d7950be1SGuo Ren jsr r26 169d7950be1SGuo Ren mcount_exit 170d7950be1SGuo RenEND(ftrace_graph_caller) 171d7950be1SGuo Ren 172d7950be1SGuo RenENTRY(return_to_handler) 173d7950be1SGuo Ren save_return_regs 174d7950be1SGuo Ren mov a0, r8 175d7950be1SGuo Ren jsri ftrace_return_to_handler 176d7950be1SGuo Ren restore_return_regs 177d7950be1SGuo Ren jmp lr 178d7950be1SGuo RenEND(return_to_handler) 179d7950be1SGuo Ren#endif 180*89a3927aSGuo Ren 181*89a3927aSGuo Ren#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS 182*89a3927aSGuo RenENTRY(ftrace_regs_caller) 183*89a3927aSGuo Ren mcount_enter_regs 184*89a3927aSGuo Ren 185*89a3927aSGuo Ren lrw t1, PT_FRAME_SIZE 186*89a3927aSGuo Ren add t1, sp 187*89a3927aSGuo Ren 188*89a3927aSGuo Ren ldw a0, (t1, 0) 189*89a3927aSGuo Ren subi a0, 4 190*89a3927aSGuo Ren ldw a1, (t1, 8) 191*89a3927aSGuo Ren lrw a2, function_trace_op 192*89a3927aSGuo Ren ldw a2, (a2, 0) 193*89a3927aSGuo Ren mov a3, sp 194*89a3927aSGuo Ren 195*89a3927aSGuo Ren nop 196*89a3927aSGuo RenGLOBAL(ftrace_regs_call) 197*89a3927aSGuo Ren nop32_stub 198*89a3927aSGuo Ren 199*89a3927aSGuo Ren#ifdef CONFIG_FUNCTION_GRAPH_TRACER 200*89a3927aSGuo Ren nop 201*89a3927aSGuo RenGLOBAL(ftrace_graph_regs_call) 202*89a3927aSGuo Ren nop32_stub 203*89a3927aSGuo Ren#endif 204*89a3927aSGuo Ren 205*89a3927aSGuo Ren mcount_exit_regs 206*89a3927aSGuo RenENDPROC(ftrace_regs_caller) 207*89a3927aSGuo Ren#endif /* CONFIG_DYNAMIC_FTRACE */ 208