1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright (C) 2022 Loongson Technology Corporation Limited 4 */ 5 6#include <asm/ftrace.h> 7#include <asm/regdef.h> 8#include <asm/stackframe.h> 9 10 .text 11/* 12 * Due to -fpatchable-function-entry=2: the compiler inserted 2 NOPs before the 13 * regular C function prologue. When PC arrived here, the last 2 instructions 14 * are as follows: 15 * move t0, ra 16 * bl callsite (for modules, callsite is a tramplione) 17 * 18 * modules trampoline is as follows: 19 * lu12i.w t1, callsite[31:12] 20 * lu32i.d t1, callsite[51:32] 21 * lu52i.d t1, t1, callsite[63:52] 22 * jirl zero, t1, callsite[11:0] >> 2 23 * 24 * See arch/loongarch/kernel/ftrace_dyn.c for details. Here, pay attention to 25 * that the T series regs are available and safe because each C functions 26 * follows the LoongArch's psABI as well. 27 */ 28 29 .macro ftrace_regs_entry allregs=0 30 PTR_ADDI sp, sp, -PT_SIZE 31 PTR_S t0, sp, PT_R1 /* Save parent ra at PT_R1(RA) */ 32 PTR_S a0, sp, PT_R4 33 PTR_S a1, sp, PT_R5 34 PTR_S a2, sp, PT_R6 35 PTR_S a3, sp, PT_R7 36 PTR_S a4, sp, PT_R8 37 PTR_S a5, sp, PT_R9 38 PTR_S a6, sp, PT_R10 39 PTR_S a7, sp, PT_R11 40 PTR_S fp, sp, PT_R22 41 .if \allregs 42 PTR_S tp, sp, PT_R2 43 PTR_S t0, sp, PT_R12 44 PTR_S t2, sp, PT_R14 45 PTR_S t3, sp, PT_R15 46 PTR_S t4, sp, PT_R16 47 PTR_S t5, sp, PT_R17 48 PTR_S t6, sp, PT_R18 49 PTR_S t7, sp, PT_R19 50 PTR_S t8, sp, PT_R20 51 PTR_S u0, sp, PT_R21 52 PTR_S s0, sp, PT_R23 53 PTR_S s1, sp, PT_R24 54 PTR_S s2, sp, PT_R25 55 PTR_S s3, sp, PT_R26 56 PTR_S s4, sp, PT_R27 57 PTR_S s5, sp, PT_R28 58 PTR_S s6, sp, PT_R29 59 PTR_S s7, sp, PT_R30 60 PTR_S s8, sp, PT_R31 61 /* Clear it for later use as a flag sometimes. */ 62 PTR_S zero, sp, PT_R0 63 .endif 64 PTR_S ra, sp, PT_ERA /* Save trace function ra at PT_ERA */ 65 move t1, zero 66 PTR_S t1, sp, PT_R13 67 PTR_ADDI t8, sp, PT_SIZE 68 PTR_S t8, sp, PT_R3 69 .endm 70 71SYM_FUNC_START(ftrace_stub) 72 jr ra 73SYM_FUNC_END(ftrace_stub) 74 75SYM_CODE_START(ftrace_common) 76 UNWIND_HINT_UNDEFINED 77 PTR_ADDI a0, ra, -8 /* arg0: ip */ 78 move a1, t0 /* arg1: parent_ip */ 79 la.pcrel t1, function_trace_op 80 PTR_L a2, t1, 0 /* arg2: op */ 81 move a3, sp /* arg3: regs */ 82 83SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 84 bl ftrace_stub 85#ifdef CONFIG_FUNCTION_GRAPH_TRACER 86SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL) 87 nop /* b ftrace_graph_caller */ 88#endif 89 90/* 91 * As we didn't use S series regs in this assmembly code and all calls 92 * are C function which will save S series regs by themselves, there is 93 * no need to restore S series regs. The T series is available and safe 94 * at the callsite, so there is no need to restore the T series regs. 95 */ 96ftrace_common_return: 97 PTR_L a0, sp, PT_R4 98 PTR_L a1, sp, PT_R5 99 PTR_L a2, sp, PT_R6 100 PTR_L a3, sp, PT_R7 101 PTR_L a4, sp, PT_R8 102 PTR_L a5, sp, PT_R9 103 PTR_L a6, sp, PT_R10 104 PTR_L a7, sp, PT_R11 105 PTR_L fp, sp, PT_R22 106 PTR_L t1, sp, PT_R13 107 bnez t1, .Ldirect 108 109 PTR_L ra, sp, PT_R1 110 PTR_L t0, sp, PT_ERA 111 PTR_ADDI sp, sp, PT_SIZE 112 jr t0 113.Ldirect: 114 PTR_L t0, sp, PT_R1 115 PTR_L ra, sp, PT_ERA 116 PTR_ADDI sp, sp, PT_SIZE 117 jr t1 118SYM_CODE_END(ftrace_common) 119 120SYM_CODE_START(ftrace_caller) 121 UNWIND_HINT_UNDEFINED 122 ftrace_regs_entry allregs=0 123 b ftrace_common 124SYM_CODE_END(ftrace_caller) 125 126#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS 127SYM_CODE_START(ftrace_regs_caller) 128 UNWIND_HINT_UNDEFINED 129 ftrace_regs_entry allregs=1 130 b ftrace_common 131SYM_CODE_END(ftrace_regs_caller) 132#endif 133 134#ifdef CONFIG_FUNCTION_GRAPH_TRACER 135SYM_CODE_START(ftrace_graph_caller) 136 UNWIND_HINT_UNDEFINED 137 PTR_L a0, sp, PT_ERA 138 PTR_ADDI a0, a0, -8 /* arg0: self_addr */ 139 PTR_ADDI a1, sp, PT_R1 /* arg1: parent */ 140 bl prepare_ftrace_return 141 b ftrace_common_return 142SYM_CODE_END(ftrace_graph_caller) 143 144SYM_CODE_START(return_to_handler) 145 UNWIND_HINT_UNDEFINED 146 /* Save return value regs */ 147 PTR_ADDI sp, sp, -PT_SIZE 148 PTR_S a0, sp, PT_R4 149 PTR_S a1, sp, PT_R5 150 PTR_S zero, sp, PT_R22 151 152 move a0, sp 153 bl ftrace_return_to_handler 154 move ra, a0 155 156 /* Restore return value regs */ 157 PTR_L a0, sp, PT_R4 158 PTR_L a1, sp, PT_R5 159 PTR_ADDI sp, sp, PT_SIZE 160 161 jr ra 162SYM_CODE_END(return_to_handler) 163#endif 164 165#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 166SYM_CODE_START(ftrace_stub_direct_tramp) 167 UNWIND_HINT_UNDEFINED 168 move t1, ra 169 move ra, t0 170 jr t1 171SYM_CODE_END(ftrace_stub_direct_tramp) 172#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ 173