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 <linux/cfi_types.h>
7#include <linux/export.h>
8#include <asm/asm.h>
9#include <asm/csr.h>
10#include <asm/unistd.h>
11#include <asm/thread_info.h>
12#include <asm/asm-offsets.h>
13#include <asm/ftrace.h>
14
15 .text
16
17 .macro SAVE_ABI_STATE
18 addi sp, sp, -16
19 REG_S s0, 0*SZREG(sp)
20 REG_S ra, 1*SZREG(sp)
21 addi s0, sp, 16
22 .endm
23
24 /*
25 * The call to ftrace_return_to_handler would overwrite the return
26 * register if a0 was not saved.
27 */
28 .macro SAVE_RET_ABI_STATE
29 addi sp, sp, -4*SZREG
30 REG_S s0, 2*SZREG(sp)
31 REG_S ra, 3*SZREG(sp)
32 REG_S a0, 1*SZREG(sp)
33 REG_S a1, 0*SZREG(sp)
34 addi s0, sp, 4*SZREG
35 .endm
36
37 .macro RESTORE_ABI_STATE
38 REG_L ra, 1*SZREG(sp)
39 REG_L s0, 0*SZREG(sp)
40 addi sp, sp, 16
41 .endm
42
43 .macro RESTORE_RET_ABI_STATE
44 REG_L ra, 3*SZREG(sp)
45 REG_L s0, 2*SZREG(sp)
46 REG_L a0, 1*SZREG(sp)
47 REG_L a1, 0*SZREG(sp)
48 addi sp, sp, 4*SZREG
49 .endm
50
51SYM_TYPED_FUNC_START(ftrace_stub)
52#ifdef CONFIG_DYNAMIC_FTRACE
53 .global _mcount
54 .set _mcount, ftrace_stub
55#endif
56 ret
57SYM_FUNC_END(ftrace_stub)
58
59#ifdef CONFIG_FUNCTION_GRAPH_TRACER
60SYM_TYPED_FUNC_START(ftrace_stub_graph)
61 ret
62SYM_FUNC_END(ftrace_stub_graph)
63
64SYM_FUNC_START(return_to_handler)
65/*
66 * On implementing the frame point test, the ideal way is to compare the
67 * s0 (frame pointer, if enabled) on entry and the sp (stack pointer) on return.
68 * However, the psABI of variable-length-argument functions does not allow this.
69 *
70 * So alternatively we check the *old* frame pointer position, that is, the
71 * value stored in -16(s0) on entry, and the s0 on return.
72 */
73 SAVE_RET_ABI_STATE
74 mv a0, sp
75 call ftrace_return_to_handler
76 mv a2, a0
77 RESTORE_RET_ABI_STATE
78 jalr a2
79SYM_FUNC_END(return_to_handler)
80#endif
81
82#ifndef CONFIG_DYNAMIC_FTRACE
83SYM_FUNC_START(_mcount)
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, .Ldo_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, .Ldo_ftrace_graph_caller
94#endif
95 la t3, ftrace_trace_function
96 REG_L t5, 0(t3)
97 bne t5, t4, .Ldo_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 */
105.Ldo_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 */
121.Ldo_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
129SYM_FUNC_END(_mcount)
130#endif
131EXPORT_SYMBOL(_mcount)
132

source code of linux/arch/riscv/kernel/mcount.S