tracing: updates for 3.5
Steven Rostedt
maintainerIngo,
Although only two patches are in this, it really contains the 5 patches that I pushed out earlier. As only patch 4/5 changed, instead of spamming LKML with the same patches 1-3, I'm only reposting 4 and 5.
Patch 5 just came along for the ride (same as the previous post).
Patch 4 (here it's patch 1) was update as per Masami's suggestions (again).
Thanks!
-- Steve
Please pull the latest tip/perf/core-2 tree, which can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
tip/perf/core-2
Head SHA1: e2017387836dcb963fcbefa767f9f20282349c75
Steven Rostedt (2):
ftrace/x86: Have arch x86_64 use breakpoints instead of stop machine ftrace/x86: Remove the complex ftrace NMI handling code
----
arch/x86/Kconfig | 1 - arch/x86/include/asm/ftrace.h | 3 + arch/x86/kernel/ftrace.c | 511 +++++++++++++++++++++++++++-------------- arch/x86/kernel/nmi.c | 10 +- arch/x86/kernel/traps.c | 8 +- include/linux/ftrace.h | 6 + 6 files changed, 364 insertions(+), 175 deletions(-)
Steven Rostedt
maintainerPATCH v2 1/2 ftrace/x86: Have arch x86_64 use breakpoints instead of stop machine
From: Steven Rostedt <[email protected]>
This method changes x86 to add a breakpoint to the mcount locations instead of calling stop machine.
Now that iret can be handled by NMIs, we perform the following to update code:
1) Add a breakpoint to all locations that will be modified
2) Sync all cores
3) Update all locations to be either a nop or call (except breakpoint op)
4) Sync all cores
5) Remove the breakpoint with the new code.
6) Sync all cores
[
Added updates that Masami suggested:
Use unlikely(modifying_ftrace_code) in int3 trap to keep kprobes efficient. Don't use NOTIFY_* in ftrace handler in int3 as it is not a notifier.
]
--- arch/x86/include/asm/ftrace.h | 3 + arch/x86/kernel/ftrace.c | 342 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/traps.c | 8 +- include/linux/ftrace.h | 6 + 4 files changed, 358 insertions(+), 1 deletion(-)
arch/x86/include/asm/ftrace.h +3 -0
@@ -34,6 +34,7 @@#ifndef __ASSEMBLY__extern void mcount (void ); +extern int modifying_ftrace_code;static inline unsigned long ftrace_call_adjust (unsigned long addr) {
@@ -50,6 +51,8 @@ struct dyn_arch_ftrace {/* No extra data needed for x86 */ }; +int ftrace_int3_handler (struct pt_regs *regs); +#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */
arch/x86/kernel/ftrace.c +342 -0
354 lines not on this page · raw message
arch/x86/kernel/traps.c +7 -1
@@ -50,6 +50,7 @@#include <asm/processor.h> #include <asm/debugreg.h> #include <linux/atomic.h> +#include <asm/ftrace.h> #include <asm/traps.h> #include <asm/desc.h> #include <asm/i387.h>
@@ -303,8 +304,13 @@ gp_in_kernel: }/* May run on IST stack. */ -dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) +dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_code) { +#ifdef CONFIG_DYNAMIC_FTRACE +/* ftrace must be first, everything else may cause a recursive crash */ +if (unlikely (modifying_ftrace_code) &&ftrace_int3_handler (regs)) +return ; +#endif #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap (DIE_INT3 ,"int3" , regs, error_code,X86_TRAP_BP ,SIGTRAP ) ==NOTIFY_STOP )
include/linux/ftrace.h +6 -0
@@ -286,6 +286,12 @@ struct ftrace_rec_iter *ftrace_rec_iter_start(void);struct ftrace_rec_iter *ftrace_rec_iter_next (struct ftrace_rec_iter *iter);struct dyn_ftrace *ftrace_rec_iter_record (struct ftrace_rec_iter *iter); +#define for_ftrace_rec_iter (iter) \ + for (iter = ftrace_rec_iter_start(); \ + iter; \ + iter = ftrace_rec_iter_next(iter)) + +int ftrace_update_record (struct dyn_ftrace *rec,int enable);int ftrace_test_record (struct dyn_ftrace *rec,int enable);void ftrace_run_stop_machine (int command);
Signature · 1 line
1.7.9.5
[tip:x86/ftrace] ftrace, x86: Have arch x86_64 use breakpoints instead of stop machine
Commit-ID: d7d7199002115b26687d6b78b380bb9fb9e53254 Gitweb: http://git.kernel.org/tip/d7d7199002115b26687d6b78b380bb9fb9e53254 Author: Steven Rostedt <[email protected]> AuthorDate: Thu, 26 Apr 2012 13:34:05 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 26 Apr 2012 11:22:20 -0700
ftrace, x86: Have arch x86_64 use breakpoints instead of stop machine
This method changes x86 to add a breakpoint to the mcount locations instead of calling stop machine.
Now that iret can be handled by NMIs, we perform the following to update code:
1) Add a breakpoint to all locations that will be modified
2) Sync all cores
3) Update all locations to be either a nop or call (except breakpoint op)
4) Sync all cores
5) Remove the breakpoint with the new code.
6) Sync all cores
[
Added updates that Masami suggested:
Use unlikely(modifying_ftrace_code) in int3 trap to keep kprobes efficient. Don't use NOTIFY_* in ftrace handler in int3 as it is not a notifier.
]
--- arch/x86/include/asm/ftrace.h | 3 + arch/x86/kernel/ftrace.c | 342 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/traps.c | 8 +- include/linux/ftrace.h | 6 + 4 files changed, 358 insertions(+), 1 deletions(-)
arch/x86/include/asm/ftrace.h +3 -0
@@ -34,6 +34,7 @@#ifndef __ASSEMBLY__extern void mcount (void ); +extern int modifying_ftrace_code;static inline unsigned long ftrace_call_adjust (unsigned long addr) {
@@ -50,6 +51,8 @@ struct dyn_arch_ftrace {/* No extra data needed for x86 */ }; +int ftrace_int3_handler (struct pt_regs *regs); +#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */
arch/x86/kernel/ftrace.c +342 -0
354 lines not on this page · raw message
arch/x86/kernel/traps.c +7 -1
@@ -50,6 +50,7 @@#include <asm/processor.h> #include <asm/debugreg.h> #include <linux/atomic.h> +#include <asm/ftrace.h> #include <asm/traps.h> #include <asm/desc.h> #include <asm/i387.h>
@@ -303,8 +304,13 @@ gp_in_kernel: }/* May run on IST stack. */ -dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) +dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_code) { +#ifdef CONFIG_DYNAMIC_FTRACE +/* ftrace must be first, everything else may cause a recursive crash */ +if (unlikely (modifying_ftrace_code) &&ftrace_int3_handler (regs)) +return ; +#endif #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap (DIE_INT3 ,"int3" , regs, error_code,X86_TRAP_BP ,SIGTRAP ) ==NOTIFY_STOP )
include/linux/ftrace.h +6 -0
@@ -286,6 +286,12 @@ struct ftrace_rec_iter *ftrace_rec_iter_start(void);struct ftrace_rec_iter *ftrace_rec_iter_next (struct ftrace_rec_iter *iter);struct dyn_ftrace *ftrace_rec_iter_record (struct ftrace_rec_iter *iter); +#define for_ftrace_rec_iter (iter) \ + for (iter = ftrace_rec_iter_start(); \ + iter; \ + iter = ftrace_rec_iter_next(iter)) + +int ftrace_update_record (struct dyn_ftrace *rec,int enable);int ftrace_test_record (struct dyn_ftrace *rec,int enable);void ftrace_run_stop_machine (int command);
Re: [PATCH 1/2 v2] ftrace/x86: Have arch x86_64 use breakpoints instead of stop machine
In reply to Steven RostedtQuoted 19 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
This method changes x86 to add a breakpoint to the mcount locations instead of calling stop machine.
Now that iret can be handled by NMIs, we perform the following to update code:
1) Add a breakpoint to all locations that will be modified
2) Sync all cores
3) Update all locations to be either a nop or call (except breakpoint op)
4) Sync all cores
5) Remove the breakpoint with the new code.
Quoted 7 lines
6) Sync all cores
[
Added updates that Masami suggested:
Useunlikely(modifying_ftrace_code)in int3 trap to keep kprobes efficient. Don't use NOTIFY_* in ftrace handler in int3 as it is not a notifier.
]
This looks good to me :)
Quoted 436 lines
Cc Masami Hiramatsu <[email protected]>Cc H. Peter Anvin <[email protected]>Signed-off-by Steven Rostedt <[email protected]>--- arch/x86/include/asm/ftrace.h | 3 + arch/x86/kernel/ftrace.c | 342 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/traps.c | 8 +- include/linux/ftrace.h | 6 + 4 files changed, 358 insertions(+), 1 deletion(-)arch/x86/include/asm/ftrace.h +3
-0@@ -34,6 +34,7 @@#ifndef __ASSEMBLY__extern void mcount (void ); +extern int modifying_ftrace_code;static inline unsigned long ftrace_call_adjust (unsigned long addr) {@@ -50,6 +51,8 @@ struct dyn_arch_ftrace {/* No extra data needed for x86 */ }; +int ftrace_int3_handler (struct pt_regs *regs); +#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */ arch/x86/kernel/ftrace.c +342
-0@@ -20,6 +20,7 @@#include <linux/init.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/kprobes.h> #include <trace/syscall.h> @@ -334,6 +335,347 @@ int ftrace_update_ftrace_func(ftrace_func_t func)return ret; } +int modifying_ftrace_code__read_mostly ; + +/* +* A breakpoint was added to the code address we are about to +* modify, and this is the handle that will just skip over it. +* We are either changing a nop into a trace call, or a trace +* call to a nop. While the change is taking place, we treat +* it just like it was a nop. +*/ +int ftrace_int3_handler (struct pt_regs *regs) +{ +if (WARN_ON_ONCE (!regs)) +return 0 ; + +if (!ftrace_location (regs->ip -1 )) +return 0 ; + + regs->ip +=MCOUNT_INSN_SIZE -1 ; + +return 1 ; +} + +static int ftrace_write (unsigned long ip,const char *val,int size) +{ +/* +* On x86_64, kernel text mappings are mapped read-only with +* CONFIG_DEBUG_RODATA. So we use the kernel identity mapping instead +* of the kernel text mapping to modify the kernel text. +* +* For 32bit kernels, these mappings are same and we can use +* kernel identity mapping to modify code. +*/ +if (within (ip, (unsigned long )_text, (unsigned long )_etext)) + ip = (unsigned long )__va (__pa (ip)); + +return probe_kernel_write ((void *)ip, val, size); +} + +static int add_break (unsigned long ip,const char *old) +{ +unsigned char replaced[MCOUNT_INSN_SIZE ]; +unsigned char brk =BREAKPOINT_INSTRUCTION ; + +if (probe_kernel_read (replaced, (void *)ip,MCOUNT_INSN_SIZE )) +return -EFAULT ; + +/* Make sure it is what we expect it to be */ +if (memcmp (replaced, old,MCOUNT_INSN_SIZE ) !=0 ) +return -EINVAL ; + +if (ftrace_write (ip, &brk,1 )) +return -EPERM ; + +return 0 ; +} + +static int add_brk_on_call (struct dyn_ftrace *rec,unsigned long addr) +{ +unsigned const char *old; +unsigned long ip = rec->ip; + + old =ftrace_call_replace (ip, addr); + +return add_break (rec->ip, old); +} + + +static int add_brk_on_nop (struct dyn_ftrace *rec) +{ +unsigned const char *old; + + old =ftrace_nop_replace (); + +return add_break (rec->ip, old); +} + +static int add_breakpoints (struct dyn_ftrace *rec,int enable) +{ +unsigned long ftrace_addr; +int ret; + + ret =ftrace_test_record (rec, enable); + + ftrace_addr = (unsigned long )FTRACE_ADDR ; + +switch (ret) { +case FTRACE_UPDATE_IGNORE : +return 0 ; + +case FTRACE_UPDATE_MAKE_CALL : +/* converting nop to call */ +return add_brk_on_nop (rec); + +case FTRACE_UPDATE_MAKE_NOP : +/* converting a call to a nop */ +return add_brk_on_call (rec, ftrace_addr); + } +return 0 ; +} + +/* +* On error, we need to remove breakpoints. This needs to +* be done caefully. If the address does not currently have a +* breakpoint, we know we are done. Otherwise, we look at the +* remaining 4 bytes of the instruction. If it matches a nop +* we replace the breakpoint with the nop. Otherwise we replace +* it with the call instruction. +*/ +static int remove_breakpoint (struct dyn_ftrace *rec) +{ +unsigned char ins[MCOUNT_INSN_SIZE ]; +unsigned char brk =BREAKPOINT_INSTRUCTION ; +const unsigned char *nop; +unsigned long ftrace_addr; +unsigned long ip = rec->ip; + +/* If we fail the read, just give up */ +if (probe_kernel_read (ins, (void *)ip,MCOUNT_INSN_SIZE )) +return -EFAULT ; + +/* If this does not have a breakpoint, we are done */ +if (ins[0 ] != brk) +return -1 ; + + nop =ftrace_nop_replace (); + +/* +* If the last 4 bytes of the instruction do not match +* a nop, then we assume that this is a call to ftrace_addr. +*/ +if (memcmp (&ins[1 ], &nop[1 ],MCOUNT_INSN_SIZE -1 ) !=0 ) { +/* +* For extra paranoidism, we check if the breakpoint is on +* a call that would actually jump to the ftrace_addr. +* If not, don't touch the breakpoint, we make just create +* a disaster. +*/ + ftrace_addr = (unsigned long )FTRACE_ADDR ; + nop =ftrace_call_replace (ip, ftrace_addr); + +if (memcmp (&ins[1 ], &nop[1 ],MCOUNT_INSN_SIZE -1 ) !=0 ) +return -EINVAL ; + } + +return probe_kernel_write ((void *)ip, &nop[0 ],1 ); +} + +static int add_update_code (unsigned long ip,unsigned const char *new) +{ +/* skip breakpoint */ + ip++; + new++; +if (ftrace_write (ip, new,MCOUNT_INSN_SIZE -1 )) +return -EPERM ; +return 0 ; +} + +static int add_update_call (struct dyn_ftrace *rec,unsigned long addr) +{ +unsigned long ip = rec->ip; +unsigned const char *new; + + new =ftrace_call_replace (ip, addr); +return add_update_code (ip, new); +} + +static int add_update_nop (struct dyn_ftrace *rec) +{ +unsigned long ip = rec->ip; +unsigned const char *new; + + new =ftrace_nop_replace (); +return add_update_code (ip, new); +} + +static int add_update (struct dyn_ftrace *rec,int enable) +{ +unsigned long ftrace_addr; +int ret; + + ret =ftrace_test_record (rec, enable); + + ftrace_addr = (unsigned long )FTRACE_ADDR ; + +switch (ret) { +case FTRACE_UPDATE_IGNORE : +return 0 ; + +case FTRACE_UPDATE_MAKE_CALL : +/* converting nop to call */ +return add_update_call (rec, ftrace_addr); + +case FTRACE_UPDATE_MAKE_NOP : +/* converting a call to a nop */ +return add_update_nop (rec); + } + +return 0 ; +} + +static int finish_update_call (struct dyn_ftrace *rec,unsigned long addr) +{ +unsigned long ip = rec->ip; +unsigned const char *new; + + new =ftrace_call_replace (ip, addr); + +if (ftrace_write (ip, new,1 )) +return -EPERM ; + +return 0 ; +} + +static int finish_update_nop (struct dyn_ftrace *rec) +{ +unsigned long ip = rec->ip; +unsigned const char *new; + + new =ftrace_nop_replace (); + +if (ftrace_write (ip, new,1 )) +return -EPERM ; +return 0 ; +} + +static int finish_update (struct dyn_ftrace *rec,int enable) +{ +unsigned long ftrace_addr; +int ret; + + ret =ftrace_update_record (rec, enable); + + ftrace_addr = (unsigned long )FTRACE_ADDR ; + +switch (ret) { +case FTRACE_UPDATE_IGNORE : +return 0 ; + +case FTRACE_UPDATE_MAKE_CALL : +/* converting nop to call */ +return finish_update_call (rec, ftrace_addr); + +case FTRACE_UPDATE_MAKE_NOP : +/* converting a call to a nop */ +return finish_update_nop (rec); + } + +return 0 ; +} + +static void do_sync_core (void *data) +{ +sync_core (); +} + +static void run_sync (void ) +{ +int enable_irqs =irqs_disabled (); + +/* We may be called with interrupts disbled (on bootup). */ +if (enable_irqs) +local_irq_enable (); +on_each_cpu (do_sync_core,NULL ,1 ); +if (enable_irqs) +local_irq_disable (); +} + +static void ftrace_replace_code (int enable) +{ +struct ftrace_rec_iter *iter; +struct dyn_ftrace *rec; +const char *report ="adding breakpoints" ; +int count =0 ; +int ret; + +for_ftrace_rec_iter (iter) { + rec =ftrace_rec_iter_record (iter); + + ret =add_breakpoints (rec, enable); +if (ret) + goto remove_breakpoints; + count++; + } + +run_sync (); + + report ="updating code" ; + +for_ftrace_rec_iter (iter) { + rec =ftrace_rec_iter_record (iter); + + ret =add_update (rec, enable); +if (ret) + goto remove_breakpoints; + } + +run_sync (); + + report ="removing breakpoints" ; + +for_ftrace_rec_iter (iter) { + rec =ftrace_rec_iter_record (iter); + + ret =finish_update (rec, enable); +if (ret) + goto remove_breakpoints; + } + +run_sync (); + +return ; + + remove_breakpoints: +ftrace_bug (ret, rec ? rec->ip :0 ); +printk (KERN_WARNING "Failed on %s (%d):\n" , report, count); +for_ftrace_rec_iter (iter) { + rec =ftrace_rec_iter_record (iter); +remove_breakpoint (rec); + } +} + +void arch_ftrace_update_code (int command) +{ + modifying_ftrace_code++; + +if (command &FTRACE_UPDATE_CALLS ) +ftrace_replace_code (1 ); +else if (command &FTRACE_DISABLE_CALLS ) +ftrace_replace_code (0 ); + +if (command &FTRACE_UPDATE_TRACE_FUNC ) +ftrace_update_ftrace_func (ftrace_trace_function); + +if (command &FTRACE_START_FUNC_RET ) +ftrace_enable_ftrace_graph_caller (); +else if (command &FTRACE_STOP_FUNC_RET ) +ftrace_disable_ftrace_graph_caller (); + + modifying_ftrace_code--; +} +int __init ftrace_dyn_arch_init (void *data) {/* The return code is retured via data */ arch/x86/kernel/traps.c +7
-1@@ -50,6 +50,7 @@#include <asm/processor.h> #include <asm/debugreg.h> #include <linux/atomic.h> +#include <asm/ftrace.h> #include <asm/traps.h> #include <asm/desc.h> #include <asm/i387.h> @@ -303,8 +304,13 @@ gp_in_kernel: }/* May run on IST stack. */ -dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) +dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_code) { +#ifdef CONFIG_DYNAMIC_FTRACE +/* ftrace must be first, everything else may cause a recursive crash */ +if (unlikely (modifying_ftrace_code) &&ftrace_int3_handler (regs)) +return ; +#endif #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap (DIE_INT3 ,"int3" , regs, error_code,X86_TRAP_BP ,SIGTRAP ) ==NOTIFY_STOP )include/linux/ftrace.h +6
-0@@ -286,6 +286,12 @@ struct ftrace_rec_iter *ftrace_rec_iter_start(void);struct ftrace_rec_iter *ftrace_rec_iter_next (struct ftrace_rec_iter *iter);struct dyn_ftrace *ftrace_rec_iter_record (struct ftrace_rec_iter *iter); +#define for_ftrace_rec_iter (iter) \ + for (iter = ftrace_rec_iter_start(); \ + iter; \ + iter = ftrace_rec_iter_next(iter)) + +int ftrace_update_record (struct dyn_ftrace *rec,int enable);int ftrace_test_record (struct dyn_ftrace *rec,int enable);void ftrace_run_stop_machine (int command);
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerPATCH v2 2/2 ftrace/x86: Remove the complex ftrace NMI handling code
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
As ftrace function tracing would require modifying code that could be executed in NMI context, which is not stopped with stop_machine(), ftrace had to do a complex algorithm with various stages of setup and memory barriers to make it work.
With the new breakpoint method, this is no longer required. The changes to the code can be done without any problem in NMI context, as well as without stop machine altogether. Remove the complex code as it is no longer needed.
Also, a lot of the notrace annotations could be removed from the NMI code as it is now safe to trace them. With the exception of do_nmi itself, which does some special work to handle running in the debug stack. The breakpoint method can cause NMIs to double nest the debug stack if it's not setup properly, and that is done in do_nmi(), thus that function must not be traced.
(Note the arch sh may want to do the same)
--- arch/x86/Kconfig | 1 - arch/x86/kernel/ftrace.c | 169 +--------------------------------------------- arch/x86/kernel/nmi.c | 10 +-- 3 files changed, 6 insertions(+), 174 deletions(-)
arch/x86/Kconfig +0 -1
@@ -40,7 +40,6 @@ config X86 select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_GRAPH_FP_TEST select HAVE_FUNCTION_TRACE_MCOUNT_TEST - select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE select HAVE_SYSCALL_TRACEPOINTS select HAVE_KVM select HAVE_ARCH_KGDB
arch/x86/kernel/ftrace.c +1 -168
199 lines not on this page · raw message
arch/x86/kernel/nmi.c +5 -5
@@ -84,7 +84,7 @@ __setup("unknown_nmi_panic", setup_unknown_nmi_panic);#define nmi_to_desc (type) (&nmi_desc[type]) -static int notrace __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b) +static int __kprobes nmi_handle (unsigned int type,struct pt_regs *regs,bool b2b) {struct nmi_desc *desc =nmi_to_desc (type);struct nmiaction *a;
@@ -209,7 +209,7 @@ void unregister_nmi_handler(unsigned int type, const char *name)EXPORT_SYMBOL_GPL (unregister_nmi_handler); -static notrace __kprobes void +static __kprobes void pci_serr_error (unsigned char reason,struct pt_regs *regs) { pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
@@ -236,7 +236,7 @@ pci_serr_error(unsigned char reason, struct pt_regs *regs)outb (reason,NMI_REASON_PORT ); } -static notrace __kprobes void +static __kprobes void io_check_error (unsigned char reason,struct pt_regs *regs) {unsigned long i;
@@ -263,7 +263,7 @@ io_check_error(unsigned char reason, struct pt_regs *regs)outb (reason,NMI_REASON_PORT ); } -static notrace __kprobes void +static __kprobes void unknown_nmi_error (unsigned char reason,struct pt_regs *regs) {int handled;
@@ -305,7 +305,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs) static DEFINE_PER_CPU(bool, swallow_nmi); static DEFINE_PER_CPU(unsigned long, last_nmi_rip); -static notrace __kprobes void default_do_nmi(struct pt_regs *regs) +static __kprobes void default_do_nmi (struct pt_regs *regs) {unsigned char reason =0 ;int handled;
Signature · 1 line
1.7.9.5
[tip:x86/ftrace] ftrace, x86: Remove the complex ftrace NMI handling code
Commit-ID: bf6266f9db57ee6fcbcb3e3da824dc6d33531720 Gitweb: http://git.kernel.org/tip/bf6266f9db57ee6fcbcb3e3da824dc6d33531720 Author: Steven Rostedt <[email protected]> AuthorDate: Thu, 26 Apr 2012 13:34:06 -0400 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 26 Apr 2012 11:22:29 -0700
ftrace, x86: Remove the complex ftrace NMI handling code
As ftrace function tracing would require modifying code that could be executed in NMI context, which is not stopped with stop_machine(), ftrace had to do a complex algorithm with various stages of setup and memory barriers to make it work.
With the new breakpoint method, this is no longer required. The changes to the code can be done without any problem in NMI context, as well as without stop machine altogether. Remove the complex code as it is no longer needed.
Also, a lot of the notrace annotations could be removed from the NMI code as it is now safe to trace them. With the exception of do_nmi itself, which does some special work to handle running in the debug stack. The breakpoint method can cause NMIs to double nest the debug stack if it's not setup properly, and that is done in do_nmi(), thus that function must not be traced.
(Note the arch sh may want to do the same)
--- arch/x86/Kconfig | 1 - arch/x86/kernel/ftrace.c | 169 +--------------------------------------------- arch/x86/kernel/nmi.c | 10 ++-- 3 files changed, 6 insertions(+), 174 deletions(-)
arch/x86/Kconfig +0 -1
@@ -40,7 +40,6 @@ config X86 select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_GRAPH_FP_TEST select HAVE_FUNCTION_TRACE_MCOUNT_TEST - select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE select HAVE_SYSCALL_TRACEPOINTS select HAVE_KVM select HAVE_ARCH_KGDB
arch/x86/kernel/ftrace.c +1 -168
199 lines not on this page · raw message
arch/x86/kernel/nmi.c +5 -5
@@ -84,7 +84,7 @@ __setup("unknown_nmi_panic", setup_unknown_nmi_panic);#define nmi_to_desc (type) (&nmi_desc[type]) -static int notrace __kprobes nmi_handle(unsigned int type, struct pt_regs *regs, bool b2b) +static int __kprobes nmi_handle (unsigned int type,struct pt_regs *regs,bool b2b) {struct nmi_desc *desc =nmi_to_desc (type);struct nmiaction *a;
@@ -209,7 +209,7 @@ void unregister_nmi_handler(unsigned int type, const char *name)EXPORT_SYMBOL_GPL (unregister_nmi_handler); -static notrace __kprobes void +static __kprobes void pci_serr_error (unsigned char reason,struct pt_regs *regs) { pr_emerg("NMI: PCI system error (SERR) for reason %02x on CPU %d.\n",
@@ -236,7 +236,7 @@ pci_serr_error(unsigned char reason, struct pt_regs *regs)outb (reason,NMI_REASON_PORT ); } -static notrace __kprobes void +static __kprobes void io_check_error (unsigned char reason,struct pt_regs *regs) {unsigned long i;
@@ -263,7 +263,7 @@ io_check_error(unsigned char reason, struct pt_regs *regs)outb (reason,NMI_REASON_PORT ); } -static notrace __kprobes void +static __kprobes void unknown_nmi_error (unsigned char reason,struct pt_regs *regs) {int handled;
@@ -305,7 +305,7 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs) static DEFINE_PER_CPU(bool, swallow_nmi); static DEFINE_PER_CPU(unsigned long, last_nmi_rip); -static notrace __kprobes void default_do_nmi(struct pt_regs *regs) +static __kprobes void default_do_nmi (struct pt_regs *regs) {unsigned char reason =0 ;int handled;
Steven Rostedt
maintainerHi Peter,
I see you pulled in the patches individually instead of doing a git pull. But you missed the three patches that were in the previous pull request (that I only left out to not spam LKML as they were not changed). Also, without the git pull, it makes my repo out of sync with tip. As that is usually how I know what was pushed upstream or not.
-- Steve
Quoted 34 lines · Steven Rostedt
Ingo,
Although only two patches are in this, it really contains the 5 patches that I pushed out earlier. As only patch 4/5 changed, instead of spamming LKML with the same patches 1-3, I'm only reposting 4 and 5.
Patch 5 just came along for the ride (same as the previous post).
Patch 4 (here it's patch 1) was update as per Masami's suggestions (again).
Thanks!
-- Steve
Please pull the latest tip/perf/core-2 tree, which can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
tip/perf/core-2Head SHA1:
e2017387836dcb963fcbefa767f9f20282349c75Steven Rostedt (2):
ftrace/x86: Have archx86_64use breakpoints instead of stop machine ftrace/x86: Remove the complex ftrace NMI handling code----
arch/x86/Kconfig | 1 - arch/x86/include/asm/ftrace.h | 3 + arch/x86/kernel/ftrace.c | 511 +++++++++++++++++++++++++++-------------- arch/x86/kernel/nmi.c | 10 +- arch/x86/kernel/traps.c | 8 +- include/linux/ftrace.h | 6 + 6 files changed, 364 insertions(+), 175 deletions(-)
Steven Rostedt
maintainerQuoted 8 lines · Steven Rostedt
Hi Peter,
I see you pulled in the patches individually instead of doing a git pull. But you missed the three patches that were in the previous pull request (that I only left out to not spam LKML as they were not changed). Also, without the git pull, it makes my repo out of sync with tip. As that is usually how I know what was pushed upstream or not.
Quoted 14 lines
-- Steve
Quoted 10 lines · Steven Rostedt
Ingo,
Although only two patches are in this, it really contains the 5 patches that I pushed out earlier. As only patch 4/5 changed, instead of spamming LKML with the same patches 1-3, I'm only reposting 4 and 5.
Patch 5 just came along for the ride (same as the previous post).
Patch 4 (here it's patch 1) was update as per Masami's suggestions (again).
Peter,
I just realized that these two patches contained a Cc to you, but the cover letter did not Cc you. Probably confused you in what to pull.
Sorry about that.
-- Steve
Quoted 8 lines · Steven Rostedt
Peter,
I just realized that these two patches contained a Cc to you, but the cover letter did not Cc you. Probably confused you in what to pull.
Sorry about that.
Joy. Let me figure out the remaining patches and pull them in.
-hpa
Steven Rostedt
maintainerQuoted 4 lines · H. Peter Anvin
Quoted 3 lines · Steven Rostedt
Peter,
Quoted 8 lines
Quoted 5 lines
I just realized that these two patches contained a Cc to you, but the cover letter did not Cc you. Probably confused you in what to pull.
Sorry about that.
Joy. Let me figure out the remaining patches and pull them in.
Do you want me to rebase on top of tip, and do another pull request. That may make it easier on you.
-- Steve
Quoted 8 lines · Steven Rostedt
Quoted 7 lines · H. Peter Anvin
Quoted 6 lines · Steven Rostedt
Peter,
I just realized that these two patches contained a Cc to you, but the cover letter did not Cc you. Probably confused you in what to pull.
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
Sorry about that.
Joy. Let me figure out the remaining patches and pull them in.
Do you want me to rebase on top of tip, and do another pull request. That may make it easier on you.
Sure.
-hpa