1/* SPDX-License-Identifier: GPL-2.0 */ 2/* Copyright (C) 2017 Andes Technology Corporation */ 3 4#include <linux/init.h> 5#include <linux/linkage.h> 6#include <linux/cfi_types.h> 7#include <linux/export.h> 8#include <asm/asm.h> 9#include <asm/csr.h> 10#include <asm/unistd.h> 11#include <asm/thread_info.h> 12#include <asm/asm-offsets.h> 13#include <asm/ftrace.h> 14 15 .text 16 17 .macro SAVE_ABI_STATE 18 addi sp, sp, -16 19 REG_S s0, 0*SZREG(sp) 20 REG_S ra, 1*SZREG(sp) 21 addi s0, sp, 16 22 .endm 23 24 /* 25 * The call to ftrace_return_to_handler would overwrite the return 26 * register if a0 was not saved. 27 */ 28 .macro SAVE_RET_ABI_STATE 29 addi sp, sp, -4*SZREG 30 REG_S s0, 2*SZREG(sp) 31 REG_S ra, 3*SZREG(sp) 32 REG_S a0, 1*SZREG(sp) 33 REG_S a1, 0*SZREG(sp) 34 addi s0, sp, 4*SZREG 35 .endm 36 37 .macro RESTORE_ABI_STATE 38 REG_L ra, 1*SZREG(sp) 39 REG_L s0, 0*SZREG(sp) 40 addi sp, sp, 16 41 .endm 42 43 .macro RESTORE_RET_ABI_STATE 44 REG_L ra, 3*SZREG(sp) 45 REG_L s0, 2*SZREG(sp) 46 REG_L a0, 1*SZREG(sp) 47 REG_L a1, 0*SZREG(sp) 48 addi sp, sp, 4*SZREG 49 .endm 50 51SYM_TYPED_FUNC_START(ftrace_stub) 52#ifdef CONFIG_DYNAMIC_FTRACE 53 .global _mcount 54 .set _mcount, ftrace_stub 55#endif 56 ret 57SYM_FUNC_END(ftrace_stub) 58 59#ifdef CONFIG_FUNCTION_GRAPH_TRACER 60SYM_TYPED_FUNC_START(ftrace_stub_graph) 61 ret 62SYM_FUNC_END(ftrace_stub_graph) 63 64SYM_FUNC_START(return_to_handler) 65/* 66 * On implementing the frame point test, the ideal way is to compare the 67 * s0 (frame pointer, if enabled) on entry and the sp (stack pointer) on return. 68 * However, the psABI of variable-length-argument functions does not allow this. 69 * 70 * So alternatively we check the *old* frame pointer position, that is, the 71 * value stored in -16(s0) on entry, and the s0 on return. 72 */ 73 SAVE_RET_ABI_STATE 74 mv a0, sp 75 call ftrace_return_to_handler 76 mv a2, a0 77 RESTORE_RET_ABI_STATE 78 jalr a2 79SYM_FUNC_END(return_to_handler) 80#endif 81 82#ifndef CONFIG_DYNAMIC_FTRACE 83SYM_FUNC_START(_mcount) 84 la t4, ftrace_stub 85#ifdef CONFIG_FUNCTION_GRAPH_TRACER 86 la t0, ftrace_graph_return 87 REG_L t1, 0(t0) 88 bne t1, t4, .Ldo_ftrace_graph_caller 89 90 la t3, ftrace_graph_entry 91 REG_L t2, 0(t3) 92 la t6, ftrace_graph_entry_stub 93 bne t2, t6, .Ldo_ftrace_graph_caller 94#endif 95 la t3, ftrace_trace_function 96 REG_L t5, 0(t3) 97 bne t5, t4, .Ldo_trace 98 ret 99 100#ifdef CONFIG_FUNCTION_GRAPH_TRACER 101/* 102 * A pseudo representation for the function graph tracer: 103 * prepare_to_return(&ra_to_caller_of_caller, ra_to_caller) 104 */ 105.Ldo_ftrace_graph_caller: 106 addi a0, s0, -SZREG 107 mv a1, ra 108#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 109 REG_L a2, -2*SZREG(s0) 110#endif 111 SAVE_ABI_STATE 112 call prepare_ftrace_return 113 RESTORE_ABI_STATE 114 ret 115#endif 116 117/* 118 * A pseudo representation for the function tracer: 119 * (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller) 120 */ 121.Ldo_trace: 122 REG_L a1, -SZREG(s0) 123 mv a0, ra 124 125 SAVE_ABI_STATE 126 jalr t5 127 RESTORE_ABI_STATE 128 ret 129SYM_FUNC_END(_mcount) 130#endif 131EXPORT_SYMBOL(_mcount) 132