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 48ENTRY(ftrace_stub) 49#ifdef CONFIG_DYNAMIC_FTRACE 50 .global _mcount 51 .set _mcount, ftrace_stub 52#endif 53 ret 54ENDPROC(ftrace_stub) 55 56#ifdef CONFIG_FUNCTION_GRAPH_TRACER 57ENTRY(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 77ENDPROC(return_to_handler) 78EXPORT_SYMBOL(return_to_handler) 79#endif 80 81#ifndef CONFIG_DYNAMIC_FTRACE 82ENTRY(_mcount) 83 la t4, ftrace_stub 84#ifdef CONFIG_FUNCTION_GRAPH_TRACER 85 la t0, ftrace_graph_return 86 ld t1, 0(t0) 87 bne t1, t4, do_ftrace_graph_caller 88 89 la t3, ftrace_graph_entry 90 ld t2, 0(t3) 91 la t6, ftrace_graph_entry_stub 92 bne t2, t6, do_ftrace_graph_caller 93#endif 94 la t3, ftrace_trace_function 95 ld t5, 0(t3) 96 bne t5, t4, do_trace 97 ret 98 99#ifdef CONFIG_FUNCTION_GRAPH_TRACER 100/* 101 * A pseudo representation for the function graph tracer: 102 * prepare_to_return(&ra_to_caller_of_caller, ra_to_caller) 103 */ 104do_ftrace_graph_caller: 105 addi a0, s0, -8 106 mv a1, ra 107#ifdef HAVE_FUNCTION_GRAPH_FP_TEST 108 ld a2, -16(s0) 109#endif 110 SAVE_ABI_STATE 111 call prepare_ftrace_return 112 RESTORE_ABI_STATE 113 ret 114#endif 115 116/* 117 * A pseudo representation for the function tracer: 118 * (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller) 119 */ 120do_trace: 121 ld a1, -8(s0) 122 mv a0, ra 123 124 SAVE_ABI_STATE 125 jalr t5 126 RESTORE_ABI_STATE 127 ret 128ENDPROC(_mcount) 129EXPORT_SYMBOL(_mcount) 130#endif 131