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#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 69 mv t6, s0 70#endif 71 SAVE_RET_ABI_STATE 72#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 73 mv a0, t6 74#endif 75 call ftrace_return_to_handler 76 mv a2, a0 77 RESTORE_RET_ABI_STATE 78 jalr a2 79ENDPROC(return_to_handler) 80#endif 81 82#ifndef CONFIG_DYNAMIC_FTRACE 83ENTRY(MCOUNT_NAME) 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, do_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, do_ftrace_graph_caller 94#endif 95 la t3, ftrace_trace_function 96 REG_L t5, 0(t3) 97 bne t5, t4, do_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 */ 105do_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 */ 121do_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 129ENDPROC(MCOUNT_NAME) 130#endif 131EXPORT_SYMBOL(MCOUNT_NAME) 132