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 STORE_ABI_STATE 36 ld ra, 8(sp) 37 ld s0, 0(sp) 38 addi sp, sp, 16 39 .endm 40 41 .macro STORE_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 48ENTRY(ftrace_stub) 49 ret 50ENDPROC(ftrace_stub) 51 52#ifdef CONFIG_FUNCTION_GRAPH_TRACER 53ENTRY(return_to_handler) 54/* 55 * On implementing the frame point test, the ideal way is to compare the 56 * s0 (frame pointer, if enabled) on entry and the sp (stack pointer) on return. 57 * However, the psABI of variable-length-argument functions does not allow this. 58 * 59 * So alternatively we check the *old* frame pointer position, that is, the 60 * value stored in -16(s0) on entry, and the s0 on return. 61 */ 62#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 63 mv t6, s0 64#endif 65 SAVE_RET_ABI_STATE 66#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 67 mv a0, t6 68#endif 69 la t0, ftrace_return_to_handler 70 jalr t0 71 mv a1, a0 72 STORE_RET_ABI_STATE 73 jalr a1 74ENDPROC(return_to_handler) 75EXPORT_SYMBOL(return_to_handler) 76#endif 77 78ENTRY(_mcount) 79 la t4, ftrace_stub 80#ifdef CONFIG_FUNCTION_GRAPH_TRACER 81 la t0, ftrace_graph_return 82 ld t1, 0(t0) 83 bne t1, t4, do_ftrace_graph_caller 84 85 la t3, ftrace_graph_entry 86 ld 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 ld 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, -8 102 mv a1, ra 103#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 104 ld a2, -16(s0) 105#endif 106 SAVE_ABI_STATE 107 la t0, prepare_ftrace_return 108 jalr t0 109 STORE_ABI_STATE 110 ret 111#endif 112 113/* 114 * A pseudo representation for the function tracer: 115 * (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller) 116 */ 117do_trace: 118 ld a1, -8(s0) 119 mv a0, ra 120 121 SAVE_ABI_STATE 122 jalr t5 123 STORE_ABI_STATE 124 ret 125ENDPROC(_mcount) 126EXPORT_SYMBOL(_mcount) 127