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> 689a3927aSGuo Ren#include <abi/entry.h> 789a3927aSGuo 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 4989a3927aSGuo Ren.macro mcount_enter_regs 5089a3927aSGuo Ren subi sp, 8 5189a3927aSGuo Ren stw lr, (sp, 0) 5289a3927aSGuo Ren stw r8, (sp, 4) 5389a3927aSGuo Ren SAVE_REGS_FTRACE 5489a3927aSGuo Ren.endm 5589a3927aSGuo Ren 5689a3927aSGuo Ren.macro mcount_exit_regs 5789a3927aSGuo Ren RESTORE_REGS_FTRACE 5889a3927aSGuo Ren ldw t1, (sp, 0) 5989a3927aSGuo Ren ldw r8, (sp, 4) 6089a3927aSGuo Ren ldw lr, (sp, 8) 6189a3927aSGuo Ren addi sp, 12 6289a3927aSGuo Ren jmp t1 6389a3927aSGuo Ren.endm 6489a3927aSGuo 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) 106*a13d5887SGuo Ren lrw a2, function_trace_op 107*a13d5887SGuo Ren ldw a2, (a2, 0) 108d7950be1SGuo Ren 109d7950be1SGuo Ren jsr r26 110d7950be1SGuo Ren 111d7950be1SGuo Ren#ifndef CONFIG_FUNCTION_GRAPH_TRACER 112d7950be1SGuo Renskip_ftrace: 113d7950be1SGuo Ren mcount_exit 114d7950be1SGuo Ren#else 115d7950be1SGuo Renskip_ftrace: 116d7950be1SGuo Ren lrw a0, ftrace_graph_return 117d7950be1SGuo Ren ldw a0, (a0, 0) 118d7950be1SGuo Ren lrw a1, ftrace_stub 119d7950be1SGuo Ren cmpne a0, a1 120d7950be1SGuo Ren bt ftrace_graph_caller 121d7950be1SGuo Ren 122d7950be1SGuo Ren lrw a0, ftrace_graph_entry 123d7950be1SGuo Ren ldw a0, (a0, 0) 124d7950be1SGuo Ren lrw a1, ftrace_graph_entry_stub 125d7950be1SGuo Ren cmpne a0, a1 126d7950be1SGuo Ren bt ftrace_graph_caller 127d7950be1SGuo Ren 128d7950be1SGuo Ren mcount_exit 129d7950be1SGuo Ren#endif 130230c77a5SGuo RenEND(_mcount) 13128bb030fSGuo Ren#else /* CONFIG_DYNAMIC_FTRACE */ 13228bb030fSGuo RenENTRY(_mcount) 13328bb030fSGuo Ren mov t1, lr 13428bb030fSGuo Ren ldw lr, (sp, 0) 13528bb030fSGuo Ren addi sp, 4 13628bb030fSGuo Ren jmp t1 13728bb030fSGuo RenENDPROC(_mcount) 13828bb030fSGuo Ren 13928bb030fSGuo RenENTRY(ftrace_caller) 14028bb030fSGuo Ren mcount_enter 14128bb030fSGuo Ren 14228bb030fSGuo Ren ldw a0, (sp, 16) 14328bb030fSGuo Ren subi a0, 4 14428bb030fSGuo Ren ldw a1, (sp, 24) 14589a3927aSGuo Ren lrw a2, function_trace_op 14689a3927aSGuo Ren ldw a2, (a2, 0) 14728bb030fSGuo Ren 14828bb030fSGuo Ren nop 14928bb030fSGuo RenGLOBAL(ftrace_call) 15028bb030fSGuo Ren nop32_stub 15128bb030fSGuo Ren 15228bb030fSGuo Ren#ifdef CONFIG_FUNCTION_GRAPH_TRACER 15328bb030fSGuo Ren nop 15428bb030fSGuo RenGLOBAL(ftrace_graph_call) 15528bb030fSGuo Ren nop32_stub 15628bb030fSGuo Ren#endif 15728bb030fSGuo Ren 15828bb030fSGuo Ren mcount_exit 15928bb030fSGuo RenENDPROC(ftrace_caller) 16028bb030fSGuo Ren#endif /* CONFIG_DYNAMIC_FTRACE */ 161d7950be1SGuo Ren 162d7950be1SGuo Ren#ifdef CONFIG_FUNCTION_GRAPH_TRACER 163d7950be1SGuo RenENTRY(ftrace_graph_caller) 164d7950be1SGuo Ren mov a0, sp 165d7950be1SGuo Ren addi a0, 24 166d7950be1SGuo Ren ldw a1, (sp, 16) 16728bb030fSGuo Ren subi a1, 4 168d7950be1SGuo Ren mov a2, r8 169d7950be1SGuo Ren lrw r26, prepare_ftrace_return 170d7950be1SGuo Ren jsr r26 171d7950be1SGuo Ren mcount_exit 172d7950be1SGuo RenEND(ftrace_graph_caller) 173d7950be1SGuo Ren 174d7950be1SGuo RenENTRY(return_to_handler) 175d7950be1SGuo Ren save_return_regs 176d7950be1SGuo Ren mov a0, r8 177d7950be1SGuo Ren jsri ftrace_return_to_handler 178d7950be1SGuo Ren restore_return_regs 179d7950be1SGuo Ren jmp lr 180d7950be1SGuo RenEND(return_to_handler) 181d7950be1SGuo Ren#endif 18289a3927aSGuo Ren 18389a3927aSGuo Ren#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS 18489a3927aSGuo RenENTRY(ftrace_regs_caller) 18589a3927aSGuo Ren mcount_enter_regs 18689a3927aSGuo Ren 18789a3927aSGuo Ren lrw t1, PT_FRAME_SIZE 18889a3927aSGuo Ren add t1, sp 18989a3927aSGuo Ren 19089a3927aSGuo Ren ldw a0, (t1, 0) 19189a3927aSGuo Ren subi a0, 4 19289a3927aSGuo Ren ldw a1, (t1, 8) 19389a3927aSGuo Ren lrw a2, function_trace_op 19489a3927aSGuo Ren ldw a2, (a2, 0) 19589a3927aSGuo Ren mov a3, sp 19689a3927aSGuo Ren 19789a3927aSGuo Ren nop 19889a3927aSGuo RenGLOBAL(ftrace_regs_call) 19989a3927aSGuo Ren nop32_stub 20089a3927aSGuo Ren 20189a3927aSGuo Ren#ifdef CONFIG_FUNCTION_GRAPH_TRACER 20289a3927aSGuo Ren nop 20389a3927aSGuo RenGLOBAL(ftrace_graph_regs_call) 20489a3927aSGuo Ren nop32_stub 20589a3927aSGuo Ren#endif 20689a3927aSGuo Ren 20789a3927aSGuo Ren mcount_exit_regs 20889a3927aSGuo RenENDPROC(ftrace_regs_caller) 20989a3927aSGuo Ren#endif /* CONFIG_DYNAMIC_FTRACE */ 210