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