Loading arch/x86/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ config X86 select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_ARCH_KGDB if !X86_VOYAGER select HAVE_ARCH_TRACEHOOK Loading arch/x86/kernel/ftrace.c +8 −27 Original line number Diff line number Diff line Loading @@ -82,7 +82,7 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) * are the same as what exists. */ static atomic_t in_nmi = ATOMIC_INIT(0); static atomic_t nmi_running = ATOMIC_INIT(0); static int mod_code_status; /* holds return value of text write */ static int mod_code_write; /* set when NMI should do the write */ static void *mod_code_ip; /* holds the IP to write to */ Loading Loading @@ -115,8 +115,8 @@ static void ftrace_mod_code(void) void ftrace_nmi_enter(void) { atomic_inc(&in_nmi); /* Must have in_nmi seen before reading write flag */ atomic_inc(&nmi_running); /* Must have nmi_running seen before reading write flag */ smp_mb(); if (mod_code_write) { ftrace_mod_code(); Loading @@ -126,19 +126,19 @@ void ftrace_nmi_enter(void) void ftrace_nmi_exit(void) { /* Finish all executions before clearing in_nmi */ /* Finish all executions before clearing nmi_running */ smp_wmb(); atomic_dec(&in_nmi); atomic_dec(&nmi_running); } static void wait_for_nmi(void) { if (!atomic_read(&in_nmi)) if (!atomic_read(&nmi_running)) return; do { cpu_relax(); } while(atomic_read(&in_nmi)); } while (atomic_read(&nmi_running)); nmi_wait_count++; } Loading Loading @@ -367,25 +367,6 @@ int ftrace_disable_ftrace_graph_caller(void) return ftrace_mod_jmp(ip, old_offset, new_offset); } #else /* CONFIG_DYNAMIC_FTRACE */ /* * These functions are picked from those used on * this page for dynamic ftrace. They have been * simplified to ignore all traces in NMI context. */ static atomic_t in_nmi; void ftrace_nmi_enter(void) { atomic_inc(&in_nmi); } void ftrace_nmi_exit(void) { atomic_dec(&in_nmi); } #endif /* !CONFIG_DYNAMIC_FTRACE */ /* Add a function return address to the trace stack on thread info.*/ Loading Loading @@ -475,7 +456,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) &return_to_handler; /* Nmi's are currently unsupported */ if (unlikely(atomic_read(&in_nmi))) if (unlikely(in_nmi())) return; if (unlikely(atomic_read(¤t->tracing_graph_pause))) Loading include/linux/ftrace.h +1 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,7 @@ static inline int ftrace_disable_ftrace_graph_caller(void) { return 0; } #endif /** * ftrace_make_nop - convert code into top * ftrace_make_nop - convert code into nop * @mod: module structure if called by module load initialization * @rec: the mcount call site record * @addr: the address that the call site should be calling Loading include/linux/ftrace_irq.h +1 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ #define _LINUX_FTRACE_IRQ_H #if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_FUNCTION_GRAPH_TRACER) #ifdef CONFIG_FTRACE_NMI_ENTER extern void ftrace_nmi_enter(void); extern void ftrace_nmi_exit(void); #else Loading include/linux/hardirq.h +15 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,12 @@ #error PREEMPT_ACTIVE is too low! #endif #define NMI_OFFSET (PREEMPT_ACTIVE << 1) #if NMI_OFFSET >= 0x80000000 #error PREEMPT_ACTIVE too high! #endif #define hardirq_count() (preempt_count() & HARDIRQ_MASK) #define softirq_count() (preempt_count() & SOFTIRQ_MASK) #define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK)) Loading @@ -73,6 +79,11 @@ #define in_softirq() (softirq_count()) #define in_interrupt() (irq_count()) /* * Are we in NMI context? */ #define in_nmi() (preempt_count() & NMI_OFFSET) #if defined(CONFIG_PREEMPT) # define PREEMPT_INATOMIC_BASE kernel_locked() # define PREEMPT_CHECK_OFFSET 1 Loading Loading @@ -167,6 +178,8 @@ extern void irq_exit(void); #define nmi_enter() \ do { \ ftrace_nmi_enter(); \ BUG_ON(in_nmi()); \ add_preempt_count(NMI_OFFSET); \ lockdep_off(); \ rcu_nmi_enter(); \ __irq_enter(); \ Loading @@ -177,6 +190,8 @@ extern void irq_exit(void); __irq_exit(); \ rcu_nmi_exit(); \ lockdep_on(); \ BUG_ON(!in_nmi()); \ sub_preempt_count(NMI_OFFSET); \ ftrace_nmi_exit(); \ } while (0) Loading Loading
arch/x86/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ config X86 select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_ARCH_KGDB if !X86_VOYAGER select HAVE_ARCH_TRACEHOOK Loading
arch/x86/kernel/ftrace.c +8 −27 Original line number Diff line number Diff line Loading @@ -82,7 +82,7 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) * are the same as what exists. */ static atomic_t in_nmi = ATOMIC_INIT(0); static atomic_t nmi_running = ATOMIC_INIT(0); static int mod_code_status; /* holds return value of text write */ static int mod_code_write; /* set when NMI should do the write */ static void *mod_code_ip; /* holds the IP to write to */ Loading Loading @@ -115,8 +115,8 @@ static void ftrace_mod_code(void) void ftrace_nmi_enter(void) { atomic_inc(&in_nmi); /* Must have in_nmi seen before reading write flag */ atomic_inc(&nmi_running); /* Must have nmi_running seen before reading write flag */ smp_mb(); if (mod_code_write) { ftrace_mod_code(); Loading @@ -126,19 +126,19 @@ void ftrace_nmi_enter(void) void ftrace_nmi_exit(void) { /* Finish all executions before clearing in_nmi */ /* Finish all executions before clearing nmi_running */ smp_wmb(); atomic_dec(&in_nmi); atomic_dec(&nmi_running); } static void wait_for_nmi(void) { if (!atomic_read(&in_nmi)) if (!atomic_read(&nmi_running)) return; do { cpu_relax(); } while(atomic_read(&in_nmi)); } while (atomic_read(&nmi_running)); nmi_wait_count++; } Loading Loading @@ -367,25 +367,6 @@ int ftrace_disable_ftrace_graph_caller(void) return ftrace_mod_jmp(ip, old_offset, new_offset); } #else /* CONFIG_DYNAMIC_FTRACE */ /* * These functions are picked from those used on * this page for dynamic ftrace. They have been * simplified to ignore all traces in NMI context. */ static atomic_t in_nmi; void ftrace_nmi_enter(void) { atomic_inc(&in_nmi); } void ftrace_nmi_exit(void) { atomic_dec(&in_nmi); } #endif /* !CONFIG_DYNAMIC_FTRACE */ /* Add a function return address to the trace stack on thread info.*/ Loading Loading @@ -475,7 +456,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) &return_to_handler; /* Nmi's are currently unsupported */ if (unlikely(atomic_read(&in_nmi))) if (unlikely(in_nmi())) return; if (unlikely(atomic_read(¤t->tracing_graph_pause))) Loading
include/linux/ftrace.h +1 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,7 @@ static inline int ftrace_disable_ftrace_graph_caller(void) { return 0; } #endif /** * ftrace_make_nop - convert code into top * ftrace_make_nop - convert code into nop * @mod: module structure if called by module load initialization * @rec: the mcount call site record * @addr: the address that the call site should be calling Loading
include/linux/ftrace_irq.h +1 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ #define _LINUX_FTRACE_IRQ_H #if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_FUNCTION_GRAPH_TRACER) #ifdef CONFIG_FTRACE_NMI_ENTER extern void ftrace_nmi_enter(void); extern void ftrace_nmi_exit(void); #else Loading
include/linux/hardirq.h +15 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,12 @@ #error PREEMPT_ACTIVE is too low! #endif #define NMI_OFFSET (PREEMPT_ACTIVE << 1) #if NMI_OFFSET >= 0x80000000 #error PREEMPT_ACTIVE too high! #endif #define hardirq_count() (preempt_count() & HARDIRQ_MASK) #define softirq_count() (preempt_count() & SOFTIRQ_MASK) #define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK)) Loading @@ -73,6 +79,11 @@ #define in_softirq() (softirq_count()) #define in_interrupt() (irq_count()) /* * Are we in NMI context? */ #define in_nmi() (preempt_count() & NMI_OFFSET) #if defined(CONFIG_PREEMPT) # define PREEMPT_INATOMIC_BASE kernel_locked() # define PREEMPT_CHECK_OFFSET 1 Loading Loading @@ -167,6 +178,8 @@ extern void irq_exit(void); #define nmi_enter() \ do { \ ftrace_nmi_enter(); \ BUG_ON(in_nmi()); \ add_preempt_count(NMI_OFFSET); \ lockdep_off(); \ rcu_nmi_enter(); \ __irq_enter(); \ Loading @@ -177,6 +190,8 @@ extern void irq_exit(void); __irq_exit(); \ rcu_nmi_exit(); \ lockdep_on(); \ BUG_ON(!in_nmi()); \ sub_preempt_count(NMI_OFFSET); \ ftrace_nmi_exit(); \ } while (0) Loading