1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun#include <linux/linkage.h> 5*4882a593Smuzhiyun#include <asm/ftrace.h> 6*4882a593Smuzhiyun#include <abi/entry.h> 7*4882a593Smuzhiyun#include <asm/asm-offsets.h> 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun/* 10*4882a593Smuzhiyun * csky-gcc with -pg will put the following asm after prologue: 11*4882a593Smuzhiyun * push r15 12*4882a593Smuzhiyun * jsri _mcount 13*4882a593Smuzhiyun * 14*4882a593Smuzhiyun * stack layout after mcount_enter in _mcount(): 15*4882a593Smuzhiyun * 16*4882a593Smuzhiyun * current sp => 0:+-------+ 17*4882a593Smuzhiyun * | a0-a3 | -> must save all argument regs 18*4882a593Smuzhiyun * +16:+-------+ 19*4882a593Smuzhiyun * | lr | -> _mcount lr (instrumente function's pc) 20*4882a593Smuzhiyun * +20:+-------+ 21*4882a593Smuzhiyun * | fp=r8 | -> instrumented function fp 22*4882a593Smuzhiyun * +24:+-------+ 23*4882a593Smuzhiyun * | plr | -> instrumented function lr (parent's pc) 24*4882a593Smuzhiyun * +-------+ 25*4882a593Smuzhiyun */ 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun.macro mcount_enter 28*4882a593Smuzhiyun subi sp, 24 29*4882a593Smuzhiyun stw a0, (sp, 0) 30*4882a593Smuzhiyun stw a1, (sp, 4) 31*4882a593Smuzhiyun stw a2, (sp, 8) 32*4882a593Smuzhiyun stw a3, (sp, 12) 33*4882a593Smuzhiyun stw lr, (sp, 16) 34*4882a593Smuzhiyun stw r8, (sp, 20) 35*4882a593Smuzhiyun.endm 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun.macro mcount_exit 38*4882a593Smuzhiyun ldw a0, (sp, 0) 39*4882a593Smuzhiyun ldw a1, (sp, 4) 40*4882a593Smuzhiyun ldw a2, (sp, 8) 41*4882a593Smuzhiyun ldw a3, (sp, 12) 42*4882a593Smuzhiyun ldw t1, (sp, 16) 43*4882a593Smuzhiyun ldw r8, (sp, 20) 44*4882a593Smuzhiyun ldw lr, (sp, 24) 45*4882a593Smuzhiyun addi sp, 28 46*4882a593Smuzhiyun jmp t1 47*4882a593Smuzhiyun.endm 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun.macro mcount_enter_regs 50*4882a593Smuzhiyun subi sp, 8 51*4882a593Smuzhiyun stw lr, (sp, 0) 52*4882a593Smuzhiyun stw r8, (sp, 4) 53*4882a593Smuzhiyun SAVE_REGS_FTRACE 54*4882a593Smuzhiyun.endm 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun.macro mcount_exit_regs 57*4882a593Smuzhiyun RESTORE_REGS_FTRACE 58*4882a593Smuzhiyun subi sp, 152 59*4882a593Smuzhiyun ldw t1, (sp, 4) 60*4882a593Smuzhiyun addi sp, 152 61*4882a593Smuzhiyun ldw r8, (sp, 4) 62*4882a593Smuzhiyun ldw lr, (sp, 8) 63*4882a593Smuzhiyun addi sp, 12 64*4882a593Smuzhiyun jmp t1 65*4882a593Smuzhiyun.endm 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun.macro save_return_regs 68*4882a593Smuzhiyun subi sp, 16 69*4882a593Smuzhiyun stw a0, (sp, 0) 70*4882a593Smuzhiyun stw a1, (sp, 4) 71*4882a593Smuzhiyun stw a2, (sp, 8) 72*4882a593Smuzhiyun stw a3, (sp, 12) 73*4882a593Smuzhiyun.endm 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun.macro restore_return_regs 76*4882a593Smuzhiyun mov lr, a0 77*4882a593Smuzhiyun ldw a0, (sp, 0) 78*4882a593Smuzhiyun ldw a1, (sp, 4) 79*4882a593Smuzhiyun ldw a2, (sp, 8) 80*4882a593Smuzhiyun ldw a3, (sp, 12) 81*4882a593Smuzhiyun addi sp, 16 82*4882a593Smuzhiyun.endm 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun.macro nop32_stub 85*4882a593Smuzhiyun nop32 86*4882a593Smuzhiyun nop32 87*4882a593Smuzhiyun nop32 88*4882a593Smuzhiyun.endm 89*4882a593Smuzhiyun 90*4882a593SmuzhiyunENTRY(ftrace_stub) 91*4882a593Smuzhiyun jmp lr 92*4882a593SmuzhiyunEND(ftrace_stub) 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun#ifndef CONFIG_DYNAMIC_FTRACE 95*4882a593SmuzhiyunENTRY(_mcount) 96*4882a593Smuzhiyun mcount_enter 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun /* r26 is link register, only used with jsri translation */ 99*4882a593Smuzhiyun lrw r26, ftrace_trace_function 100*4882a593Smuzhiyun ldw r26, (r26, 0) 101*4882a593Smuzhiyun lrw a1, ftrace_stub 102*4882a593Smuzhiyun cmpne r26, a1 103*4882a593Smuzhiyun bf skip_ftrace 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun mov a0, lr 106*4882a593Smuzhiyun subi a0, 4 107*4882a593Smuzhiyun ldw a1, (sp, 24) 108*4882a593Smuzhiyun lrw a2, function_trace_op 109*4882a593Smuzhiyun ldw a2, (a2, 0) 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun jsr r26 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun#ifndef CONFIG_FUNCTION_GRAPH_TRACER 114*4882a593Smuzhiyunskip_ftrace: 115*4882a593Smuzhiyun mcount_exit 116*4882a593Smuzhiyun#else 117*4882a593Smuzhiyunskip_ftrace: 118*4882a593Smuzhiyun lrw a0, ftrace_graph_return 119*4882a593Smuzhiyun ldw a0, (a0, 0) 120*4882a593Smuzhiyun lrw a1, ftrace_stub 121*4882a593Smuzhiyun cmpne a0, a1 122*4882a593Smuzhiyun bt ftrace_graph_caller 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun lrw a0, ftrace_graph_entry 125*4882a593Smuzhiyun ldw a0, (a0, 0) 126*4882a593Smuzhiyun lrw a1, ftrace_graph_entry_stub 127*4882a593Smuzhiyun cmpne a0, a1 128*4882a593Smuzhiyun bt ftrace_graph_caller 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun mcount_exit 131*4882a593Smuzhiyun#endif 132*4882a593SmuzhiyunEND(_mcount) 133*4882a593Smuzhiyun#else /* CONFIG_DYNAMIC_FTRACE */ 134*4882a593SmuzhiyunENTRY(_mcount) 135*4882a593Smuzhiyun mov t1, lr 136*4882a593Smuzhiyun ldw lr, (sp, 0) 137*4882a593Smuzhiyun addi sp, 4 138*4882a593Smuzhiyun jmp t1 139*4882a593SmuzhiyunENDPROC(_mcount) 140*4882a593Smuzhiyun 141*4882a593SmuzhiyunENTRY(ftrace_caller) 142*4882a593Smuzhiyun mcount_enter 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun ldw a0, (sp, 16) 145*4882a593Smuzhiyun subi a0, 4 146*4882a593Smuzhiyun ldw a1, (sp, 24) 147*4882a593Smuzhiyun lrw a2, function_trace_op 148*4882a593Smuzhiyun ldw a2, (a2, 0) 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun nop 151*4882a593SmuzhiyunGLOBAL(ftrace_call) 152*4882a593Smuzhiyun nop32_stub 153*4882a593Smuzhiyun 154*4882a593Smuzhiyun#ifdef CONFIG_FUNCTION_GRAPH_TRACER 155*4882a593Smuzhiyun nop 156*4882a593SmuzhiyunGLOBAL(ftrace_graph_call) 157*4882a593Smuzhiyun nop32_stub 158*4882a593Smuzhiyun#endif 159*4882a593Smuzhiyun 160*4882a593Smuzhiyun mcount_exit 161*4882a593SmuzhiyunENDPROC(ftrace_caller) 162*4882a593Smuzhiyun#endif /* CONFIG_DYNAMIC_FTRACE */ 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun#ifdef CONFIG_FUNCTION_GRAPH_TRACER 165*4882a593SmuzhiyunENTRY(ftrace_graph_caller) 166*4882a593Smuzhiyun mov a0, sp 167*4882a593Smuzhiyun addi a0, 24 168*4882a593Smuzhiyun ldw a1, (sp, 16) 169*4882a593Smuzhiyun subi a1, 4 170*4882a593Smuzhiyun mov a2, r8 171*4882a593Smuzhiyun lrw r26, prepare_ftrace_return 172*4882a593Smuzhiyun jsr r26 173*4882a593Smuzhiyun mcount_exit 174*4882a593SmuzhiyunEND(ftrace_graph_caller) 175*4882a593Smuzhiyun 176*4882a593SmuzhiyunENTRY(return_to_handler) 177*4882a593Smuzhiyun save_return_regs 178*4882a593Smuzhiyun mov a0, r8 179*4882a593Smuzhiyun jsri ftrace_return_to_handler 180*4882a593Smuzhiyun restore_return_regs 181*4882a593Smuzhiyun jmp lr 182*4882a593SmuzhiyunEND(return_to_handler) 183*4882a593Smuzhiyun#endif 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS 186*4882a593SmuzhiyunENTRY(ftrace_regs_caller) 187*4882a593Smuzhiyun mcount_enter_regs 188*4882a593Smuzhiyun 189*4882a593Smuzhiyun lrw t1, PT_FRAME_SIZE 190*4882a593Smuzhiyun add t1, sp 191*4882a593Smuzhiyun 192*4882a593Smuzhiyun ldw a0, (t1, 0) 193*4882a593Smuzhiyun subi a0, 4 194*4882a593Smuzhiyun ldw a1, (t1, 8) 195*4882a593Smuzhiyun lrw a2, function_trace_op 196*4882a593Smuzhiyun ldw a2, (a2, 0) 197*4882a593Smuzhiyun mov a3, sp 198*4882a593Smuzhiyun 199*4882a593Smuzhiyun nop 200*4882a593SmuzhiyunGLOBAL(ftrace_regs_call) 201*4882a593Smuzhiyun nop32_stub 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun#ifdef CONFIG_FUNCTION_GRAPH_TRACER 204*4882a593Smuzhiyun nop 205*4882a593SmuzhiyunGLOBAL(ftrace_graph_regs_call) 206*4882a593Smuzhiyun nop32_stub 207*4882a593Smuzhiyun#endif 208*4882a593Smuzhiyun 209*4882a593Smuzhiyun mcount_exit_regs 210*4882a593SmuzhiyunENDPROC(ftrace_regs_caller) 211*4882a593Smuzhiyun#endif /* CONFIG_DYNAMIC_FTRACE */ 212