ftrace, kprobes: Ftrace-based kprobe optimization
cover ftrace, kprobes: Ftrace-based kprobe optimization
Hi Steven,
Here, the series of patches which allows kprobes to use ftrace for optimizing probing path if the probe on ftrace (mcount call). The optimization is transparently done by kprobes.
Only if kprobe.break_handler is set, that probe can not be optimized with ftrace (nor put on ftrace). The reason why this limitation comes is that this break_handler may be used only from jprobes which changes ip address (for fetching the function arguments).
In this series, ftrace doesn't allow to change regs->ip, since I don't want to make any non-essential trouble ;)
After deep consideration, I've decided to remove "real_addr" method at this time, since it is hard to achieve complete transparency with the combination of jprobe and aggregated kprobes.
And also, at least on x86, ftrace-based kprobes is available.
Anyway, I can say jprobes is an out-dated probe because we already has kprobe-tracer and perf-probe which allows us to get function arguments directly from kprobes. :)
For using ftrace from kprobes, this series introduces two new interface for ftrace;
- ftrace_ops.regs_func, which is a callback handler invoked with pt_regs as third argument. For enable this feature, ftrace_ops.flags must set FTRACE_OPS_FL_SAVE_REGS bit.
- ftrace_set_filter_ip(), which allows to set new address-based filter instead of glob pattern.
In this series, FTRACE_OPS_FL_SAVE_REGS feature is supported only on x86 (x86-64 and i386). It may be possible to port it on other architectures too.
Also, this makes all __kprobes functions "notrace", because some of those functions are considered as to be called from kprobes handler which is called from function tracer. I think that is another discussion point. Perhaps, we need to introduce another tag which means "don't put kprobe on this function" instead of __kprobes and apply that.
Thank you,
---
Masami Hiramatsu (8):
kprobes/x86: ftrace based optiomization for x86
kprobes: introduce ftrace based optiomization
kprobes: Move locks into appropriate functions
kprobes: cleanup to separate probe-able check
ftrace: add ftrace_set_filter_ip() for address based filter ftrace/x86: Support SAVE_REGS feature on i386 ftrace/x86-64: support SAVE_REGS feature on x86-64
ftrace: Add pt_regs acceptable trace callback
Steven Rostedt (1):
kprobes: Inverse taking of module_mutex with kprobe_mutex
arch/x86/include/asm/ftrace.h | 4 + arch/x86/include/asm/kprobes.h | 1 arch/x86/kernel/entry_32.S | 64 +++++++++- arch/x86/kernel/entry_64.S | 38 +++++- arch/x86/kernel/kprobes.c | 48 ++++++++ include/linux/ftrace.h | 24 ++++ include/linux/kprobes.h | 35 +++++ kernel/kprobes.c | 256 +++++++++++++++++++++++++++++----------- kernel/trace/ftrace.c | 103 ++++++++++++++-- 9 files changed, 471 insertions(+), 102 deletions(-)
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
RFC PATCH 1/9 ftrace: Add pt_regs acceptable trace callback
Add a new callback interface regs_func to ftrace_ops which is an anonymous union to share the pointer with func member. So, current ftrace user doesn't need to change their callbacks.
This callback must be used with FTRACE_OPS_FL_SAVE_REGS.
---
include/linux/ftrace.h | 21 ++++++++++++++++++++- kernel/trace/ftrace.c | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 14 deletions(-)
include/linux/ftrace.h +20 -1
@@ -10,6 +10,8 @@#include <linux/kallsyms.h> #include <linux/linkage.h> #include <linux/bitops.h> +#include <linux/module.h> +#include <linux/ptrace.h> #include <linux/ktime.h> #include <linux/sched.h> #include <linux/types.h>
@@ -18,6 +20,14 @@#include <asm/ftrace.h> +/* +* If the arch supports saving the regs to the ftrace_ops +* then it should set this to 1. +*/ +#ifndef ARCH_SUPPORTS_FTRACE_SAVE_REGS +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 0 +#endif +struct module ;struct ftrace_hash ;
@@ -30,6 +40,8 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, loff_t *ppos);typedef void (*ftrace_func_t )(unsigned long ip,unsigned long parent_ip); +typedef void (*ftrace_regs_func_t )(unsigned long ip,unsigned long parent_ip, +struct pt_regs *regs);/* * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are
@@ -45,16 +57,22 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip);* could be controled by following calls: * ftrace_function_local_enable * ftrace_function_local_disable +* SAVE_REGS - set manualy by ftrace_ops user to denote the ftrace_ops +* requests to pass pt_regs to callback. */ enum {FTRACE_OPS_FL_ENABLED =1 <<0 ,FTRACE_OPS_FL_GLOBAL =1 <<1 ,FTRACE_OPS_FL_DYNAMIC =1 <<2 ,FTRACE_OPS_FL_CONTROL =1 <<3 , +FTRACE_OPS_FL_SAVE_REGS =1 <<4 , };struct ftrace_ops { -ftrace_func_t func; +union { +ftrace_func_t func; +ftrace_regs_func_t regs_func; + };struct ftrace_ops *next;unsigned long flags;int __percpu *disabled;
@@ -164,6 +182,7 @@ static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) }extern void ftrace_stub (unsigned long a0,unsigned long a1); +#define ftrace_regs_stub (ftrace_regs_func_t)(ftrace_stub)#else /* !CONFIG_FUNCTION_TRACER */ /*
kernel/trace/ftrace.c +31 -13
119 lines not on this page · raw message
Steven Rostedt
maintainerRe: [RFC PATCH -tip 1/9] ftrace: Add pt_regs acceptable trace callback
Quoted 11 lines · Masami Hiramatsu
struct
ftrace_ops{include/linux/ftrace.h +4
-1-ftrace_func_t func; +union { +ftrace_func_t func; +ftrace_regs_func_t regs_func; + };struct ftrace_ops *next;unsigned long flags;int __percpu *disabled;@@ -164,6 +182,7 @@ static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) }
[..]
Quoted 11 lines
static struct
ftrace_opsglobal_ops= {kernel/trace/ftrace.c +2
-1- .func = ftrace_stub, + .regs_func = ftrace_regs_stub, .notrace_hash = EMPTY_HASH, .filter_hash = EMPTY_HASH, + .flags = FTRACE_OPS_FL_SAVE_REGS, };static DEFINE_MUTEX (ftrace_regex_lock);
kernel/trace/ftrace.c void __init ftrace_init(void) · line 3930
Quoted 8 lines
kernel/trace/ftrace.c +2
-1@@ -3911,7 +3924,8 @@ void __init ftrace_init(void)#else static struct ftrace_ops global_ops = { - .func = ftrace_stub, + .regs_func = ftrace_regs_stub, + .flags =FTRACE_OPS_FL_SAVE_REGS , };
Ug, this wont compile with some versions of gcc :-(
The one I stumbled on is gcc 4.5.1 (which I test builds against 4.5.1 and 4.6.0). Then I saw this BZ:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676
This can't be a union :-( Then we can not initialize it.
I may go with my old approach and just change all callers to have a regs parameter.
-- Steve
Re: Re: [RFC PATCH -tip 1/9] ftrace: Add pt_regs acceptable trace callback
Quoted 38 lines · Steven Rostedt
Quoted 11 lines · Masami Hiramatsu
struct
ftrace_ops{include/linux/ftrace.h +4
-1-ftrace_func_t func; +union { +ftrace_func_t func; +ftrace_regs_func_t regs_func; + };struct ftrace_ops *next;unsigned long flags;int __percpu *disabled;@@ -164,6 +182,7 @@ static inline int ftrace_function_local_disabled(struct ftrace_ops *ops) }[..]
Quoted 11 lines
static struct
ftrace_opsglobal_ops= {kernel/trace/ftrace.c +2
-1- .func = ftrace_stub, + .regs_func = ftrace_regs_stub, .notrace_hash = EMPTY_HASH, .filter_hash = EMPTY_HASH, + .flags = FTRACE_OPS_FL_SAVE_REGS, };static DEFINE_MUTEX (ftrace_regex_lock);kernel/trace/ftrace.c void __init ftrace_init(void) · line 3930
Quoted 8 lines
kernel/trace/ftrace.c +2
-1@@ -3911,7 +3924,8 @@ void __init ftrace_init(void)#else static struct ftrace_ops global_ops = { - .func = ftrace_stub, + .regs_func = ftrace_regs_stub, + .flags =FTRACE_OPS_FL_SAVE_REGS , };Ug, this wont compile with some versions of gcc :-(
Quoted 6 lines
The one I stumbled on is gcc 4.5.1 (which I test builds against 4.5.1 and 4.6.0). Then I saw this BZ:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676
This can't be a union :-( Then we can not initialize it.
Hmm, how about initializing in __init function ? Or we can make func and regs_func in different members, instead of using a union. (in that case, we can remove FTRACE_OPS_FL_SAVE_REGS.)
I just consider passing uninitialized argument to user function can cause unexpected behavior...
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: Re: [RFC PATCH -tip 1/9] ftrace: Add pt_regs acceptable trace callback
Quoted 6 lines · Masami Hiramatsu
Hmm, how about initializing in
__initfunction ? Or we can make func andregs_funcin different members, instead of using a union. (in that case, we can removeFTRACE_OPS_FL_SAVE_REGS.)
I just consider passing uninitialized argument to user function can cause unexpected behavior...
Easy solution:
As I want all functions to pass the ftrace_ops anyway, we can implement the ftrace_ops and the regs passing together. The arch will need to update both at the same time.
But for archs that do not support ftrace_ops (and thus also not regs), we can do (and I will do this):
static inline void
__global_list_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops, struct pt_regs *regs)
{
[do the loop, ignoring ops anyway, but passing in regs]
}
#ifndef ARCH_SUPPORTS_FTRACE_OPS
static voidnoregs_global_list_func(unsigned long ip, unsigned long parent_ip)
{
__global_list_func(ip, parent_ip, NULL, NULL);
}#define global_list_func (ftrace_func_t)noregs_global_list_func #else
static void global_list_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops, struct pt_regs *regs)
{
__global_list_func(ip, parent_ip, ops, regs);
}#endif
Nothing will be passed uninitialized. If an arch does not support passing ftrace ops and regs, then it will be calling the noregs_global_list_func() (or whatever I name it), which only expects the ip and parent_ip as parameters. Then that will be calling the actual loop function with NULLs in the parameters.
When an arch supports passing of ftrace_ops, then it should also support passing in the regs (as that should be the trivial part).
Note, all funcs will get regs, but it may not get the full regs. That requires the ftrace_ops setting the special flag. The regs are saved for the mcount already. But only a partial set. Those will be sent to all function callbacks. If the function call back requires a full set (like kprobes does), then it must set the flag before registering.
Hows this sound?
-- Steve
Re: Re: Re: [RFC PATCH -tip 1/9] ftrace: Add pt_regs acceptable trace callback
Quoted 9 lines · Steven Rostedt
Quoted 6 lines · Masami Hiramatsu
Hmm, how about initializing in
__initfunction ? Or we can make func andregs_funcin different members, instead of using a union. (in that case, we can removeFTRACE_OPS_FL_SAVE_REGS.)
I just consider passing uninitialized argument to user function can cause unexpected behavior...
Quoted 5 lines
Easy solution:
As I want all functions to pass the
ftrace_opsanyway, we can implement theftrace_opsand the regs passing together. The arch will need to update both at the same time.
Hmm, is that ftrace_ops for recursion check? :)
Quoted 28 lines
But for archs that do not support
ftrace_ops(and thus also not regs), we can do (and I will do this):static inline void
__global_list_func(unsigned long ip, unsigned longparent_ip,
structftrace_ops*ops, structpt_regs*regs)
{
[do the loop, ignoring ops anyway, but passing in regs]
}#ifndef
ARCH_SUPPORTS_FTRACE_OPS
static voidnoregs_global_list_func(unsigned long ip, unsigned long parent_ip){ __global_list_func(ip, parent_ip, NULL, NULL); }#define
global_list_func(ftrace_func_t)noregs_global_list_func #else
static void global_list_func(unsigned long ip, unsigned longparent_ip,
structftrace_ops*ops, structpt_regs*regs){ __global_list_func(ip, parent_ip, ops, regs); }#endif
Quoted 5 lines
Nothing will be passed uninitialized. If an arch does not support passing ftrace ops and regs, then it will be calling the
noregs_global_list_func()(or whatever I name it), which only expects the ip andparent_ipas parameters. Then that will be calling the actual loop function with NULLs in the parameters.
Yeah, that's safe, but I think dyn_ftrace can't call handler directly from ftrace_call on such archs, can it?
# It depends on performance degradation.
Quoted 2 lines
When an arch supports passing of
ftrace_ops, then it should also support passing in the regs (as that should be the trivial part).
Preparing pt_regs by software is hard on some archs, e.g. IA64. But yeah, that's an obsolete arch. We'd better focus on x86 and ARM variants.
Quoted 5 lines
Note, all funcs will get regs, but it may not get the full regs. That requires the
ftrace_opssetting the special flag. The regs are saved for the mcount already. But only a partial set. Those will be sent to all function callbacks. If the function call back requires a full set (like kprobes does), then it must set the flag before registering.
Just out of curiously, would you mean that you will allocate full pt_regs frame on stack always?
Quoted 2 lines
Hows this sound?
Sounds better to me, at far as there are non-initialized parameters passed to user handler. :)
BTW, would you like to update ftrace part? I'd like to fix to remove notrace from my previous patchset and resend tomorrow.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: Re: Re: [RFC PATCH -tip 1/9] ftrace: Add pt_regs acceptable trace callback
Quoted 5 lines · Masami Hiramatsu
Quoted 3 lines
As I want all functions to pass the
ftrace_opsanyway, we can implement theftrace_opsand the regs passing together. The arch will need to update both at the same time.Hmm, is that
ftrace_opsfor recursion check? :)
Nope, it's to pass data to the callbacks.
Quoted 10 lines
Quoted 5 lines
Nothing will be passed uninitialized. If an arch does not support passing ftrace ops and regs, then it will be calling the
noregs_global_list_func()(or whatever I name it), which only expects the ip andparent_ipas parameters. Then that will be calling the actual loop function with NULLs in the parameters.Yeah, that's safe, but I think
dyn_ftracecan't call handler directly fromftrace_callon such archs, can it?
# It depends on performance degradation.
Actually, there's already a performance degradation on most archs. They must also implement a fast "shut off function tracing", and if it doesn't, it calls a helper function. I'll merge the helper function into this call so we don't have two indirections.
Quoted 6 lines
Quoted 2 lines
When an arch supports passing of
ftrace_ops, then it should also support passing in the regs (as that should be the trivial part).Preparing
pt_regsby software is hard on some archs, e.g. IA64. But yeah, that's an obsolete arch. We'd better focus on x86 and ARM variants.
It shouldn't be hard to pass a forth arg. Then if it's too hard to pass regs, it can still pass NULL. We can just make all callbacks check for NULL. I can add an config option that tests to make sure this is the case. If the regs flag isn't set, I can call the call back with NULL in the regs, and make it crash. Obviously this config will be a a debug config and not something normal users should set. :-)
Quoted 9 lines
Quoted 6 lines
Note, all funcs will get regs, but it may not get the full regs. That requires the
ftrace_opssetting the special flag. The regs are saved for the mcount already. But only a partial set. Those will be sent to all function callbacks. If the function call back requires a full set (like kprobes does), then it must set the flag before registering.Just out of curiously, would you mean that you will allocate full
pt_regsframe on stack always?
Yes. The allocation is done, but the actual storage is not. This could cause cache issues, but nothing too bad. If you are worried about stack overflow, then the code itself is using too much stack and should be reported. Of course, that's what the stack tracer is for ;-)
Quoted 9 lines
Quoted 3 lines
Hows this sound?
Sounds better to me, at far as there are non-initialized parameters passed to user handler. :)
BTW, would you like to update ftrace part? I'd like to fix to remove notrace from my previous patchset and resend tomorrow.
I'll work today on getting out a new git tree that has my latest updates.
Thanks!
-- Steve
RFC PATCH 2/9 ftrace/x86-64: support SAVE_REGS feature on x86-64
In reply to Masami HiramatsuAdd register saving/restoring sequence in ftrace_caller on x86-64 for enabling SAVE_REGS feature.
---
arch/x86/include/asm/ftrace.h | 4 ++++ arch/x86/kernel/entry_64.S | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-)
arch/x86/include/asm/ftrace.h +4 -0
@@ -32,6 +32,10 @@#define MCOUNT_ADDR ((long)(mcount))#define MCOUNT_INSN_SIZE 5/* sizeof mcount call */ +#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 ) +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 1 +#endif +#ifndef __ASSEMBLY__extern void mcount (void );extern int modifying_ftrace_code;
arch/x86/kernel/entry_64.S +33 -5
@@ -73,21 +73,44 @@ ENTRY(mcount) retq END(mcount) + .macro MCOUNT_SAVE_ALL + SAVE_ARGS (RSP-ORIG_RAX) + SAVE_REST + /* Adjust eflags, rsp and rip */ + movq RSP(%rsp), %rdx + movq %rdx, EFLAGS(%rsp) + leaq SS+8(%rsp), %rdx + movq %rdx, RSP(%rsp) + movq SS(%rsp), %rdi + subq $MCOUNT_INSN_SIZE, %rdi + movq %rdi, RIP(%rsp) + .endm + + .macro MCOUNT_RESTORE_ALL + /* store eflags into regs->rsp */ + movq EFLAGS(%rsp), %rax + movq %rax, RSP(%rsp) + RESTORE_REST + RESTORE_ARGS 1, (RSP-ORIG_RAX) + .endm + ENTRY(ftrace_caller) + CFI_STARTPROC simple + pushfq_cfi cmpl $0, function_trace_stop - jne ftrace_stub + jne ftrace_exit - MCOUNT_SAVE_FRAME + MCOUNT_SAVE_ALL - movq 0x38(%rsp), %rdi movq 8(%rbp), %rsi - subq $MCOUNT_INSN_SIZE, %rdi + movq %rsp, %rdx GLOBAL(ftrace_call) call ftrace_stub - MCOUNT_RESTORE_FRAME + MCOUNT_RESTORE_ALL + popfq_cfi #ifdef CONFIG_FUNCTION_GRAPH_TRACER GLOBAL(ftrace_graph_call) jmp ftrace_stub
@@ -95,6 +118,11 @@ GLOBAL(ftrace_graph_call) GLOBAL(ftrace_stub) retq + +ftrace_exit: + popfq_cfi + retq + CFI_ENDPROC END(ftrace_caller) #else /* ! CONFIG_DYNAMIC_FTRACE */
Steven Rostedt
maintainerRe: [RFC PATCH -tip 2/9] ftrace/x86-64: support SAVE_REGS feature on x86-64
Quoted 54 lines · Masami Hiramatsu
Add register saving/restoring sequence in
ftrace_calleron x86-64 for enablingSAVE_REGSfeature.Signed-off-by Masami Hiramatsu <[email protected]>Cc Steven Rostedt <[email protected]>---
arch/x86/include/asm/ftrace.h | 4 ++++ arch/x86/kernel/entry_64.S | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-)arch/x86/include/asm/ftrace.h +4
-0@@ -32,6 +32,10 @@#define MCOUNT_ADDR ((long)(mcount))#define MCOUNT_INSN_SIZE 5/* sizeof mcount call */ +#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 ) +#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 1 +#endif +#ifndef __ASSEMBLY__extern void mcount (void );extern int modifying_ftrace_code;arch/x86/kernel/entry_64.S +20
-0@@ -73,21 +73,44 @@ ENTRY(mcount) retq END(mcount) + .macro MCOUNT_SAVE_ALL + SAVE_ARGS (RSP-ORIG_RAX) + SAVE_REST + /* Adjust eflags, rsp and rip */ + movq RSP(%rsp), %rdx + movq %rdx, EFLAGS(%rsp) + leaq SS+8(%rsp), %rdx + movq %rdx, RSP(%rsp) + movq SS(%rsp), %rdi + subq $MCOUNT_INSN_SIZE, %rdi + movq %rdi, RIP(%rsp) + .endm + + .macro MCOUNT_RESTORE_ALL + /* store eflags into regs->rsp */ + movq EFLAGS(%rsp), %rax + movq %rax, RSP(%rsp) + RESTORE_REST + RESTORE_ARGS 1, (RSP-ORIG_RAX) + .endm
arch/x86/kernel/entry_64.S ENTRY(mcount) · line 103
Quoted 10 lines
arch/x86/kernel/entry_64.S +5
-2+ ENTRY(ftrace_caller) + CFI_STARTPROC simple + pushfq_cfi cmpl $0, function_trace_stop - jne ftrace_stub + jne ftrace_exit - MCOUNT_SAVE_FRAME + MCOUNT_SAVE_ALL
No! Please do not make ftrace save all regs for everyone. This is critical. This will slow down function tracing even more. We do not need to save all regs for every function call, unless it is asked for.
It should only save all regs if the ftrace_ops that is registered asked for it. I had code that actually does that. I can merge your patches with them if you would like.
Thanks,
-- Steve
Quoted 28 lines
arch/x86/kernel/entry_64.S +8
-3- movq 0x38(%rsp), %rdi movq 8(%rbp), %rsi - subq $MCOUNT_INSN_SIZE, %rdi + movq %rsp, %rdx GLOBAL(ftrace_call) call ftrace_stub - MCOUNT_RESTORE_FRAME + MCOUNT_RESTORE_ALL + popfq_cfi #ifdef CONFIG_FUNCTION_GRAPH_TRACER GLOBAL(ftrace_graph_call) jmp ftrace_stub@@ -95,6 +118,11 @@ GLOBAL(ftrace_graph_call) GLOBAL(ftrace_stub) retq + +ftrace_exit: + popfq_cfi + retq + CFI_ENDPROC END(ftrace_caller) #else /* ! CONFIG_DYNAMIC_FTRACE */
Re: [RFC PATCH -tip 2/9] ftrace/x86-64: support SAVE_REGS feature on x86-64
Quoted 3 lines · Steven Rostedt
No! Please do not make ftrace save all regs for everyone. This is critical. This will slow down function tracing even more. We do not need to save all regs for every function call, unless it is asked for.
Indeed, I have just removed your save_regs dynamic selector code, because I'd like to make this series as simple as possible for review.
Quoted 3 lines
It should only save all regs if the
ftrace_opsthat is registered asked for it. I had code that actually does that. I can merge your patches with them if you would like.
Yes, I'd like :)
BTW, that code which dynamically selects trace_caller on your ftrace-v2 tree, seems to be an uncompleted work. Would you already have done it?
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: [RFC PATCH -tip 2/9] ftrace/x86-64: support SAVE_REGS feature on x86-64
Quoted 3 lines · Masami Hiramatsu
BTW, that code which dynamically selects
trace_calleron your ftrace-v2 tree, seems to be an uncompleted work. Would you already have done it?
I'll have to see where I left off. I'm a bit ADHD when it comes to some of my projects. I work on them for a bit, then the next day I'll go work on something else. Eventually all my projects get done (well, I like to think they do ;-)
I'm currently working on a nasty bug that's in mainline when you enable both LOCKDEP and FUNCTION_TRACING. I've been at it since Thursday (even worked a bit over the US holiday here). I'm hoping I have a working solution for it today. But I can't work on anything else till this is complete.
After I get this bug fixed, I can take a look at the multi select code I have.
Thanks,
-- Steve
RFC PATCH 3/9 ftrace/x86: Support SAVE_REGS feature on i386
In reply to Masami HiramatsuAdd register saving/restoring sequence in ftrace_caller on i386 for enabling SAVE_REGS feature.
---
arch/x86/include/asm/ftrace.h | 2 + arch/x86/kernel/entry_32.S | 64 +++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 10 deletions(-)
arch/x86/include/asm/ftrace.h +1 -1
@@ -32,7 +32,7 @@#define MCOUNT_ADDR ((long)(mcount))#define MCOUNT_INSN_SIZE 5/* sizeof mcount call */ -#if defined(CONFIG_DYNAMIC_FTRACE ) && defined(CONFIG_X86_64 ) +#if defined(CONFIG_DYNAMIC_FTRACE )#define ARCH_SUPPORTS_FTRACE_SAVE_REGS 1#endif
arch/x86/kernel/entry_32.S +55 -9
85 lines not on this page · raw message
RFC PATCH 4/9 ftrace: add ftrace_set_filter_ip() for address based filter
In reply to Masami HiramatsuAdd a new filter update interface ftrace_set_filter_ip() to set ftrace filter by ip address, not only glob pattern.
---
include/linux/ftrace.h | 3 ++ kernel/trace/ftrace.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 2 deletions(-)
include/linux/ftrace.h +3 -0
@@ -263,6 +263,8 @@ struct dyn_ftrace { };int ftrace_force_update (void ); +int ftrace_set_filter_ip (struct ftrace_ops *ops,unsigned long ip, +int remove,int reset);int ftrace_set_filter (struct ftrace_ops *ops,unsigned char *buf,int len,int reset); int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf,
@@ -432,6 +434,7 @@ static inline int ftrace_text_reserved(void *start, void *end)*/ #define ftrace_regex_open (ops, flag, inod, file) ({ -ENODEV; })#define ftrace_set_early_filter (ops, buf, enable) do { } while (0) +#define ftrace_set_filter_ip (ops, ip, remove, reset) ({ -ENODEV; })#define ftrace_set_filter (ops, buf, len, reset) ({ -ENODEV; })#define ftrace_set_notrace (ops, buf, len, reset) ({ -ENODEV; })#define ftrace_free_filter (ops) do { } while (0)
kernel/trace/ftrace.c +57 -2
77 lines not on this page · raw message
RFC PATCH 5/9 kprobes: Inverse taking of module_mutex with kprobe_mutex
In reply to Masami HiramatsuFrom: Steven Rostedt <[email protected]>
Currently module_mutex is taken before kprobe_mutex, but this can cause issues when we have kprobes register ftrace, as the ftrace mutex is taken before enabling a tracepoint, which currently takes the module mutex.
If module_mutex is taken before kprobe_mutex, then we can not have kprobes use the ftrace infrastructure.
There seems to be no reason that the kprobe_mutex can't be taken before the module_mutex. Running lockdep shows that it is safe among the kernels I've run.
---
kernel/kprobes.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
kernel/kprobes.c +2 -2
@@ -561,9 +561,9 @@ static __kprobes void kprobe_optimizer(struct work_struct *work) {LIST_HEAD (free_list); +mutex_lock (&kprobe_mutex);/* Lock modules while optimizing kprobes */ mutex_lock (&module_mutex); -mutex_lock (&kprobe_mutex);/* * Step 1: Unoptimize kprobes and collect cleaned (unused and disarmed)
@@ -586,8 +586,8 @@ static __kprobes void kprobe_optimizer(struct work_struct *work)/* Step 4: Free cleaned kprobes after quiesence period */ do_free_cleaned_kprobes (&free_list); -mutex_unlock (&kprobe_mutex);mutex_unlock (&module_mutex); +mutex_unlock (&kprobe_mutex);/* Step 5: Kick optimizer again if needed */ if (!list_empty (&optimizing_list) || !list_empty (&unoptimizing_list))
RFC PATCH 6/9 kprobes: cleanup to separate probe-able check
In reply to Masami HiramatsuSeparate probe-able address checking code fromregister_kprobe().
---
kernel/kprobes.c | 82 ++++++++++++++++++++++++++++++------------------------ 1 files changed, 45 insertions(+), 37 deletions(-)
kernel/kprobes.c +45 -37
@@ -1313,67 +1313,80 @@ static inline int check_kprobe_rereg(struct kprobe *p)return ret; } -int __kprobes register_kprobe (struct kprobe *p) +static __kprobes int check_kprobe_address_safe (struct kprobe *p, +struct module **probed_mod) {int ret =0 ; -struct kprobe *old_p; -struct module *probed_mod; -kprobe_opcode_t *addr; - - addr =kprobe_addr (p); -if (IS_ERR (addr)) -return PTR_ERR (addr); - p->addr = addr; - - ret =check_kprobe_rereg (p); -if (ret) -return ret;jump_label_lock ();preempt_disable (); + +/* Ensure it is not in reserved area nor out of text */ if (!kernel_text_address ((unsigned long ) p->addr) ||in_kprobes_functions ((unsigned long ) p->addr) ||ftrace_text_reserved (p->addr, p->addr) ||jump_label_text_reserved (p->addr, p->addr)) { ret = -EINVAL ; - goto cannot_probe; + goto out; } -/* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ - p->flags &=KPROBE_FLAG_DISABLED ; - -/* -* Check if are we probing a module. -*/ - probed_mod =__module_text_address ((unsigned long ) p->addr); -if (probed_mod) { -/* Return -ENOENT if fail. */ - ret = -ENOENT ; +/* Check if are we probing a module */ + *probed_mod =__module_text_address ((unsigned long ) p->addr); +if (*probed_mod) {/* * We must hold a refcount of the probed module while updating * its code to prohibit unexpected unloading. */ -if (unlikely (!try_module_get (probed_mod))) - goto cannot_probe; +if (unlikely (!try_module_get (*probed_mod))) { + ret = -ENOENT ; + goto out; + }/* * If the module freed .init.text, we couldn't insert * kprobes in there. */ -if (within_module_init ((unsigned long )p->addr, probed_mod) && - probed_mod->state !=MODULE_STATE_COMING ) { -module_put (probed_mod); - goto cannot_probe; +if (within_module_init ((unsigned long )p->addr, *probed_mod) && + (*probed_mod)->state !=MODULE_STATE_COMING ) { +module_put (*probed_mod); + *probed_mod =NULL ; + ret = -ENOENT ; } -/* ret will be updated by following code */ } +out:preempt_enable ();jump_label_unlock (); +return ret; +} + +int __kprobes register_kprobe (struct kprobe *p) +{ +int ret; +struct kprobe *old_p; +struct module *probed_mod; +kprobe_opcode_t *addr; + +/* Adjust probe address from symbol */ + addr =kprobe_addr (p); +if (IS_ERR (addr)) +return PTR_ERR (addr); + p->addr = addr; + + ret =check_kprobe_rereg (p); +if (ret) +return ret; + +/* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ + p->flags &=KPROBE_FLAG_DISABLED ; p->nmissed =0 ;INIT_LIST_HEAD (&p->list); -mutex_lock (&kprobe_mutex); + ret =check_kprobe_address_safe (p, &probed_mod); +if (ret) +return ret; + +mutex_lock (&kprobe_mutex);jump_label_lock ();/* needed to call jump_label_text_reserved() */ get_online_cpus ();/* For avoiding text_mutex deadlock. */
@@ -1410,11 +1423,6 @@ out:module_put (probed_mod);return ret; - -cannot_probe: -preempt_enable (); -jump_label_unlock (); -return ret; }EXPORT_SYMBOL_GPL (register_kprobe);
RFC PATCH 7/9 kprobes: Move locks into appropriate functions
In reply to Masami HiramatsuBreak a big critical region into fine-grained pieces at registering kprobe path. This helps us to solve circular locking dependency when introducing ftrace-based kprobes.
---
kernel/kprobes.c | 63 ++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 42 insertions(+), 21 deletions(-)
kernel/kprobes.c +42 -21
@@ -759,20 +759,28 @@ static __kprobes void try_to_optimize_kprobe(struct kprobe *p)struct kprobe *ap;struct optimized_kprobe *op; +/* For preparing optimization, jump_label_text_reserved() is called */ +jump_label_lock (); +mutex_lock (&text_mutex); + ap =alloc_aggr_kprobe (p);if (!ap) -return ; + goto out; op = container_of(ap, struct optimized_kprobe, kp);if (!arch_prepared_optinsn (&op->optinsn)) {/* If failed to setup optimizing, fallback to kprobe */ arch_remove_optimized_kprobe (op);kfree (op); -return ; + goto out; }init_aggr_kprobe (ap, p); -optimize_kprobe (ap); +optimize_kprobe (ap);/* This just kicks optimizer thread */ + +out: +mutex_unlock (&text_mutex); +jump_label_unlock (); }#ifdef CONFIG_SYSCTL
@@ -1144,12 +1152,6 @@ static int __kprobes add_new_kprobe(struct kprobe *ap, struct kprobe *p)if (p->post_handler && !ap->post_handler) ap->post_handler = aggr_post_handler; -if (kprobe_disabled (ap) && !kprobe_disabled (p)) { - ap->flags &= ~KPROBE_FLAG_DISABLED ; -if (!kprobes_all_disarmed) -/* Arm the breakpoint again. */ -__arm_kprobe (ap); - }return 0 ; }
@@ -1189,11 +1191,22 @@ static int __kprobes register_aggr_kprobe(struct kprobe *orig_p,int ret =0 ;struct kprobe *ap = orig_p; +/* For preparing optimization, jump_label_text_reserved() is called */ +jump_label_lock (); +/* +* Get online CPUs to avoid text_mutex deadlock.with stop machine, +* which is invoked by unoptimize_kprobe() in add_new_kprobe() +*/ +get_online_cpus (); +mutex_lock (&text_mutex); +if (!kprobe_aggrprobe (orig_p)) {/* If orig_p is not an aggr_kprobe, create new aggr_kprobe. */ ap =alloc_aggr_kprobe (orig_p); -if (!ap) -return -ENOMEM ; +if (!ap) { + ret = -ENOMEM ; + goto out; + }init_aggr_kprobe (ap, orig_p); }else if (kprobe_unused (ap))/* This probe is going to die. Rescue it */
@@ -1213,7 +1226,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *orig_p,* free aggr_probe. It will be used next time, or * freed by unregister_kprobe. */ -return ret; + goto out;/* Prepare optimized instructions if possible. */ prepare_optimized_kprobe (ap);
@@ -1228,7 +1241,20 @@ static int __kprobes register_aggr_kprobe(struct kprobe *orig_p,/* Copy ap's insn slot to p */ copy_kprobe (ap, p); -return add_new_kprobe (ap, p); + ret =add_new_kprobe (ap, p); + +out: +mutex_unlock (&text_mutex); +put_online_cpus (); +jump_label_unlock (); + +if (ret ==0 &&kprobe_disabled (ap) && !kprobe_disabled (p)) { + ap->flags &= ~KPROBE_FLAG_DISABLED ; +if (!kprobes_all_disarmed) +/* Arm the breakpoint again. */ +arm_kprobe (ap); + } +return ret; }static int __kprobes in_kprobes_functions (unsigned long addr)
@@ -1387,10 +1413,6 @@ int __kprobes register_kprobe(struct kprobe *p)return ret;mutex_lock (&kprobe_mutex); -jump_label_lock ();/* needed to call jump_label_text_reserved() */ - -get_online_cpus ();/* For avoiding text_mutex deadlock. */ -mutex_lock (&text_mutex); old_p =get_kprobe (p->addr);if (old_p) {
@@ -1399,7 +1421,9 @@ int __kprobes register_kprobe(struct kprobe *p) goto out; } +mutex_lock (&text_mutex);/* Avoiding text modification */ ret =arch_prepare_kprobe (p); +mutex_unlock (&text_mutex);if (ret) goto out;
@@ -1408,15 +1432,12 @@ int __kprobes register_kprobe(struct kprobe *p) &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);if (!kprobes_all_disarmed && !kprobe_disabled (p)) -__arm_kprobe (p); +arm_kprobe (p);/* Try to optimize kprobe */ try_to_optimize_kprobe (p); out: -mutex_unlock (&text_mutex); -put_online_cpus (); -jump_label_unlock ();mutex_unlock (&kprobe_mutex);if (probed_mod)
RFC PATCH 8/9 kprobes: introduce ftrace based optiomization
In reply to Masami HiramatsuIntroduce function trace based kprobes optimization.
With using ftrace optimization, kprobes on the mcount calling address, use ftrace's mcount call instead of breakpoint. Farthermore, this optimization works with preemptive kernel not like as current jump-based optimization. Of cource, this feature is limited only if the probe on mcount call.
Only if kprobe.break_handler is set, that probe is not optimized with ftrace (nor put on ftrace). The reason why this limitation comes is that this break_handler may be used only from jprobes which changes ip address (for fetching the function arguments), but function tracer ignores modified ip address.
---
include/linux/kprobes.h | 35 ++++++++++++++- kernel/kprobes.c | 111 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 132 insertions(+), 14 deletions(-)
include/linux/kprobes.h +34 -1
@@ -38,6 +38,7 @@#include <linux/spinlock.h> #include <linux/rcupdate.h> #include <linux/mutex.h> +#include <linux/ftrace.h> #ifdef CONFIG_KPROBES #include <asm/kprobes.h>
@@ -48,8 +49,26 @@#define KPROBE_REENTER 0x00000004#define KPROBE_HIT_SSDONE 0x00000008 +/* +* If function tracer is enabled and the arch supports full +* passing of pt_regs to function tracing, then kprobes can +* optimize on top of function tracing. +*/ +#if defined(CONFIG_FUNCTION_TRACER ) && defined(ARCH_SUPPORTS_FTRACE_SAVE_REGS ) \ + && defined(ARCH_SUPPORTS_KPROBES_ON_FTRACE ) +# define KPROBES_CAN_USE_FTRACE +#endif +/* Attach to insert probes on any functions which should be ignored*/ -#define __kprobes __attribute__((__section__(".kprobes.text"))) +#define ____kprobes __attribute__((__section__(".kprobes.text"))) + +#ifdef KPROBES_CAN_USE_FTRACE +/* If kprobes use ftrace, its handers must be notrace. */ +# define __kprobes ____kprobes notrace +#else +# define __kprobes ____kprobes +#endif +#else /* CONFIG_KPROBES */ typedef int kprobe_opcode_t ; struct arch_specific_insn {
@@ -128,6 +147,7 @@ struct kprobe {* NOTE: * this flag is only for optimized_kprobe. */ +#define KPROBE_FLAG_FTRACE 8/* probe is using ftrace */ /* Has this kprobe gone ? */ static inline int kprobe_gone (struct kprobe *p)
@@ -146,6 +166,13 @@ static inline int kprobe_optimized(struct kprobe *p) {return p->flags &KPROBE_FLAG_OPTIMIZED ; } + +/* Is this kprobe uses ftrace ? */ +static inline int kprobe_ftrace (struct kprobe *p) +{ +return p->flags &KPROBE_FLAG_FTRACE ; +} +/* * Special probe type that uses setjmp-longjmp type tricks to resume * execution at a specified entry with a matching prototype corresponding
@@ -295,6 +322,12 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,#endif #endif /* CONFIG_OPTPROBES */ +#ifdef KPROBES_CAN_USE_FTRACE +extern void kprobe_ftrace_handler (unsigned long ip,unsigned long parent_ip, +struct pt_regs *regs); +extern int arch_prepare_kprobe_ftrace (struct kprobe *p); +#endif +/* Get the kprobe at this addr (if any) - called with preemption disabled */ struct kprobe *get_kprobe (void *addr);
kernel/kprobes.c +98 -13
196 lines not on this page · raw message
Re: [RFC PATCH -tip 8/9] kprobes: introduce ftrace based optiomization
Quoted 7 lines · Masami Hiramatsu
Introduce function trace based kprobes optimization.
With using ftrace optimization, kprobes on the mcount calling address, use ftrace's mcount call instead of breakpoint. Farthermore, this optimization works with preemptive kernel not like as current jump-based optimization. Of cource, this feature is limited only if the probe on mcount call.
The above paragraph doesn't parse correctly for me. Do you mean to say if the probe is on the mcount calling address, use the jump based approach instead of the breakpoint one? Could you please rephrase?
...
kernel/kprobes.c static __kprobes struct kprobe *alloc_aggr_kprobe(struct kprobe *p) · line 936
Quoted 8 lines
kernel/kprobes.c +8
-0+static void __kprobes kprobe_ftrace_init (void ) +{ +int ret; + + ret =register_ftrace_function (&kprobe_ftrace_ops); +WARN (ret <0 ,"Failed to init kprobe-ftrace (%d)\n" , ret); + + kprobe_ftrace_enabled =1 ;
Hmm.. is this right? kprobe_ftrace_enabled is 1 even if the init failed.
Ananth
Re: [RFC PATCH -tip 8/9] kprobes: introduce ftrace based optiomization
Quoted 9 lines · Ananth N Mavinakayanahalli
Quoted 7 lines · Masami Hiramatsu
Introduce function trace based kprobes optimization.
With using ftrace optimization, kprobes on the mcount calling address, use ftrace's mcount call instead of breakpoint. Farthermore, this optimization works with preemptive kernel not like as current jump-based optimization. Of cource, this feature is limited only if the probe on mcount call.
Quoted 3 lines
The above paragraph doesn't parse correctly for me. Do you mean to say if the probe is on the mcount calling address, use the jump based approach instead of the breakpoint one? Could you please rephrase?
Right, but not use current jump-base one, but use function tracer handler directly.
So, ftrace-based optimization will be done on the kprobe at the mcount calling address, which has been replaced with a 5 byte NOP at the build-time.
The ftrace-based optimization uses function-tracer handler (kernel/trace/ftrace.c) instead of int3 breakpoint trapping.
The probing behavior is like below
1. hit mcount calling address
2. call ftrace_caller
-> 3. save all registers
4. call ftrace's handler (kprobe_ftrace_handler) -> 5. set up current kprobe
6. call kprobe handler
<- 7. return
8. restore registers
<- 9. return
10. continue to run
Quoted 10 lines
kernel/kprobes.c static __kprobes struct kprobe *alloc_aggr_kprobe(struct kprobe *p) · line 936
Quoted 8 lines
kernel/kprobes.c +8
-0+static void __kprobes kprobe_ftrace_init (void ) +{ +int ret; + + ret =register_ftrace_function (&kprobe_ftrace_ops); +WARN (ret <0 ,"Failed to init kprobe-ftrace (%d)\n" , ret); + + kprobe_ftrace_enabled =1 ;Hmm.. is this right?
kprobe_ftrace_enabledis 1 even if the init failed.
Oops, that should be a bug! thanks!
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
RFC PATCH 9/9 kprobes/x86: ftrace based optiomization for x86
In reply to Masami HiramatsuAdd function tracer based kprobe optimization support handlers on x86. This allows kprobes to use function tracer for probing on mcount call.
---
arch/x86/include/asm/kprobes.h | 1 + arch/x86/kernel/kprobes.c | 48 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 0 deletions(-)
arch/x86/include/asm/kprobes.h +1 -0
@@ -27,6 +27,7 @@#include <asm/insn.h> #define __ARCH_WANT_KPROBES_INSN_SLOT +#define ARCH_SUPPORTS_KPROBES_ON_FTRACE struct pt_regs ;struct kprobe ;
arch/x86/kernel/kprobes.c +48 -0
54 lines not on this page · raw message
Steven Rostedt
maintainerQuoted 6 lines · Masami Hiramatsu
Also, this makes all
__kprobesfunctions "notrace", because some of those functions are considered as to be called from kprobes handler which is called from function tracer. I think that is another discussion point. Perhaps, we need to introduce another tag which means "don't put kprobe on this function" instead of__kprobesand apply that.
Actually, instead, we can force kprobes to have all "__kprobes" functions added to its 'notrace' ftrace_ops. This will just keep kprobes from function tracing these, as I find myself tracing functions marked by kprobes quite a bit.
-- Steve
Quoted 9 lines · Steven Rostedt
Quoted 6 lines · Masami Hiramatsu
Also, this makes all
__kprobesfunctions "notrace", because some of those functions are considered as to be called from kprobes handler which is called from function tracer. I think that is another discussion point. Perhaps, we need to introduce another tag which means "don't put kprobe on this function" instead of__kprobesand apply that.
Quoted 4 lines
Actually, instead, we can force kprobes to have all "
__kprobes" functions added to its 'notrace'ftrace_ops. This will just keep kprobes from function tracing these, as I find myself tracing functions marked by kprobes quite a bit.
Hmm, I'm not so sure how the notrace and filter works. What happens if I set a foo function-entry on filter and keep notrace empty?
- only foo's nop is replaced with call?
- or all functions including foo is traced?
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 7 lines · Masami Hiramatsu
Hmm, I'm not so sure how the notrace and filter works. What happens if I set a foo function-entry on filter and keep notrace empty?
- only foo's nop is replaced with call?
- or all functions including foo is traced?From
Documentation/trace/ftrace.txt:
"If a function exists in both set_ftrace_filter
and set_ftrace_notrace, the function will _not_ be traced."
The filters work exactly the same. If notrace always take precedence over filter. If you have foo and bar in filter, and put foo in notrace, then only bar is traced.
"filter" means "limit tracing only to these functions" "notrace" means "do not trace this function"
Think of 'filter' as a way of making the 'available_filter_functions' smaller. It filters the list. But 'notrace' is just like adding a 'notrace' tag. It stops it from being traced regardless.
-- Steve
Quoted 17 lines · Steven Rostedt
Quoted 5 lines · Masami Hiramatsu
Hmm, I'm not so sure how the notrace and filter works. What happens if I set a foo function-entry on filter and keep notrace empty?
- only foo's nop is replaced with call?
- or all functions including foo is traced?From
Documentation/trace/ftrace.txt:"If a function exists in both
set_ftrace_filter
andset_ftrace_notrace, the function will _not_ be traced."The filters work exactly the same. If notrace always take precedence over filter. If you have foo and bar in filter, and put foo in notrace, then only bar is traced.
Quoted 6 lines
"filter" means "limit tracing only to these functions" "notrace" means "do not trace this function"
Think of 'filter' as a way of making the '
available_filter_functions' smaller. It filters the list. But 'notrace' is just like adding a 'notrace' tag. It stops it from being traced regardless.
OK, that's same as what I expected. In that case, all __kprobes functions are already filtered out by kprobes itself. So we don't need to set that anymore.
Hmm, CFLAGS_REMOVE_kprobes.o can also keep kprobes from function tracer. So I'd like to try to use that instead of including notrace into __kprobes.
However, in that case, kprobe users must remove -pg from their kernel modules too, and take care that they must call only notrace kernel APIs...
Perhaps, we'd better introduce new kprobe flag which allow kprobe to accept new probe on ftrace, so that user can explicitly understand what he will do.
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 11 lines · Masami Hiramatsu
OK, that's same as what I expected. In that case, all
__kprobesfunctions are already filtered out by kprobes itself. So we don't need to set that anymore.Hmm, CFLAGS_REMOVE_kprobes.o can also keep kprobes from function tracer. So I'd like to try to use that instead of including notrace into
__kprobes.
However, in that case, kprobe users must remove -pg from their kernel modules too, and take care that they must call only notrace kernel APIs...
Quoted 3 lines
Perhaps, we'd better introduce new kprobe flag which allow kprobe to accept new probe on ftrace, so that user can explicitly understand what he will do.
Please do not make kprobe functions not allow function tracing! I *want* to trace these functions! For example, I trace functions in NMIs all the time, and I know these are prohibited by kprobes.
Why can't we function trace this? If kprobes does not trace functions marked with kprobes already, then it should not have any issue. Kprobes will only use the function tracer for what its allowed to use.
Do not remove -pg from anything to satisfy kprobes. It shouldn't need it.
-- Steve
Quoted 17 lines · Steven Rostedt
Quoted 11 lines · Masami Hiramatsu
OK, that's same as what I expected. In that case, all
__kprobesfunctions are already filtered out by kprobes itself. So we don't need to set that anymore.Hmm, CFLAGS_REMOVE_kprobes.o can also keep kprobes from function tracer. So I'd like to try to use that instead of including notrace into
__kprobes.
However, in that case, kprobe users must remove -pg from their kernel modules too, and take care that they must call only notrace kernel APIs...Quoted 3 lines
Perhaps, we'd better introduce new kprobe flag which allow kprobe to accept new probe on ftrace, so that user can explicitly understand what he will do.
Quoted 7 lines
Please do not make kprobe functions not allow function tracing! I *want* to trace these functions! For example, I trace functions in NMIs all the time, and I know these are prohibited by kprobes.
Why can't we function trace this? If kprobes does not trace functions marked with kprobes already, then it should not have any issue. Kprobes will only use the function tracer for what its allowed to use.
Because when I removed notrace from the __kprobes, the kernel caused triple fault and didn't boot, even kprobes was not used. I guess that it is because some recursive call of function tracer has happened. So, I've added notrace to __kprobes (but it was too widely applied).
Quoted 2 lines
Do not remove -pg from anything to satisfy kprobes. It shouldn't need it.
But some kprobes functions will/must be called from kprobes handlers. Those should be marked as notrace, shouldn't it?
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Quoted 17 lines · Steven Rostedt
Quoted 11 lines · Masami Hiramatsu
OK, that's same as what I expected. In that case, all
__kprobesfunctions are already filtered out by kprobes itself. So we don't need to set that anymore.Hmm, CFLAGS_REMOVE_kprobes.o can also keep kprobes from function tracer. So I'd like to try to use that instead of including notrace into
__kprobes.
However, in that case, kprobe users must remove -pg from their kernel modules too, and take care that they must call only notrace kernel APIs...Quoted 3 lines
Perhaps, we'd better introduce new kprobe flag which allow kprobe to accept new probe on ftrace, so that user can explicitly understand what he will do.
Quoted 7 lines
Please do not make kprobe functions not allow function tracing! I *want* to trace these functions! For example, I trace functions in NMIs all the time, and I know these are prohibited by kprobes.
Why can't we function trace this? If kprobes does not trace functions marked with kprobes already, then it should not have any issue. Kprobes will only use the function tracer for what its allowed to use.
OK, so I've introduced new noprobe tag and replaced __kprobes with it. And now __kprobes tag which is a combination of noprobe and notrace, means that the function is not probed and it can be called from kprobe handler. (thus user must use this with their handlers and functions which will be used from the handlers) And also most of __kprobes tags are replaced by noprobe only. This means that you can trace those by function tracer :)
BTW, currently kprobes allows user cases pagefault in their handler (kprobe.fault_handler will handle it). I guess that can cause some problem with ftrace, isn't it? If so, I need to deny a kprobe using ftrace if it has fault_handler.
As far as I know, systemtap relays on it.
(of course, kprobe-tracer doesn't use it)
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 6 lines · Masami Hiramatsu
OK, so I've introduced new noprobe tag and replaced
__kprobeswith it. And now__kprobestag which is a combination of noprobe and notrace, means that the function is not probed and it can be called from kprobe handler. (thus user must use this with their handlers and functions which will be used from the handlers) And also most of__kprobestags are replaced by noprobe only.
You still haven't answered my question. Why can't function tracer still trace these? If kprobes does not allow it to be probed, it should not interfere with your code. But normal function tracing should still allow these.
I still do not understand why you need to add 'notrace' at all.
Quoted 6 lines
This means that you can trace those by function tracer :)
BTW, currently kprobes allows user cases pagefault in their handler (kprobe.fault_handler will handle it). I guess that can cause some problem with ftrace, isn't it? If so, I need to deny a kprobe using ftrace if it has
fault_handler.
As long as there's recursion protection you are fine. In fact, I may add recursion protection within the assembly itself, that will make all function tracing safe. (does not solve the breakpoint bug from the other thread, but will solve most other things). In fact, this may allow us to remove notraces that were added because of recursion issues.
-- Steve
Quoted 9 lines · Steven Rostedt
Quoted 6 lines · Masami Hiramatsu
OK, so I've introduced new noprobe tag and replaced
__kprobeswith it. And now__kprobestag which is a combination of noprobe and notrace, means that the function is not probed and it can be called from kprobe handler. (thus user must use this with their handlers and functions which will be used from the handlers) And also most of__kprobestags are replaced by noprobe only.
Quoted 4 lines
You still haven't answered my question. Why can't function tracer still trace these? If kprobes does not allow it to be probed, it should not interfere with your code. But normal function tracing should still allow these.
Because those are called from ftrace-based kprobe, which means it is directly invoked from kprobe_ftrace_handler. I think that should be handled as a part of ftrace handler. Currently, I just added notrace on below two kind of functions
- handler functions which can be called intermediately from ftrace
- get_kprobe, set_kprobe_instance, etc. internal utility functions which is called directly from kprobe ftrace handler.
Quoted 1 line
I still do not understand why you need to add 'notrace' at all.
Because I'd like to solve a recursive call problem.
I saw a problem which I hit some odd function tracer behavior. When I removed notrace from get_kprobe(), which is an essential internal function called directly from kprobe_ftrace_handler, I hit a kernel crash caused by recursive call right after I registered kprobe_ftrace_handler to ftrace. At that time, ftrace_ops.filter was empty so I thought there is no function traced, but the kprobe_ftrace_handler was called from somewhere. So I saw it hit a recursive loop of ftrace_call -> kprobe_ftrace_handler -> get_kprobe -> ftrace_call ...
I think if I just register kprobe's ftrace_ops without start tracing, I think we can just do tracing without "notrace".
Quoted 7 lines
Quoted 6 lines
This means that you can trace those by function tracer :)
BTW, currently kprobes allows user cases pagefault in their handler (kprobe.fault_handler will handle it). I guess that can cause some problem with ftrace, isn't it? If so, I need to deny a kprobe using ftrace if it has
fault_handler.
Quoted 5 lines
As long as there's recursion protection you are fine. In fact, I may add recursion protection within the assembly itself, that will make all function tracing safe. (does not solve the breakpoint bug from the other thread, but will solve most other things). In fact, this may allow us to remove notraces that were added because of recursion issues.
OK, I think kprobe already solves that as long as get_kprobe and kprobe_running doesn't cause recursion...
Thank you,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerQuoted 10 lines · Masami Hiramatsu
Quoted 9 lines · Steven Rostedt
Quoted 6 lines · Masami Hiramatsu
OK, so I've introduced new noprobe tag and replaced
__kprobeswith it. And now__kprobestag which is a combination of noprobe and notrace, means that the function is not probed and it can be called from kprobe handler. (thus user must use this with their handlers and functions which will be used from the handlers) And also most of__kprobestags are replaced by noprobe only.
Quoted 6 lines
Quoted 4 lines
You still haven't answered my question. Why can't function tracer still trace these? If kprobes does not allow it to be probed, it should not interfere with your code. But normal function tracing should still allow these.
Because those are called from ftrace-based kprobe, which means
But if it has kprobes annotation on it, you can't put a kprobe on it, thus you can't kprobe function trace on it. But function tracing should not interfere with kprobe tracing. You can trace these functions with other function tracers without bothering kprobes. Function tracing should handle this.
Quoted 1 line
it is directly invoked from
kprobe_ftrace_handler.
So what? ftrace only calls the callbacks to functions that you ask to be called back for. If you put a probe on scheduler, your call back will only see the schedule function. It will not see the stack tracer tracing timers and everything else. The two are agnostic.
Quoted 2 lines
I think
that should be handled as a part of ftrace handler.
NO! Why should we limit function tracing just because one of its users can't call some functions?
How does this make it any different than what it is today? It's just an optimization for kprobes. Being able to trace things that kprobes can not, should cause no issue for kprobes. Why would NMI tracing affect kprobes using function tracer?
Show me an example of a problem that you see.
Quoted 3 lines
Currently, I just added notrace on below two kind of functions
- handler functions which can be called intermediately from ftrace
Do they currently break ftrace?
Quoted 2 lines
-
get_kprobe,set_kprobe_instance, etc. internal utility functions which is called directly from kprobe ftrace handler.
Why can't we function trace these? Note, if we have two function tracers, A and B. And A's handler calls something that B traces, it should not be an issue, as long as B does not call something that A traces.
Now if this does happen, it is trivial to add recursion protection in the function tracer code itself. Such that B's handler will not be called if A calls something B traces.
If we just add notrace all over the kernel to protect against this, soon there will be nothing left to trace.
Quoted 6 lines
Quoted 3 lines
I still do not understand why you need to add 'notrace' at all.
Because I'd like to solve a recursive call problem.
Quoted 9 lines
I saw a problem which I hit some odd function tracer behavior. When I removed notrace from
get_kprobe(), which is an essential internal function called directly fromkprobe_ftrace_handler, I hit a kernel crash caused by recursive call right after I registeredkprobe_ftrace_handlerto ftrace. At that time, ftrace_ops.filter was empty so I thought there is no function traced, but thekprobe_ftrace_handlerwas called from somewhere. So I saw it hit a recursive loop offtrace_call->kprobe_ftrace_handler->get_kprobe->ftrace_call...
OK, then the recursion protection I want to add will solve this. But why would the ftrace_call call the kprobe_ftrace_handler? You should be setting up the filter before registering the trace.
Quoted 3 lines
I think if I just register kprobe's
ftrace_opswithout start tracing, I think we can just do tracing without "notrace".
You should be able to register the filter first, and then register function tracer. If you register without setting the filter, you will start tracing all functions.
I think that may be the problem you are seeing. You want to register the filter first and then the ftrace_ops.
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
This means that you can trace those by function tracer :)
BTW, currently kprobes allows user cases pagefault in their handler (kprobe.fault_handler will handle it). I guess that can cause some problem with ftrace, isn't it? If so, I need to deny a kprobe using ftrace if it has
fault_handler.
Quoted 8 lines
Quoted 5 lines
As long as there's recursion protection you are fine. In fact, I may add recursion protection within the assembly itself, that will make all function tracing safe. (does not solve the breakpoint bug from the other thread, but will solve most other things). In fact, this may allow us to remove notraces that were added because of recursion issues.
OK, I think kprobe already solves that as long as
get_kprobeandkprobe_runningdoesn't cause recursion...
I think the issue is to register the filter first. But I still need to prevent that recursion protection.
-- Steve
Quoted 10 lines · Steven Rostedt
Quoted 2 lines · Masami Hiramatsu
I think if I just register kprobe's
ftrace_opswithout start tracing, I think we can just do tracing without "notrace".You should be able to register the filter first, and then register function tracer. If you register without setting the filter, you will start tracing all functions.
I think that may be the problem you are seeing. You want to register the filter first and then the
ftrace_ops.
Ah, that's all what I need to know! :)
OK, I'll do that for avoiding recursion problem.
Thanks!
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]