forked from mirrors/linux
		
	ftrace: pass fregs to arch_ftrace_set_direct_caller()
In subsequent patches we'll arrange for architectures to have an ftrace_regs which is entirely distinct from pt_regs. In preparation for this, we need to minimize the use of pt_regs to where strictly necessary in the core ftrace code. This patch changes the prototype of arch_ftrace_set_direct_caller() to take ftrace_regs rather than pt_regs, and moves the extraction of the pt_regs into arch_ftrace_set_direct_caller(). On x86, arch_ftrace_set_direct_caller() can be used even when CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=n, and <linux/ftrace.h> defines struct ftrace_regs. Due to this, it's necessary to define arch_ftrace_set_direct_caller() as a macro to avoid using an incomplete type. I've also moved the body of arch_ftrace_set_direct_caller() after the CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y defineidion of struct ftrace_regs. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Florent Revest <revest@chromium.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Steven Rostedt <rostedt@goodmis.org> Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org> Link: https://lore.kernel.org/r/20221103170520.931305-2-mark.rutland@arm.com Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
		
							parent
							
								
									f0c4d9fc9c
								
							
						
					
					
						commit
						9705bc7096
					
				
					 4 changed files with 27 additions and 21 deletions
				
			
		|  | @ -60,6 +60,7 @@ static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *f | ||||||
| 	fregs->regs.psw.addr = ip; | 	fregs->regs.psw.addr = ip; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS | ||||||
| /*
 | /*
 | ||||||
|  * When an ftrace registered caller is tracing a function that is |  * When an ftrace registered caller is tracing a function that is | ||||||
|  * also set by a register_ftrace_direct() call, it needs to be |  * also set by a register_ftrace_direct() call, it needs to be | ||||||
|  | @ -67,10 +68,12 @@ static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *f | ||||||
|  * place the direct caller in the ORIG_GPR2 part of pt_regs. This |  * place the direct caller in the ORIG_GPR2 part of pt_regs. This | ||||||
|  * tells the ftrace_caller that there's a direct caller. |  * tells the ftrace_caller that there's a direct caller. | ||||||
|  */ |  */ | ||||||
| static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) | static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr) | ||||||
| { | { | ||||||
|  | 	struct pt_regs *regs = &fregs->regs; | ||||||
| 	regs->orig_gpr2 = addr; | 	regs->orig_gpr2 = addr; | ||||||
| } | } | ||||||
|  | #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Even though the system call numbers are identical for s390/s390x a |  * Even though the system call numbers are identical for s390/s390x a | ||||||
|  |  | ||||||
|  | @ -34,19 +34,6 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) | ||||||
| 	return addr; | 	return addr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * When a ftrace registered caller is tracing a function that is |  | ||||||
|  * also set by a register_ftrace_direct() call, it needs to be |  | ||||||
|  * differentiated in the ftrace_caller trampoline. To do this, we |  | ||||||
|  * place the direct caller in the ORIG_AX part of pt_regs. This |  | ||||||
|  * tells the ftrace_caller that there's a direct caller. |  | ||||||
|  */ |  | ||||||
| static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) |  | ||||||
| { |  | ||||||
| 	/* Emulate a call */ |  | ||||||
| 	regs->orig_ax = addr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS | #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS | ||||||
| struct ftrace_regs { | struct ftrace_regs { | ||||||
| 	struct pt_regs		regs; | 	struct pt_regs		regs; | ||||||
|  | @ -72,6 +59,24 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, | ||||||
| #define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR | #define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS | ||||||
|  | /*
 | ||||||
|  |  * When a ftrace registered caller is tracing a function that is | ||||||
|  |  * also set by a register_ftrace_direct() call, it needs to be | ||||||
|  |  * differentiated in the ftrace_caller trampoline. To do this, we | ||||||
|  |  * place the direct caller in the ORIG_AX part of pt_regs. This | ||||||
|  |  * tells the ftrace_caller that there's a direct caller. | ||||||
|  |  */ | ||||||
|  | static inline void | ||||||
|  | __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) | ||||||
|  | { | ||||||
|  | 	/* Emulate a call */ | ||||||
|  | 	regs->orig_ax = addr; | ||||||
|  | } | ||||||
|  | #define arch_ftrace_set_direct_caller(fregs, addr) \ | ||||||
|  | 	__arch_ftrace_set_direct_caller(&(fregs)->regs, addr) | ||||||
|  | #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ | ||||||
|  | 
 | ||||||
| #ifdef CONFIG_DYNAMIC_FTRACE | #ifdef CONFIG_DYNAMIC_FTRACE | ||||||
| 
 | 
 | ||||||
| struct dyn_arch_ftrace { | struct dyn_arch_ftrace { | ||||||
|  |  | ||||||
|  | @ -37,9 +37,10 @@ extern void ftrace_boot_snapshot(void); | ||||||
| static inline void ftrace_boot_snapshot(void) { } | static inline void ftrace_boot_snapshot(void) { } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_FUNCTION_TRACER |  | ||||||
| struct ftrace_ops; | struct ftrace_ops; | ||||||
| struct ftrace_regs; | struct ftrace_regs; | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_FUNCTION_TRACER | ||||||
| /*
 | /*
 | ||||||
|  * If the arch's mcount caller does not support all of ftrace's |  * If the arch's mcount caller does not support all of ftrace's | ||||||
|  * features, then it must call an indirect function that |  * features, then it must call an indirect function that | ||||||
|  | @ -427,9 +428,7 @@ static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsi | ||||||
| { | { | ||||||
| 	return -ENODEV; | 	return -ENODEV; | ||||||
| } | } | ||||||
| #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ |  | ||||||
| 
 | 
 | ||||||
| #ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS |  | ||||||
| /*
 | /*
 | ||||||
|  * This must be implemented by the architecture. |  * This must be implemented by the architecture. | ||||||
|  * It is the way the ftrace direct_ops helper, when called |  * It is the way the ftrace direct_ops helper, when called | ||||||
|  | @ -443,9 +442,9 @@ static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsi | ||||||
|  * the return from the trampoline jump to the direct caller |  * the return from the trampoline jump to the direct caller | ||||||
|  * instead of going back to the function it just traced. |  * instead of going back to the function it just traced. | ||||||
|  */ |  */ | ||||||
| static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, | static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, | ||||||
| 						 unsigned long addr) { } | 						 unsigned long addr) { } | ||||||
| #endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ | #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_STACK_TRACER | #ifdef CONFIG_STACK_TRACER | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2487,14 +2487,13 @@ ftrace_add_rec_direct(unsigned long ip, unsigned long addr, | ||||||
| static void call_direct_funcs(unsigned long ip, unsigned long pip, | static void call_direct_funcs(unsigned long ip, unsigned long pip, | ||||||
| 			      struct ftrace_ops *ops, struct ftrace_regs *fregs) | 			      struct ftrace_ops *ops, struct ftrace_regs *fregs) | ||||||
| { | { | ||||||
| 	struct pt_regs *regs = ftrace_get_regs(fregs); |  | ||||||
| 	unsigned long addr; | 	unsigned long addr; | ||||||
| 
 | 
 | ||||||
| 	addr = ftrace_find_rec_direct(ip); | 	addr = ftrace_find_rec_direct(ip); | ||||||
| 	if (!addr) | 	if (!addr) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	arch_ftrace_set_direct_caller(regs, addr); | 	arch_ftrace_set_direct_caller(fregs, addr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct ftrace_ops direct_ops = { | struct ftrace_ops direct_ops = { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Mark Rutland
						Mark Rutland