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