Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fgraph: Replace fgraph_ret_regs with ftrace_regs

Use ftrace_regs instead of fgraph_ret_regs for tracing return value
on function_graph tracer because of simplifying the callback interface.

The CONFIG_HAVE_FUNCTION_GRAPH_RETVAL is also replaced by
CONFIG_HAVE_FUNCTION_GRAPH_FREGS.

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Acked-by: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Florent Revest <revest@chromium.org>
Cc: Martin KaFai Lau <martin.lau@linux.dev>
Cc: bpf <bpf@vger.kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Alan Maguire <alan.maguire@oracle.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: WANG Xuerui <kernel@xen0n.name>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: x86@kernel.org
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Link: https://lore.kernel.org/173518991508.391279.16635322774382197642.stgit@devnote2
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Masami Hiramatsu (Google) and committed by
Steven Rostedt (Google)
a3ed4157 41705c42

+119 -207
+1
arch/arm64/Kconfig
··· 219 219 select HAVE_FTRACE_MCOUNT_RECORD 220 220 select HAVE_FUNCTION_TRACER 221 221 select HAVE_FUNCTION_ERROR_INJECTION 222 + select HAVE_FUNCTION_GRAPH_FREGS 222 223 select HAVE_FUNCTION_GRAPH_TRACER 223 224 select HAVE_FUNCTION_GRAPH_RETVAL 224 225 select HAVE_GCC_PLUGINS
+6 -17
arch/arm64/include/asm/ftrace.h
··· 129 129 arch_ftrace_regs(fregs)->pc = arch_ftrace_regs(fregs)->lr; 130 130 } 131 131 132 + static __always_inline unsigned long 133 + ftrace_regs_get_frame_pointer(const struct ftrace_regs *fregs) 134 + { 135 + return arch_ftrace_regs(fregs)->fp; 136 + } 137 + 132 138 int ftrace_regs_query_register_offset(const char *name); 133 139 134 140 int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec); ··· 192 186 193 187 #ifndef __ASSEMBLY__ 194 188 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 195 - struct fgraph_ret_regs { 196 - /* x0 - x7 */ 197 - unsigned long regs[8]; 198 - 199 - unsigned long fp; 200 - unsigned long __unused; 201 - }; 202 - 203 - static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) 204 - { 205 - return ret_regs->regs[0]; 206 - } 207 - 208 - static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) 209 - { 210 - return ret_regs->fp; 211 - } 212 189 213 190 void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent, 214 191 unsigned long frame_pointer);
-12
arch/arm64/kernel/asm-offsets.c
··· 179 179 DEFINE(FTRACE_OPS_FUNC, offsetof(struct ftrace_ops, func)); 180 180 #endif 181 181 BLANK(); 182 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 183 - DEFINE(FGRET_REGS_X0, offsetof(struct fgraph_ret_regs, regs[0])); 184 - DEFINE(FGRET_REGS_X1, offsetof(struct fgraph_ret_regs, regs[1])); 185 - DEFINE(FGRET_REGS_X2, offsetof(struct fgraph_ret_regs, regs[2])); 186 - DEFINE(FGRET_REGS_X3, offsetof(struct fgraph_ret_regs, regs[3])); 187 - DEFINE(FGRET_REGS_X4, offsetof(struct fgraph_ret_regs, regs[4])); 188 - DEFINE(FGRET_REGS_X5, offsetof(struct fgraph_ret_regs, regs[5])); 189 - DEFINE(FGRET_REGS_X6, offsetof(struct fgraph_ret_regs, regs[6])); 190 - DEFINE(FGRET_REGS_X7, offsetof(struct fgraph_ret_regs, regs[7])); 191 - DEFINE(FGRET_REGS_FP, offsetof(struct fgraph_ret_regs, fp)); 192 - DEFINE(FGRET_REGS_SIZE, sizeof(struct fgraph_ret_regs)); 193 - #endif 194 182 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 195 183 DEFINE(FTRACE_OPS_DIRECT_CALL, offsetof(struct ftrace_ops, direct_call)); 196 184 #endif
+18 -14
arch/arm64/kernel/entry-ftrace.S
··· 329 329 * @fp is checked against the value passed by ftrace_graph_caller(). 330 330 */ 331 331 SYM_CODE_START(return_to_handler) 332 - /* save return value regs */ 333 - sub sp, sp, #FGRET_REGS_SIZE 334 - stp x0, x1, [sp, #FGRET_REGS_X0] 335 - stp x2, x3, [sp, #FGRET_REGS_X2] 336 - stp x4, x5, [sp, #FGRET_REGS_X4] 337 - stp x6, x7, [sp, #FGRET_REGS_X6] 338 - str x29, [sp, #FGRET_REGS_FP] // parent's fp 332 + /* Make room for ftrace_regs */ 333 + sub sp, sp, #FREGS_SIZE 334 + 335 + /* Save return value regs */ 336 + stp x0, x1, [sp, #FREGS_X0] 337 + stp x2, x3, [sp, #FREGS_X2] 338 + stp x4, x5, [sp, #FREGS_X4] 339 + stp x6, x7, [sp, #FREGS_X6] 340 + 341 + /* Save the callsite's FP */ 342 + str x29, [sp, #FREGS_FP] 339 343 340 344 mov x0, sp 341 - bl ftrace_return_to_handler // addr = ftrace_return_to_hander(regs); 345 + bl ftrace_return_to_handler // addr = ftrace_return_to_hander(fregs); 342 346 mov x30, x0 // restore the original return address 343 347 344 - /* restore return value regs */ 345 - ldp x0, x1, [sp, #FGRET_REGS_X0] 346 - ldp x2, x3, [sp, #FGRET_REGS_X2] 347 - ldp x4, x5, [sp, #FGRET_REGS_X4] 348 - ldp x6, x7, [sp, #FGRET_REGS_X6] 349 - add sp, sp, #FGRET_REGS_SIZE 348 + /* Restore return value regs */ 349 + ldp x0, x1, [sp, #FREGS_X0] 350 + ldp x2, x3, [sp, #FREGS_X2] 351 + ldp x4, x5, [sp, #FREGS_X4] 352 + ldp x6, x7, [sp, #FREGS_X6] 353 + add sp, sp, #FREGS_SIZE 350 354 351 355 ret 352 356 SYM_CODE_END(return_to_handler)
+1 -1
arch/loongarch/Kconfig
··· 137 137 select HAVE_FTRACE_MCOUNT_RECORD 138 138 select HAVE_FUNCTION_ARG_ACCESS_API 139 139 select HAVE_FUNCTION_ERROR_INJECTION 140 - select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER 140 + select HAVE_FUNCTION_GRAPH_FREGS 141 141 select HAVE_FUNCTION_GRAPH_TRACER 142 142 select HAVE_FUNCTION_TRACER 143 143 select HAVE_GCC_PLUGINS
+4 -22
arch/loongarch/include/asm/ftrace.h
··· 57 57 instruction_pointer_set(&arch_ftrace_regs(fregs)->regs, ip); 58 58 } 59 59 60 + #undef ftrace_regs_get_frame_pointer 61 + #define ftrace_regs_get_frame_pointer(fregs) \ 62 + (arch_ftrace_regs(fregs)->regs.regs[22]) 63 + 60 64 #define ftrace_graph_func ftrace_graph_func 61 65 void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, 62 66 struct ftrace_ops *op, struct ftrace_regs *fregs); ··· 81 77 #endif /* __ASSEMBLY__ */ 82 78 83 79 #endif /* CONFIG_FUNCTION_TRACER */ 84 - 85 - #ifndef __ASSEMBLY__ 86 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 87 - struct fgraph_ret_regs { 88 - /* a0 - a1 */ 89 - unsigned long regs[2]; 90 - 91 - unsigned long fp; 92 - unsigned long __unused; 93 - }; 94 - 95 - static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) 96 - { 97 - return ret_regs->regs[0]; 98 - } 99 - 100 - static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) 101 - { 102 - return ret_regs->fp; 103 - } 104 - #endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */ 105 - #endif 106 80 107 81 #endif /* _ASM_LOONGARCH_FTRACE_H */
-12
arch/loongarch/kernel/asm-offsets.c
··· 280 280 } 281 281 #endif 282 282 283 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 284 - static void __used output_fgraph_ret_regs_defines(void) 285 - { 286 - COMMENT("LoongArch fgraph_ret_regs offsets."); 287 - OFFSET(FGRET_REGS_A0, fgraph_ret_regs, regs[0]); 288 - OFFSET(FGRET_REGS_A1, fgraph_ret_regs, regs[1]); 289 - OFFSET(FGRET_REGS_FP, fgraph_ret_regs, fp); 290 - DEFINE(FGRET_REGS_SIZE, sizeof(struct fgraph_ret_regs)); 291 - BLANK(); 292 - } 293 - #endif 294 - 295 283 static void __used output_kvm_defines(void) 296 284 { 297 285 COMMENT("KVM/LoongArch Specific offsets.");
+10 -7
arch/loongarch/kernel/mcount.S
··· 79 79 SYM_FUNC_END(ftrace_graph_caller) 80 80 81 81 SYM_FUNC_START(return_to_handler) 82 - PTR_ADDI sp, sp, -FGRET_REGS_SIZE 83 - PTR_S a0, sp, FGRET_REGS_A0 84 - PTR_S a1, sp, FGRET_REGS_A1 85 - PTR_S zero, sp, FGRET_REGS_FP 82 + /* Save return value regs */ 83 + PTR_ADDI sp, sp, -PT_SIZE 84 + PTR_S a0, sp, PT_R4 85 + PTR_S a1, sp, PT_R5 86 + PTR_S zero, sp, PT_R22 86 87 87 88 move a0, sp 88 89 bl ftrace_return_to_handler ··· 91 90 /* Restore the real parent address: a0 -> ra */ 92 91 move ra, a0 93 92 94 - PTR_L a0, sp, FGRET_REGS_A0 95 - PTR_L a1, sp, FGRET_REGS_A1 96 - PTR_ADDI sp, sp, FGRET_REGS_SIZE 93 + /* Restore return value regs */ 94 + PTR_L a0, sp, PT_R4 95 + PTR_L a1, sp, PT_R5 96 + PTR_ADDI sp, sp, PT_SIZE 97 + 97 98 jr ra 98 99 SYM_FUNC_END(return_to_handler) 99 100 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+7 -7
arch/loongarch/kernel/mcount_dyn.S
··· 140 140 SYM_CODE_START(return_to_handler) 141 141 UNWIND_HINT_UNDEFINED 142 142 /* Save return value regs */ 143 - PTR_ADDI sp, sp, -FGRET_REGS_SIZE 144 - PTR_S a0, sp, FGRET_REGS_A0 145 - PTR_S a1, sp, FGRET_REGS_A1 146 - PTR_S zero, sp, FGRET_REGS_FP 143 + PTR_ADDI sp, sp, -PT_SIZE 144 + PTR_S a0, sp, PT_R4 145 + PTR_S a1, sp, PT_R5 146 + PTR_S zero, sp, PT_R22 147 147 148 148 move a0, sp 149 149 bl ftrace_return_to_handler 150 150 move ra, a0 151 151 152 152 /* Restore return value regs */ 153 - PTR_L a0, sp, FGRET_REGS_A0 154 - PTR_L a1, sp, FGRET_REGS_A1 155 - PTR_ADDI sp, sp, FGRET_REGS_SIZE 153 + PTR_L a0, sp, PT_R4 154 + PTR_L a1, sp, PT_R5 155 + PTR_ADDI sp, sp, PT_SIZE 156 156 157 157 jr ra 158 158 SYM_CODE_END(return_to_handler)
+1 -1
arch/riscv/Kconfig
··· 148 148 select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE 149 149 select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL 150 150 select HAVE_FUNCTION_GRAPH_TRACER 151 - select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER 151 + select HAVE_FUNCTION_GRAPH_FREGS 152 152 select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION 153 153 select HAVE_EBPF_JIT if MMU 154 154 select HAVE_GUP_FAST if MMU
+5 -21
arch/riscv/include/asm/ftrace.h
··· 168 168 return arch_ftrace_regs(fregs)->sp; 169 169 } 170 170 171 + static __always_inline unsigned long ftrace_regs_get_frame_pointer(const struct ftrace_regs *fregs) 172 + { 173 + return arch_ftrace_regs(fregs)->s0; 174 + } 175 + 171 176 static __always_inline unsigned long ftrace_regs_get_argument(struct ftrace_regs *fregs, 172 177 unsigned int n) 173 178 { ··· 212 207 #endif /* __ASSEMBLY__ */ 213 208 214 209 #endif /* CONFIG_DYNAMIC_FTRACE */ 215 - 216 - #ifndef __ASSEMBLY__ 217 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 218 - struct fgraph_ret_regs { 219 - unsigned long a1; 220 - unsigned long a0; 221 - unsigned long s0; 222 - unsigned long ra; 223 - }; 224 - 225 - static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) 226 - { 227 - return ret_regs->a0; 228 - } 229 - 230 - static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) 231 - { 232 - return ret_regs->s0; 233 - } 234 - #endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */ 235 - #endif 236 210 237 211 #endif /* _ASM_RISCV_FTRACE_H */
+13 -11
arch/riscv/kernel/mcount.S
··· 12 12 #include <asm/asm-offsets.h> 13 13 #include <asm/ftrace.h> 14 14 15 + #define ABI_SIZE_ON_STACK 80 16 + 15 17 .text 16 18 17 19 .macro SAVE_ABI_STATE ··· 28 26 * register if a0 was not saved. 29 27 */ 30 28 .macro SAVE_RET_ABI_STATE 31 - addi sp, sp, -4*SZREG 32 - REG_S s0, 2*SZREG(sp) 33 - REG_S ra, 3*SZREG(sp) 34 - REG_S a0, 1*SZREG(sp) 35 - REG_S a1, 0*SZREG(sp) 36 - addi s0, sp, 4*SZREG 29 + addi sp, sp, -ABI_SIZE_ON_STACK 30 + REG_S ra, 1*SZREG(sp) 31 + REG_S s0, 8*SZREG(sp) 32 + REG_S a0, 10*SZREG(sp) 33 + REG_S a1, 11*SZREG(sp) 34 + addi s0, sp, ABI_SIZE_ON_STACK 37 35 .endm 38 36 39 37 .macro RESTORE_ABI_STATE ··· 43 41 .endm 44 42 45 43 .macro RESTORE_RET_ABI_STATE 46 - REG_L ra, 3*SZREG(sp) 47 - REG_L s0, 2*SZREG(sp) 48 - REG_L a0, 1*SZREG(sp) 49 - REG_L a1, 0*SZREG(sp) 50 - addi sp, sp, 4*SZREG 44 + REG_L ra, 1*SZREG(sp) 45 + REG_L s0, 8*SZREG(sp) 46 + REG_L a0, 10*SZREG(sp) 47 + REG_L a1, 11*SZREG(sp) 48 + addi sp, sp, ABI_SIZE_ON_STACK 51 49 .endm 52 50 53 51 SYM_TYPED_FUNC_START(ftrace_stub)
+1 -1
arch/s390/Kconfig
··· 192 192 select HAVE_FTRACE_MCOUNT_RECORD 193 193 select HAVE_FUNCTION_ARG_ACCESS_API 194 194 select HAVE_FUNCTION_ERROR_INJECTION 195 - select HAVE_FUNCTION_GRAPH_RETVAL 195 + select HAVE_FUNCTION_GRAPH_FREGS 196 196 select HAVE_FUNCTION_GRAPH_TRACER 197 197 select HAVE_FUNCTION_TRACER 198 198 select HAVE_GCC_PLUGINS
+7 -17
arch/s390/include/asm/ftrace.h
··· 62 62 return NULL; 63 63 } 64 64 65 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 66 - struct fgraph_ret_regs { 67 - unsigned long gpr2; 68 - unsigned long fp; 69 - }; 70 - 71 - static __always_inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) 72 - { 73 - return ret_regs->gpr2; 74 - } 75 - 76 - static __always_inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) 77 - { 78 - return ret_regs->fp; 79 - } 80 - #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 81 - 82 65 static __always_inline void 83 66 ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, 84 67 unsigned long ip) 85 68 { 86 69 arch_ftrace_regs(fregs)->regs.psw.addr = ip; 70 + } 71 + 72 + #undef ftrace_regs_get_frame_pointer 73 + static __always_inline unsigned long 74 + ftrace_regs_get_frame_pointer(struct ftrace_regs *fregs) 75 + { 76 + return ftrace_regs_get_stack_pointer(fregs); 87 77 } 88 78 89 79 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
-6
arch/s390/kernel/asm-offsets.c
··· 175 175 DEFINE(OLDMEM_SIZE, PARMAREA + offsetof(struct parmarea, oldmem_size)); 176 176 DEFINE(COMMAND_LINE, PARMAREA + offsetof(struct parmarea, command_line)); 177 177 DEFINE(MAX_COMMAND_LINE_SIZE, PARMAREA + offsetof(struct parmarea, max_command_line_size)); 178 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 179 - /* function graph return value tracing */ 180 - OFFSET(__FGRAPH_RET_GPR2, fgraph_ret_regs, gpr2); 181 - OFFSET(__FGRAPH_RET_FP, fgraph_ret_regs, fp); 182 - DEFINE(__FGRAPH_RET_SIZE, sizeof(struct fgraph_ret_regs)); 183 - #endif 184 178 OFFSET(__FTRACE_REGS_PT_REGS, __arch_ftrace_regs, regs); 185 179 DEFINE(__FTRACE_REGS_SIZE, sizeof(struct __arch_ftrace_regs)); 186 180
+6 -6
arch/s390/kernel/mcount.S
··· 134 134 SYM_FUNC_START(return_to_handler) 135 135 stmg %r2,%r5,32(%r15) 136 136 lgr %r1,%r15 137 - aghi %r15,-(STACK_FRAME_OVERHEAD+__FGRAPH_RET_SIZE) 137 + # allocate ftrace_regs and stack frame for ftrace_return_to_handler 138 + aghi %r15,-STACK_FRAME_SIZE_FREGS 138 139 stg %r1,__SF_BACKCHAIN(%r15) 139 - la %r3,STACK_FRAME_OVERHEAD(%r15) 140 - stg %r1,__FGRAPH_RET_FP(%r3) 141 - stg %r2,__FGRAPH_RET_GPR2(%r3) 142 - lgr %r2,%r3 140 + stg %r2,(STACK_FREGS_PTREGS_GPRS+2*8)(%r15) 141 + stg %r1,(STACK_FREGS_PTREGS_GPRS+15*8)(%r15) 142 + la %r2,STACK_FRAME_OVERHEAD(%r15) 143 143 brasl %r14,ftrace_return_to_handler 144 - aghi %r15,STACK_FRAME_OVERHEAD+__FGRAPH_RET_SIZE 144 + aghi %r15,STACK_FRAME_SIZE_FREGS 145 145 lgr %r14,%r2 146 146 lmg %r2,%r5,32(%r15) 147 147 BR_EX %r14
+1 -1
arch/x86/Kconfig
··· 235 235 select HAVE_GUP_FAST 236 236 select HAVE_FENTRY if X86_64 || DYNAMIC_FTRACE 237 237 select HAVE_FTRACE_MCOUNT_RECORD 238 - select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER 238 + select HAVE_FUNCTION_GRAPH_FREGS if HAVE_FUNCTION_GRAPH_TRACER 239 239 select HAVE_FUNCTION_GRAPH_TRACER if X86_32 || (X86_64 && DYNAMIC_FTRACE) 240 240 select HAVE_FUNCTION_TRACER 241 241 select HAVE_GCC_PLUGINS
-20
arch/x86/include/asm/ftrace.h
··· 134 134 #endif /* !COMPILE_OFFSETS */ 135 135 #endif /* !__ASSEMBLY__ */ 136 136 137 - #ifndef __ASSEMBLY__ 138 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 139 - struct fgraph_ret_regs { 140 - unsigned long ax; 141 - unsigned long dx; 142 - unsigned long bp; 143 - }; 144 - 145 - static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) 146 - { 147 - return ret_regs->ax; 148 - } 149 - 150 - static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) 151 - { 152 - return ret_regs->bp; 153 - } 154 - #endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */ 155 - #endif 156 - 157 137 #endif /* _ASM_X86_FTRACE_H */
+7 -6
arch/x86/kernel/ftrace_32.S
··· 187 187 188 188 .globl return_to_handler 189 189 return_to_handler: 190 - pushl $0 191 - pushl %edx 192 - pushl %eax 190 + subl $(PTREGS_SIZE), %esp 191 + movl $0, PT_EBP(%esp) 192 + movl %edx, PT_EDX(%esp) 193 + movl %eax, PT_EAX(%esp) 193 194 movl %esp, %eax 194 195 call ftrace_return_to_handler 195 196 movl %eax, %ecx 196 - popl %eax 197 - popl %edx 198 - addl $4, %esp # skip ebp 197 + movl PT_EAX(%esp), %eax 198 + movl PT_EDX(%esp), %edx 199 + addl $(PTREGS_SIZE), %esp 199 200 JMP_NOSPEC ecx 200 201 #endif
+9 -8
arch/x86/kernel/ftrace_64.S
··· 348 348 SYM_CODE_START(return_to_handler) 349 349 UNWIND_HINT_UNDEFINED 350 350 ANNOTATE_NOENDBR 351 - subq $24, %rsp 352 351 353 - /* Save the return values */ 354 - movq %rax, (%rsp) 355 - movq %rdx, 8(%rsp) 356 - movq %rbp, 16(%rsp) 352 + /* Save ftrace_regs for function exit context */ 353 + subq $(FRAME_SIZE), %rsp 354 + 355 + movq %rax, RAX(%rsp) 356 + movq %rdx, RDX(%rsp) 357 + movq %rbp, RBP(%rsp) 357 358 movq %rsp, %rdi 358 359 359 360 call ftrace_return_to_handler 360 361 361 362 movq %rax, %rdi 362 - movq 8(%rsp), %rdx 363 - movq (%rsp), %rax 363 + movq RDX(%rsp), %rdx 364 + movq RAX(%rsp), %rax 364 365 365 - addq $24, %rsp 366 + addq $(FRAME_SIZE), %rsp 366 367 /* 367 368 * Jump back to the old return address. This cannot be JMP_NOSPEC rdi 368 369 * since IBT would demand that contain ENDBR, which simply isn't so for
+9 -3
include/linux/ftrace.h
··· 43 43 44 44 char *arch_ftrace_match_adjust(char *str, const char *search); 45 45 46 - #ifdef CONFIG_HAVE_FUNCTION_GRAPH_RETVAL 47 - struct fgraph_ret_regs; 48 - unsigned long ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs); 46 + #ifdef CONFIG_HAVE_FUNCTION_GRAPH_FREGS 47 + unsigned long ftrace_return_to_handler(struct ftrace_regs *fregs); 49 48 #else 50 49 unsigned long ftrace_return_to_handler(unsigned long frame_pointer); 51 50 #endif ··· 133 134 * Also, architecture dependent fields can be used for internal process. 134 135 * (e.g. orig_ax on x86_64) 135 136 * 137 + * Basically, ftrace_regs stores the registers related to the context. 138 + * On function entry, registers for function parameters and hooking the 139 + * function call are stored, and on function exit, registers for function 140 + * return value and frame pointers are stored. 141 + * 142 + * And also, it dpends on the context that which registers are restored 143 + * from the ftrace_regs. 136 144 * On the function entry, those registers will be restored except for 137 145 * the stack pointer, so that user can change the function parameters 138 146 * and instruction pointer (e.g. live patching.)
+2
include/linux/ftrace_regs.h
··· 30 30 override_function_with_return(&arch_ftrace_regs(fregs)->regs) 31 31 #define ftrace_regs_query_register_offset(name) \ 32 32 regs_query_register_offset(name) 33 + #define ftrace_regs_get_frame_pointer(fregs) \ 34 + frame_pointer(&arch_ftrace_regs(fregs)->regs) 33 35 34 36 #endif /* HAVE_ARCH_FTRACE_REGS */ 35 37
+2 -2
kernel/trace/Kconfig
··· 31 31 help 32 32 See Documentation/trace/ftrace-design.rst 33 33 34 - config HAVE_FUNCTION_GRAPH_RETVAL 34 + config HAVE_FUNCTION_GRAPH_FREGS 35 35 bool 36 36 37 37 config HAVE_DYNAMIC_FTRACE ··· 232 232 233 233 config FUNCTION_GRAPH_RETVAL 234 234 bool "Kernel Function Graph Return Value" 235 - depends on HAVE_FUNCTION_GRAPH_RETVAL 235 + depends on HAVE_FUNCTION_GRAPH_FREGS 236 236 depends on FUNCTION_GRAPH_TRACER 237 237 default n 238 238 help
+9 -12
kernel/trace/fgraph.c
··· 801 801 .notifier_call = ftrace_suspend_notifier_call, 802 802 }; 803 803 804 - /* fgraph_ret_regs is not defined without CONFIG_FUNCTION_GRAPH_RETVAL */ 805 - struct fgraph_ret_regs; 806 - 807 804 /* 808 805 * Send the trace to the ring-buffer. 809 806 * @return the original return address. 810 807 */ 811 - static unsigned long __ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs, 812 - unsigned long frame_pointer) 808 + static inline unsigned long 809 + __ftrace_return_to_handler(struct ftrace_regs *fregs, unsigned long frame_pointer) 813 810 { 814 811 struct ftrace_ret_stack *ret_stack; 815 812 struct ftrace_graph_ret trace; ··· 826 829 827 830 trace.rettime = trace_clock_local(); 828 831 #ifdef CONFIG_FUNCTION_GRAPH_RETVAL 829 - trace.retval = fgraph_ret_regs_return_value(ret_regs); 832 + trace.retval = ftrace_regs_get_return_value(fregs); 830 833 #endif 831 834 832 835 bitmap = get_bitmap_bits(current, offset); ··· 861 864 } 862 865 863 866 /* 864 - * After all architecures have selected HAVE_FUNCTION_GRAPH_RETVAL, we can 865 - * leave only ftrace_return_to_handler(ret_regs). 867 + * After all architecures have selected HAVE_FUNCTION_GRAPH_FREGS, we can 868 + * leave only ftrace_return_to_handler(fregs). 866 869 */ 867 - #ifdef CONFIG_HAVE_FUNCTION_GRAPH_RETVAL 868 - unsigned long ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs) 870 + #ifdef CONFIG_HAVE_FUNCTION_GRAPH_FREGS 871 + unsigned long ftrace_return_to_handler(struct ftrace_regs *fregs) 869 872 { 870 - return __ftrace_return_to_handler(ret_regs, 871 - fgraph_ret_regs_frame_pointer(ret_regs)); 873 + return __ftrace_return_to_handler(fregs, 874 + ftrace_regs_get_frame_pointer(fregs)); 872 875 } 873 876 #else 874 877 unsigned long ftrace_return_to_handler(unsigned long frame_pointer)