Skip to content

Commit 94d095f

Browse files
mrutland-armwilldeacon
authored andcommitted
ftrace: abstract DYNAMIC_FTRACE_WITH_ARGS accesses
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 adds new ftrace_regs_{get,set}_*() helpers which can be used to manipulate ftrace_regs. When CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y, these can always be used on any ftrace_regs, and when CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=n these can be used when regs are available. A new ftrace_regs_has_args(fregs) helper is added which code can use to check when these are usable. Co-developed-by: Florent Revest <[email protected]> Signed-off-by: Florent Revest <[email protected]> Signed-off-by: Mark Rutland <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Steven Rostedt <[email protected]> Reviewed-by: Masami Hiramatsu (Google) <[email protected]> Reviewed-by: Steven Rostedt (Google) <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 0ef8609 commit 94d095f

File tree

5 files changed

+86
-3
lines changed

5 files changed

+86
-3
lines changed

arch/powerpc/include/asm/ftrace.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,25 @@ ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
4444
regs_set_return_ip(&fregs->regs, ip);
4545
}
4646

47+
static __always_inline unsigned long
48+
ftrace_regs_get_instruction_pointer(struct ftrace_regs *fregs)
49+
{
50+
return instruction_pointer(&fregs->regs);
51+
}
52+
53+
#define ftrace_regs_get_argument(fregs, n) \
54+
regs_get_kernel_argument(&(fregs)->regs, n)
55+
#define ftrace_regs_get_stack_pointer(fregs) \
56+
kernel_stack_pointer(&(fregs)->regs)
57+
#define ftrace_regs_return_value(fregs) \
58+
regs_return_value(&(fregs)->regs)
59+
#define ftrace_regs_set_return_value(fregs, ret) \
60+
regs_set_return_value(&(fregs)->regs, ret)
61+
#define ftrace_override_function_with_return(fregs) \
62+
override_function_with_return(&(fregs)->regs)
63+
#define ftrace_regs_query_register_offset(name) \
64+
regs_query_register_offset(name)
65+
4766
struct ftrace_ops;
4867

4968
#define ftrace_graph_func ftrace_graph_func

arch/s390/include/asm/ftrace.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,32 @@ static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *
5454
return NULL;
5555
}
5656

57+
static __always_inline unsigned long
58+
ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs)
59+
{
60+
return fregs->regs.psw.addr;
61+
}
62+
5763
static __always_inline void
5864
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
5965
unsigned long ip)
6066
{
6167
fregs->regs.psw.addr = ip;
6268
}
6369

70+
#define ftrace_regs_get_argument(fregs, n) \
71+
regs_get_kernel_argument(&(fregs)->regs, n)
72+
#define ftrace_regs_get_stack_pointer(fregs) \
73+
kernel_stack_pointer(&(fregs)->regs)
74+
#define ftrace_regs_return_value(fregs) \
75+
regs_return_value(&(fregs)->regs)
76+
#define ftrace_regs_set_return_value(fregs, ret) \
77+
regs_set_return_value(&(fregs)->regs, ret)
78+
#define ftrace_override_function_with_return(fregs) \
79+
override_function_with_return(&(fregs)->regs)
80+
#define ftrace_regs_query_register_offset(name) \
81+
regs_query_register_offset(name)
82+
6483
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
6584
/*
6685
* When an ftrace registered caller is tracing a function that is

arch/x86/include/asm/ftrace.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,22 @@ arch_ftrace_get_regs(struct ftrace_regs *fregs)
5151
#define ftrace_regs_set_instruction_pointer(fregs, _ip) \
5252
do { (fregs)->regs.ip = (_ip); } while (0)
5353

54+
#define ftrace_regs_get_instruction_pointer(fregs) \
55+
((fregs)->regs.ip)
56+
57+
#define ftrace_regs_get_argument(fregs, n) \
58+
regs_get_kernel_argument(&(fregs)->regs, n)
59+
#define ftrace_regs_get_stack_pointer(fregs) \
60+
kernel_stack_pointer(&(fregs)->regs)
61+
#define ftrace_regs_return_value(fregs) \
62+
regs_return_value(&(fregs)->regs)
63+
#define ftrace_regs_set_return_value(fregs, ret) \
64+
regs_set_return_value(&(fregs)->regs, ret)
65+
#define ftrace_override_function_with_return(fregs) \
66+
override_function_with_return(&(fregs)->regs)
67+
#define ftrace_regs_query_register_offset(name) \
68+
regs_query_register_offset(name)
69+
5470
struct ftrace_ops;
5571
#define ftrace_graph_func ftrace_graph_func
5672
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,

include/linux/ftrace.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,35 @@ static __always_inline struct pt_regs *ftrace_get_regs(struct ftrace_regs *fregs
126126
return arch_ftrace_get_regs(fregs);
127127
}
128128

129+
/*
130+
* When true, the ftrace_regs_{get,set}_*() functions may be used on fregs.
131+
* Note: this can be true even when ftrace_get_regs() cannot provide a pt_regs.
132+
*/
133+
static __always_inline bool ftrace_regs_has_args(struct ftrace_regs *fregs)
134+
{
135+
if (IS_ENABLED(CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS))
136+
return true;
137+
138+
return ftrace_get_regs(fregs) != NULL;
139+
}
140+
141+
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
142+
#define ftrace_regs_get_instruction_pointer(fregs) \
143+
instruction_pointer(ftrace_get_regs(fregs))
144+
#define ftrace_regs_get_argument(fregs, n) \
145+
regs_get_kernel_argument(ftrace_get_regs(fregs), n)
146+
#define ftrace_regs_get_stack_pointer(fregs) \
147+
kernel_stack_pointer(ftrace_get_regs(fregs))
148+
#define ftrace_regs_return_value(fregs) \
149+
regs_return_value(ftrace_get_regs(fregs))
150+
#define ftrace_regs_set_return_value(fregs, ret) \
151+
regs_set_return_value(ftrace_get_regs(fregs), ret)
152+
#define ftrace_override_function_with_return(fregs) \
153+
override_function_with_return(ftrace_get_regs(fregs))
154+
#define ftrace_regs_query_register_offset(name) \
155+
regs_query_register_offset(name)
156+
#endif
157+
129158
typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip,
130159
struct ftrace_ops *op, struct ftrace_regs *fregs);
131160

kernel/trace/Kconfig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ config HAVE_DYNAMIC_FTRACE_WITH_ARGS
4646
bool
4747
help
4848
If this is set, then arguments and stack can be found from
49-
the pt_regs passed into the function callback regs parameter
49+
the ftrace_regs passed into the function callback regs parameter
5050
by default, even without setting the REGS flag in the ftrace_ops.
51-
This allows for use of regs_get_kernel_argument() and
52-
kernel_stack_pointer().
51+
This allows for use of ftrace_regs_get_argument() and
52+
ftrace_regs_get_stack_pointer().
5353

5454
config HAVE_DYNAMIC_FTRACE_NO_PATCHABLE
5555
bool

0 commit comments

Comments
 (0)