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