Skip to content

Commit 4346ba1

Browse files
mhiramatrostedt
authored andcommitted
fprobe: Rewrite fprobe on function-graph tracer
Rewrite fprobe implementation on function-graph tracer. Major API changes are: - 'nr_maxactive' field is deprecated. - This depends on CONFIG_DYNAMIC_FTRACE_WITH_ARGS or !CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS, and CONFIG_HAVE_FUNCTION_GRAPH_FREGS. So currently works only on x86_64. - Currently the entry size is limited in 15 * sizeof(long). - If there is too many fprobe exit handler set on the same function, it will fail to probe. Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Acked-by: Heiko Carstens <hca@linux.ibm.com> # s390 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: Heiko Carstens <hca@linux.ibm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: WANG Xuerui <kernel@xen0n.name> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Nicholas Piggin <npiggin@gmail.com> Cc: Christophe Leroy <christophe.leroy@csgroup.eu> Cc: Naveen N Rao <naveen@kernel.org> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> 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: 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> Cc: Andrew Morton <akpm@linux-foundation.org> Link: https://lore.kernel.org/173519003970.391279.14406792285453830996.stgit@devnote2 Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent 7495e17 commit 4346ba1

File tree

10 files changed

+538
-245
lines changed

10 files changed

+538
-245
lines changed

arch/arm64/include/asm/ftrace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ ftrace_regs_get_frame_pointer(const struct ftrace_regs *fregs)
135135
return arch_ftrace_regs(fregs)->fp;
136136
}
137137

138+
static __always_inline unsigned long
139+
ftrace_regs_get_return_address(const struct ftrace_regs *fregs)
140+
{
141+
return arch_ftrace_regs(fregs)->lr;
142+
}
143+
138144
static __always_inline struct pt_regs *
139145
ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs)
140146
{

arch/loongarch/include/asm/ftrace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long ip)
6161
#define ftrace_regs_get_frame_pointer(fregs) \
6262
(arch_ftrace_regs(fregs)->regs.regs[22])
6363

64+
static __always_inline unsigned long
65+
ftrace_regs_get_return_address(struct ftrace_regs *fregs)
66+
{
67+
return *(unsigned long *)(arch_ftrace_regs(fregs)->regs.regs[1]);
68+
}
69+
6470
#define ftrace_graph_func ftrace_graph_func
6571
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
6672
struct ftrace_ops *op, struct ftrace_regs *fregs);

arch/powerpc/include/asm/ftrace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
5757
regs_set_return_ip(&arch_ftrace_regs(fregs)->regs, ip);
5858
}
5959

60+
static __always_inline unsigned long
61+
ftrace_regs_get_return_address(struct ftrace_regs *fregs)
62+
{
63+
return arch_ftrace_regs(fregs)->regs.link;
64+
}
65+
6066
struct ftrace_ops;
6167

6268
#define ftrace_graph_func ftrace_graph_func

arch/riscv/include/asm/ftrace.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ static __always_inline unsigned long ftrace_regs_get_return_value(const struct f
186186
return arch_ftrace_regs(fregs)->a0;
187187
}
188188

189+
static __always_inline unsigned long ftrace_regs_get_return_address(const struct ftrace_regs *fregs)
190+
{
191+
return arch_ftrace_regs(fregs)->ra;
192+
}
193+
189194
static __always_inline void ftrace_regs_set_return_value(struct ftrace_regs *fregs,
190195
unsigned long ret)
191196
{

arch/s390/include/asm/ftrace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ ftrace_regs_get_frame_pointer(struct ftrace_regs *fregs)
7777
return ftrace_regs_get_stack_pointer(fregs);
7878
}
7979

80+
static __always_inline unsigned long
81+
ftrace_regs_get_return_address(const struct ftrace_regs *fregs)
82+
{
83+
return arch_ftrace_regs(fregs)->regs.gprs[14];
84+
}
85+
8086
#define arch_ftrace_fill_perf_regs(fregs, _regs) do { \
8187
(_regs)->psw.mask = 0; \
8288
(_regs)->psw.addr = arch_ftrace_regs(fregs)->regs.psw.addr; \

arch/x86/include/asm/ftrace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ arch_ftrace_get_regs(struct ftrace_regs *fregs)
5858
do { arch_ftrace_regs(fregs)->regs.ip = (_ip); } while (0)
5959

6060

61+
static __always_inline unsigned long
62+
ftrace_regs_get_return_address(struct ftrace_regs *fregs)
63+
{
64+
return *(unsigned long *)ftrace_regs_get_stack_pointer(fregs);
65+
}
66+
6167
struct ftrace_ops;
6268
#define ftrace_graph_func ftrace_graph_func
6369
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,

include/linux/fprobe.h

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55

66
#include <linux/compiler.h>
77
#include <linux/ftrace.h>
8-
#include <linux/rethook.h>
8+
#include <linux/rcupdate.h>
9+
#include <linux/refcount.h>
10+
#include <linux/slab.h>
911

1012
struct fprobe;
11-
1213
typedef int (*fprobe_entry_cb)(struct fprobe *fp, unsigned long entry_ip,
1314
unsigned long ret_ip, struct ftrace_regs *regs,
1415
void *entry_data);
@@ -17,35 +18,57 @@ typedef void (*fprobe_exit_cb)(struct fprobe *fp, unsigned long entry_ip,
1718
unsigned long ret_ip, struct ftrace_regs *regs,
1819
void *entry_data);
1920

21+
/**
22+
* struct fprobe_hlist_node - address based hash list node for fprobe.
23+
*
24+
* @hlist: The hlist node for address search hash table.
25+
* @addr: One of the probing address of @fp.
26+
* @fp: The fprobe which owns this.
27+
*/
28+
struct fprobe_hlist_node {
29+
struct hlist_node hlist;
30+
unsigned long addr;
31+
struct fprobe *fp;
32+
};
33+
34+
/**
35+
* struct fprobe_hlist - hash list nodes for fprobe.
36+
*
37+
* @hlist: The hlist node for existence checking hash table.
38+
* @rcu: rcu_head for RCU deferred release.
39+
* @fp: The fprobe which owns this fprobe_hlist.
40+
* @size: The size of @array.
41+
* @array: The fprobe_hlist_node for each address to probe.
42+
*/
43+
struct fprobe_hlist {
44+
struct hlist_node hlist;
45+
struct rcu_head rcu;
46+
struct fprobe *fp;
47+
int size;
48+
struct fprobe_hlist_node array[] __counted_by(size);
49+
};
50+
2051
/**
2152
* struct fprobe - ftrace based probe.
22-
* @ops: The ftrace_ops.
53+
*
2354
* @nmissed: The counter for missing events.
2455
* @flags: The status flag.
25-
* @rethook: The rethook data structure. (internal data)
2656
* @entry_data_size: The private data storage size.
27-
* @nr_maxactive: The max number of active functions.
57+
* @nr_maxactive: The max number of active functions. (*deprecated)
2858
* @entry_handler: The callback function for function entry.
2959
* @exit_handler: The callback function for function exit.
60+
* @hlist_array: The fprobe_hlist for fprobe search from IP hash table.
3061
*/
3162
struct fprobe {
32-
#ifdef CONFIG_FUNCTION_TRACER
33-
/*
34-
* If CONFIG_FUNCTION_TRACER is not set, CONFIG_FPROBE is disabled too.
35-
* But user of fprobe may keep embedding the struct fprobe on their own
36-
* code. To avoid build error, this will keep the fprobe data structure
37-
* defined here, but remove ftrace_ops data structure.
38-
*/
39-
struct ftrace_ops ops;
40-
#endif
4163
unsigned long nmissed;
4264
unsigned int flags;
43-
struct rethook *rethook;
4465
size_t entry_data_size;
4566
int nr_maxactive;
4667

4768
fprobe_entry_cb entry_handler;
4869
fprobe_exit_cb exit_handler;
70+
71+
struct fprobe_hlist *hlist_array;
4972
};
5073

5174
/* This fprobe is soft-disabled. */
@@ -121,4 +144,9 @@ static inline void enable_fprobe(struct fprobe *fp)
121144
fp->flags &= ~FPROBE_FL_DISABLED;
122145
}
123146

147+
/* The entry data size is 4 bits (=16) * sizeof(long) in maximum */
148+
#define FPROBE_DATA_SIZE_BITS 4
149+
#define MAX_FPROBE_DATA_SIZE_WORD ((1L << FPROBE_DATA_SIZE_BITS) - 1)
150+
#define MAX_FPROBE_DATA_SIZE (MAX_FPROBE_DATA_SIZE_WORD * sizeof(long))
151+
124152
#endif

kernel/trace/Kconfig

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,9 @@ config DYNAMIC_FTRACE_WITH_ARGS
307307

308308
config FPROBE
309309
bool "Kernel Function Probe (fprobe)"
310-
depends on FUNCTION_TRACER
311-
depends on DYNAMIC_FTRACE_WITH_REGS || DYNAMIC_FTRACE_WITH_ARGS
312-
depends on HAVE_FTRACE_REGS_HAVING_PT_REGS || !HAVE_DYNAMIC_FTRACE_WITH_ARGS
313-
depends on HAVE_RETHOOK
314-
select RETHOOK
310+
depends on HAVE_FUNCTION_GRAPH_FREGS && HAVE_FTRACE_GRAPH_FUNC
311+
depends on DYNAMIC_FTRACE_WITH_ARGS
312+
select FUNCTION_GRAPH_TRACER
315313
default n
316314
help
317315
This option enables kernel function probe (fprobe) based on ftrace.

0 commit comments

Comments
 (0)