* [PATCH 1/2] ftrace: nmi safe code modification
2008-10-30 20:08 [PATCH 0/2] ftrace: handle NMIs safely Steven Rostedt
@ 2008-10-30 20:08 ` Steven Rostedt
2008-10-30 20:32 ` Andrew Morton
2008-10-30 20:08 ` [PATCH 2/2] ftrace: nmi update statistics Steven Rostedt
2008-10-30 20:34 ` [PATCH 0/2] ftrace: handle NMIs safely Ingo Molnar
2 siblings, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2008-10-30 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: Ingo Molnar, Thomas Gleixner, Peter Zijlstra, Andrew Morton,
Linus Torvalds, Steven Rostedt
[-- Attachment #1: ftrace-nmi-safety.patch --]
[-- Type: text/plain, Size: 9653 bytes --]
Modifying code is something that needs special care. On SMP boxes,
if code that is being modified is also being executed on another CPU,
that CPU will have undefined results.
The dynamic ftrace uses kstop_machine to make the system act like a
uniprocessor system. But this does not address NMIs, that can still
run on other CPUs.
One approach to handle this is to make all code that are used by NMIs
not be traced. But NMIs can call notifiers that spread throughout the
kernel and this will be very hard to maintain, and the chance of missing
a function is very high.
The approach that this patch takes is to have the NMIs modify the code
if the modification is taking place. The way this works is that just
writing to code executing on another CPU is not harmful if what is
written is the same as what exists.
Two buffers are used: an IP buffer and a "code" buffer.
The steps that the patcher takes are:
1) Put in the instruction pointer into the IP buffer
and the new code into the "code" buffer.
2) Set a flag that says we are modifying code
3) Wait for any running NMIs to finish.
4) Write the code
5) clear the flag.
6) Wait for any running NMIs to finish.
If an NMI is executed, it will also write the pending code.
Multiple writes are OK, because what is being written is the same.
Then the patcher must wait for all running NMIs to finish before
going to the next line that must be patched.
This is basically the RCU approach to code modification.
Thanks to Ingo Molnar for suggesting the idea, and to Arjan van de Ven
for his guidence on what is safe and what is not.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
arch/arm/include/asm/ftrace.h | 5 +
arch/powerpc/include/asm/ftrace.h | 5 +
arch/sh/include/asm/ftrace.h | 5 +
arch/sparc/include/asm/ftrace.h | 5 +
arch/x86/include/asm/ftrace.h | 15 +++++
arch/x86/kernel/ftrace.c | 107 +++++++++++++++++++++++++++++++++++++-
include/linux/hardirq.h | 15 ++++-
7 files changed, 154 insertions(+), 3 deletions(-)
Index: linux-tip.git/arch/arm/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/arm/include/asm/ftrace.h 2008-10-30 10:24:09.000000000 -0400
+++ linux-tip.git/arch/arm/include/asm/ftrace.h 2008-10-30 10:27:09.000000000 -0400
@@ -1,6 +1,11 @@
#ifndef _ASM_ARM_FTRACE
#define _ASM_ARM_FTRACE
+#ifndef __ASSEMBLY__
+#define ftrace_nmi_enter() do { } while (0)
+#define ftrace_nmi_exit() do { } while (0)
+#endif
+
#ifdef CONFIG_FUNCTION_TRACER
#define MCOUNT_ADDR ((long)(mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Index: linux-tip.git/arch/powerpc/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/powerpc/include/asm/ftrace.h 2008-10-30 10:24:09.000000000 -0400
+++ linux-tip.git/arch/powerpc/include/asm/ftrace.h 2008-10-30 10:27:09.000000000 -0400
@@ -1,6 +1,11 @@
#ifndef _ASM_POWERPC_FTRACE
#define _ASM_POWERPC_FTRACE
+#ifndef __ASSEMBLY__
+#define ftrace_nmi_enter() do { } while (0)
+#define ftrace_nmi_exit() do { } while (0)
+#endif
+
#ifdef CONFIG_FUNCTION_TRACER
#define MCOUNT_ADDR ((long)(_mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Index: linux-tip.git/arch/sh/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/sh/include/asm/ftrace.h 2008-10-30 10:24:09.000000000 -0400
+++ linux-tip.git/arch/sh/include/asm/ftrace.h 2008-10-30 10:27:09.000000000 -0400
@@ -2,6 +2,11 @@
#define __ASM_SH_FTRACE_H
#ifndef __ASSEMBLY__
+#define ftrace_nmi_enter() do { } while (0)
+#define ftrace_nmi_exit() do { } while (0)
+#endif
+
+#ifndef __ASSEMBLY__
extern void mcount(void);
#endif
Index: linux-tip.git/arch/sparc/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/sparc/include/asm/ftrace.h 2008-10-30 10:24:09.000000000 -0400
+++ linux-tip.git/arch/sparc/include/asm/ftrace.h 2008-10-30 10:27:09.000000000 -0400
@@ -1,6 +1,11 @@
#ifndef _ASM_SPARC64_FTRACE
#define _ASM_SPARC64_FTRACE
+#ifndef __ASSEMBLY__
+#define ftrace_nmi_enter() do { } while (0)
+#define ftrace_nmi_exit() do { } while (0)
+#endif
+
#ifdef CONFIG_MCOUNT
#define MCOUNT_ADDR ((long)(_mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Index: linux-tip.git/arch/x86/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/x86/include/asm/ftrace.h 2008-10-30 10:26:28.000000000 -0400
+++ linux-tip.git/arch/x86/include/asm/ftrace.h 2008-10-30 13:16:22.000000000 -0400
@@ -17,6 +17,21 @@ static inline unsigned long ftrace_call_
*/
return addr - 1;
}
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+extern void ftrace_nmi_enter(void);
+extern void ftrace_nmi_exit(void);
+#else
+#define ftrace_nmi_enter() do { } while (0)
+#define ftrace_nmi_exit() do { } while (0)
+#endif
+#endif
+
+#else /* CONFIG_FUNCTION_TRACER */
+
+#ifndef __ASSEMBLY__
+#define ftrace_nmi_enter() do { } while (0)
+#define ftrace_nmi_exit() do { } while (0)
#endif
#endif /* CONFIG_FUNCTION_TRACER */
Index: linux-tip.git/arch/x86/kernel/ftrace.c
===================================================================
--- linux-tip.git.orig/arch/x86/kernel/ftrace.c 2008-10-30 10:27:07.000000000 -0400
+++ linux-tip.git/arch/x86/kernel/ftrace.c 2008-10-30 16:06:42.000000000 -0400
@@ -56,6 +56,111 @@ unsigned char *ftrace_call_replace(unsig
return calc.code;
}
+/*
+ * Modifying code must take extra care. On an SMP machine, if
+ * the code being modified is also being executed on another CPU
+ * that CPU will have undefined results and possibly take a GPF.
+ * We use kstop_machine to stop other CPUS from exectuing code.
+ * But this does not stop NMIs from happening. We still need
+ * to protect against that. We separate out the modification of
+ * the code to take care of this.
+ *
+ * Two buffers are added: An IP buffer and a "code" buffer.
+ *
+ * 1) Put in the instruction pointer into the IP buffer
+ * and the new code into the "code" buffer.
+ * 2) Set a flag that says we are modifying code
+ * 3) Wait for any running NMIs to finish.
+ * 4) Write the code
+ * 5) clear the flag.
+ * 6) Wait for any running NMIs to finish.
+ *
+ * If an NMI is executed, the first thing it does is to call
+ * "ftrace_nmi_enter". This will check if the flag is set to write
+ * and if it is, it will write what is in the IP and "code" buffers.
+ *
+ * The trick is, it does not matter if everyone is writing the same
+ * content to the code location. Also, if a CPU is executing code
+ * it is OK to write to that code location if the contents being written
+ * are the same as what exists.
+ */
+
+static atomic_t in_nmi;
+static int mod_code_status;
+static int mod_code_write;
+static void *mod_code_ip;
+static void *mod_code_newcode;
+
+static void ftrace_mod_code(void)
+{
+ /*
+ * Yes, more than one CPU process can be writing to mod_code_status.
+ * (and the code itself)
+ * But if one were to fail, then they all should, and if one were
+ * to succeed, then they all should.
+ */
+ mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
+ MCOUNT_INSN_SIZE);
+
+}
+
+void ftrace_nmi_enter(void)
+{
+ atomic_inc(&in_nmi);
+ /* Must have in_nmi seen before reading write flag */
+ smp_mb();
+ if (mod_code_write)
+ ftrace_mod_code();
+}
+
+void ftrace_nmi_exit(void)
+{
+ /* Finish all executions before clearing in_nmi */
+ smp_wmb();
+ atomic_dec(&in_nmi);
+}
+
+static void wait_for_nmi(void)
+{
+ while (atomic_read(&in_nmi))
+ cpu_relax();
+}
+
+static int
+do_ftrace_mod_code(unsigned long ip, void *new_code)
+{
+ mod_code_ip = (void *)ip;
+ mod_code_newcode = new_code;
+
+ /* The buffers need to be visible before we let NMIs write them */
+ smp_wmb();
+
+ mod_code_write = 1;
+
+ /* Make sure write bit is visible before we wait on NMIs */
+ smp_mb();
+
+ wait_for_nmi();
+
+ /* Make sure all running NMIs have finished before we write the code */
+ smp_mb();
+
+ ftrace_mod_code();
+
+ /* Make sure the write happens before clearing the bit */
+ smp_wmb();
+
+ mod_code_write = 0;
+
+ /* make sure NMIs see the cleared bit */
+ smp_mb();
+
+ wait_for_nmi();
+
+ return mod_code_status;
+}
+
+
int
ftrace_modify_code(unsigned long ip, unsigned char *old_code,
unsigned char *new_code)
@@ -81,7 +186,7 @@ ftrace_modify_code(unsigned long ip, uns
return -EINVAL;
/* replace the text with the new text */
- if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE))
+ if (do_ftrace_mod_code(ip, new_code))
return -EPERM;
sync_core();
Index: linux-tip.git/include/linux/hardirq.h
===================================================================
--- linux-tip.git.orig/include/linux/hardirq.h 2008-10-30 10:27:07.000000000 -0400
+++ linux-tip.git/include/linux/hardirq.h 2008-10-30 10:27:09.000000000 -0400
@@ -5,6 +5,7 @@
#include <linux/smp_lock.h>
#include <linux/lockdep.h>
#include <asm/hardirq.h>
+#include <asm/ftrace.h>
#include <asm/system.h>
/*
@@ -161,7 +162,17 @@ extern void irq_enter(void);
*/
extern void irq_exit(void);
-#define nmi_enter() do { lockdep_off(); __irq_enter(); } while (0)
-#define nmi_exit() do { __irq_exit(); lockdep_on(); } while (0)
+#define nmi_enter() \
+ do { \
+ ftrace_nmi_enter(); \
+ lockdep_off(); \
+ __irq_enter(); \
+ } while (0)
+#define nmi_exit() \
+ do { \
+ __irq_exit(); \
+ lockdep_on(); \
+ ftrace_nmi_exit(); \
+ } while (0)
#endif /* LINUX_HARDIRQ_H */
--
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/2] ftrace: nmi safe code modification
2008-10-30 20:08 ` [PATCH 1/2] ftrace: nmi safe code modification Steven Rostedt
@ 2008-10-30 20:32 ` Andrew Morton
2008-10-30 20:38 ` Ingo Molnar
2008-10-30 20:58 ` Steven Rostedt
0 siblings, 2 replies; 18+ messages in thread
From: Andrew Morton @ 2008-10-30 20:32 UTC (permalink / raw)
To: Steven Rostedt; +Cc: linux-kernel, mingo, tglx, peterz, torvalds, srostedt
On Thu, 30 Oct 2008 16:08:32 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> Modifying code is something that needs special care. On SMP boxes,
> if code that is being modified is also being executed on another CPU,
> that CPU will have undefined results.
>
> The dynamic ftrace uses kstop_machine to make the system act like a
> uniprocessor system. But this does not address NMIs, that can still
> run on other CPUs.
>
> One approach to handle this is to make all code that are used by NMIs
> not be traced. But NMIs can call notifiers that spread throughout the
> kernel and this will be very hard to maintain, and the chance of missing
> a function is very high.
>
> The approach that this patch takes is to have the NMIs modify the code
> if the modification is taking place. The way this works is that just
> writing to code executing on another CPU is not harmful if what is
> written is the same as what exists.
Seems like it'll work.
> +#ifndef __ASSEMBLY__
> +#define ftrace_nmi_enter() do { } while (0)
> +#define ftrace_nmi_exit() do { } while (0)
> +#endif
> ...
> +#ifndef __ASSEMBLY__
> +#define ftrace_nmi_enter() do { } while (0)
> +#define ftrace_nmi_exit() do { } while (0)
> +#endif
These could all be written in C. If there's a reson to write them in
cpp then the `#ifndef __ASSEMBLY__' isn't really needed.
> +#endif
> +
> #ifdef CONFIG_MCOUNT
> #define MCOUNT_ADDR ((long)(_mcount))
> #define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
> Index: linux-tip.git/arch/x86/include/asm/ftrace.h
> ===================================================================
> --- linux-tip.git.orig/arch/x86/include/asm/ftrace.h 2008-10-30 10:26:28.000000000 -0400
> +++ linux-tip.git/arch/x86/include/asm/ftrace.h 2008-10-30 13:16:22.000000000 -0400
> @@ -17,6 +17,21 @@ static inline unsigned long ftrace_call_
> */
> return addr - 1;
> }
> +
> +#ifdef CONFIG_DYNAMIC_FTRACE
> +extern void ftrace_nmi_enter(void);
> +extern void ftrace_nmi_exit(void);
> +#else
> +#define ftrace_nmi_enter() do { } while (0)
> +#define ftrace_nmi_exit() do { } while (0)
Either this one misses the `#ifndef __ASSEMBLY__' ...
> +#endif
> +#endif
> +
> +#else /* CONFIG_FUNCTION_TRACER */
> +
> +#ifndef __ASSEMBLY__
> +#define ftrace_nmi_enter() do { } while (0)
> +#define ftrace_nmi_exit() do { } while (0)
> #endif
or this one didn't need it.
>
> #endif /* CONFIG_FUNCTION_TRACER */
> Index: linux-tip.git/arch/x86/kernel/ftrace.c
> ===================================================================
> --- linux-tip.git.orig/arch/x86/kernel/ftrace.c 2008-10-30 10:27:07.000000000 -0400
> +++ linux-tip.git/arch/x86/kernel/ftrace.c 2008-10-30 16:06:42.000000000 -0400
> @@ -56,6 +56,111 @@ unsigned char *ftrace_call_replace(unsig
> return calc.code;
> }
>
> +/*
> + * Modifying code must take extra care. On an SMP machine, if
> + * the code being modified is also being executed on another CPU
> + * that CPU will have undefined results and possibly take a GPF.
> + * We use kstop_machine to stop other CPUS from exectuing code.
> + * But this does not stop NMIs from happening. We still need
> + * to protect against that. We separate out the modification of
> + * the code to take care of this.
> + *
> + * Two buffers are added: An IP buffer and a "code" buffer.
> + *
> + * 1) Put in the instruction pointer into the IP buffer
s/in //
> + * and the new code into the "code" buffer.
> + * 2) Set a flag that says we are modifying code
> + * 3) Wait for any running NMIs to finish.
> + * 4) Write the code
> + * 5) clear the flag.
> + * 6) Wait for any running NMIs to finish.
> + *
> + * If an NMI is executed, the first thing it does is to call
> + * "ftrace_nmi_enter". This will check if the flag is set to write
> + * and if it is, it will write what is in the IP and "code" buffers.
> + *
> + * The trick is, it does not matter if everyone is writing the same
> + * content to the code location. Also, if a CPU is executing code
> + * it is OK to write to that code location if the contents being written
> + * are the same as what exists.
> + */
> +
> +static atomic_t in_nmi;
Should formally have an ATONIC_INIT. If we're going to formalise the
"all zeroes is OK for atomic_t's" rule then we can leave this as-is.
> +static int mod_code_status;
> +static int mod_code_write;
> +static void *mod_code_ip;
> +static void *mod_code_newcode;
Some comments decribing the global state would be nice.
> +static void ftrace_mod_code(void)
> +{
> + /*
> + * Yes, more than one CPU process can be writing to mod_code_status.
> + * (and the code itself)
> + * But if one were to fail, then they all should, and if one were
> + * to succeed, then they all should.
> + */
> + mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
> + MCOUNT_INSN_SIZE);
> +
> +}
> +
> +void ftrace_nmi_enter(void)
> +{
> + atomic_inc(&in_nmi);
> + /* Must have in_nmi seen before reading write flag */
> + smp_mb();
> + if (mod_code_write)
> + ftrace_mod_code();
> +}
> +
> +void ftrace_nmi_exit(void)
> +{
> + /* Finish all executions before clearing in_nmi */
> + smp_wmb();
> + atomic_dec(&in_nmi);
> +}
> +
> +static void wait_for_nmi(void)
> +{
> + while (atomic_read(&in_nmi))
> + cpu_relax();
> +}
> +
> +static int
> +do_ftrace_mod_code(unsigned long ip, void *new_code)
> +{
> + mod_code_ip = (void *)ip;
> + mod_code_newcode = new_code;
> +
> + /* The buffers need to be visible before we let NMIs write them */
> + smp_wmb();
> +
> + mod_code_write = 1;
> +
> + /* Make sure write bit is visible before we wait on NMIs */
> + smp_mb();
> +
> + wait_for_nmi();
> +
> + /* Make sure all running NMIs have finished before we write the code */
> + smp_mb();
> +
> + ftrace_mod_code();
> +
> + /* Make sure the write happens before clearing the bit */
> + smp_wmb();
> +
> + mod_code_write = 0;
> +
> + /* make sure NMIs see the cleared bit */
> + smp_mb();
> +
> + wait_for_nmi();
> +
> + return mod_code_status;
> +}
I guess the weakness here is that the code will only allow a single
contiguous hunk of text to be modified. One could envisage situations
where two or more separate areas of memory need to be modified
atomically/together.
I guess we can cross that bridge when we fall off it.
> --- linux-tip.git.orig/include/linux/hardirq.h 2008-10-30 10:27:07.000000000 -0400
> +++ linux-tip.git/include/linux/hardirq.h 2008-10-30 10:27:09.000000000 -0400
> @@ -5,6 +5,7 @@
> #include <linux/smp_lock.h>
> #include <linux/lockdep.h>
> #include <asm/hardirq.h>
> +#include <asm/ftrace.h>
> #include <asm/system.h>
>
> /*
> @@ -161,7 +162,17 @@ extern void irq_enter(void);
> */
> extern void irq_exit(void);
>
> -#define nmi_enter() do { lockdep_off(); __irq_enter(); } while (0)
> -#define nmi_exit() do { __irq_exit(); lockdep_on(); } while (0)
> +#define nmi_enter() \
> + do { \
> + ftrace_nmi_enter(); \
> + lockdep_off(); \
> + __irq_enter(); \
> + } while (0)
> +#define nmi_exit() \
> + do { \
> + __irq_exit(); \
> + lockdep_on(); \
> + ftrace_nmi_exit(); \
> + } while (0)
>
<wonders if these needed to be written in cpp>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/2] ftrace: nmi safe code modification
2008-10-30 20:32 ` Andrew Morton
@ 2008-10-30 20:38 ` Ingo Molnar
2008-10-30 20:58 ` Steven Rostedt
1 sibling, 0 replies; 18+ messages in thread
From: Ingo Molnar @ 2008-10-30 20:38 UTC (permalink / raw)
To: Andrew Morton
Cc: Steven Rostedt, linux-kernel, tglx, peterz, torvalds, srostedt
* Andrew Morton <akpm@linux-foundation.org> wrote:
> > + /* make sure NMIs see the cleared bit */
> > + smp_mb();
> > +
> > + wait_for_nmi();
> > +
> > + return mod_code_status;
> > +}
>
> I guess the weakness here is that the code will only allow a single
> contiguous hunk of text to be modified. One could envisage
> situations where two or more separate areas of memory need to be
> modified atomically/together.
>
> I guess we can cross that bridge when we fall off it.
yeah - the whole 'transaction' concept can be extended easily, in just
one place.
Not that i think that it would really be useful to go beyond the
current (target,len) abstraction - the less complex code patching is
done, the better.
Ingo
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/2] ftrace: nmi safe code modification
2008-10-30 20:32 ` Andrew Morton
2008-10-30 20:38 ` Ingo Molnar
@ 2008-10-30 20:58 ` Steven Rostedt
2008-10-30 21:10 ` Andrew Morton
1 sibling, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2008-10-30 20:58 UTC (permalink / raw)
To: Andrew Morton
Cc: LKML, Ingo Molnar, Thomas Gleixner, Peter Zijlstra,
Linus Torvalds, srostedt
On Thu, 30 Oct 2008, Andrew Morton wrote:
>
> > +#ifndef __ASSEMBLY__
> > +#define ftrace_nmi_enter() do { } while (0)
> > +#define ftrace_nmi_exit() do { } while (0)
> > +#endif
> > ...
> > +#ifndef __ASSEMBLY__
> > +#define ftrace_nmi_enter() do { } while (0)
> > +#define ftrace_nmi_exit() do { } while (0)
> > +#endif
>
> These could all be written in C. If there's a reson to write them in
> cpp then the `#ifndef __ASSEMBLY__' isn't really needed.
I could do the C macro, and you are right, I did not need the __ASSEMBLY__
part. I guess that was me just being over-protective :-/
Which would you prefer? Changing to C or removing the __ASSEMBLY__?
>
> > +#endif
> > +
> > #ifdef CONFIG_MCOUNT
> > #define MCOUNT_ADDR ((long)(_mcount))
> > #define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
> > Index: linux-tip.git/arch/x86/include/asm/ftrace.h
> > ===================================================================
> > --- linux-tip.git.orig/arch/x86/include/asm/ftrace.h 2008-10-30 10:26:28.000000000 -0400
> > +++ linux-tip.git/arch/x86/include/asm/ftrace.h 2008-10-30 13:16:22.000000000 -0400
> > @@ -17,6 +17,21 @@ static inline unsigned long ftrace_call_
> > */
> > return addr - 1;
> > }
> > +
> > +#ifdef CONFIG_DYNAMIC_FTRACE
> > +extern void ftrace_nmi_enter(void);
> > +extern void ftrace_nmi_exit(void);
> > +#else
> > +#define ftrace_nmi_enter() do { } while (0)
> > +#define ftrace_nmi_exit() do { } while (0)
>
> Either this one misses the `#ifndef __ASSEMBLY__' ...
>
> > +#endif
> > +#endif
> > +
> > +#else /* CONFIG_FUNCTION_TRACER */
> > +
> > +#ifndef __ASSEMBLY__
> > +#define ftrace_nmi_enter() do { } while (0)
> > +#define ftrace_nmi_exit() do { } while (0)
> > #endif
>
> or this one didn't need it.
Wrong in both cases (If we ignore the fact that MACROS do not need the
__ASSEMBLY__) ;-)
Notice the two #endif in a row? Here's the full code:
#ifdef CONFIG_FUNCTION_TRACER
#define MCOUNT_ADDR ((long)(mcount))
#define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */
#ifndef __ASSEMBLY__
extern void mcount(void);
static inline unsigned long ftrace_call_adjust(unsigned long addr)
{
/*
* call mcount is "e8 <4 byte offset>"
* The addr points to the 4 byte offset and the caller of this
* function wants the pointer to e8. Simply subtract one.
*/
return addr - 1;
}
#ifdef CONFIG_DYNAMIC_FTRACE
extern void ftrace_nmi_enter(void);
extern void ftrace_nmi_exit(void);
#else
#define ftrace_nmi_enter() do { } while (0)
#define ftrace_nmi_exit() do { } while (0)
#endif
#endif
#else /* CONFIG_FUNCTION_TRACER */
#ifndef __ASSEMBLY__
#define ftrace_nmi_enter() do { } while (0)
#define ftrace_nmi_exit() do { } while (0)
#endif
#endif /* CONFIG_FUNCTION_TRACER */
I guess I could add a comment /* __ASSEMBLY__ */ on that second endif.
>
> >
> > #endif /* CONFIG_FUNCTION_TRACER */
> > Index: linux-tip.git/arch/x86/kernel/ftrace.c
> > ===================================================================
> > --- linux-tip.git.orig/arch/x86/kernel/ftrace.c 2008-10-30 10:27:07.000000000 -0400
> > +++ linux-tip.git/arch/x86/kernel/ftrace.c 2008-10-30 16:06:42.000000000 -0400
> > @@ -56,6 +56,111 @@ unsigned char *ftrace_call_replace(unsig
> > return calc.code;
> > }
> >
> > +/*
> > + * Modifying code must take extra care. On an SMP machine, if
> > + * the code being modified is also being executed on another CPU
> > + * that CPU will have undefined results and possibly take a GPF.
> > + * We use kstop_machine to stop other CPUS from exectuing code.
> > + * But this does not stop NMIs from happening. We still need
> > + * to protect against that. We separate out the modification of
> > + * the code to take care of this.
> > + *
> > + * Two buffers are added: An IP buffer and a "code" buffer.
> > + *
> > + * 1) Put in the instruction pointer into the IP buffer
>
> s/in //
OK.
>
> > + * and the new code into the "code" buffer.
> > + * 2) Set a flag that says we are modifying code
> > + * 3) Wait for any running NMIs to finish.
> > + * 4) Write the code
> > + * 5) clear the flag.
> > + * 6) Wait for any running NMIs to finish.
> > + *
> > + * If an NMI is executed, the first thing it does is to call
> > + * "ftrace_nmi_enter". This will check if the flag is set to write
> > + * and if it is, it will write what is in the IP and "code" buffers.
> > + *
> > + * The trick is, it does not matter if everyone is writing the same
> > + * content to the code location. Also, if a CPU is executing code
> > + * it is OK to write to that code location if the contents being written
> > + * are the same as what exists.
> > + */
> > +
> > +static atomic_t in_nmi;
>
> Should formally have an ATONIC_INIT. If we're going to formalise the
> "all zeroes is OK for atomic_t's" rule then we can leave this as-is.
This is a bad habit of mine :-/ I would like to formalize the "all zeroes
is OK for atomic_t's" rule, but I'm not in that position to do so.
>
> > +static int mod_code_status;
> > +static int mod_code_write;
> > +static void *mod_code_ip;
> > +static void *mod_code_newcode;
>
> Some comments decribing the global state would be nice.
Hmm, I thought I commented enough about this in the above comments. But
I guess it would not hurt to add more.
>
> > +static void ftrace_mod_code(void)
> > +{
> > + /*
> > + * Yes, more than one CPU process can be writing to mod_code_status.
> > + * (and the code itself)
> > + * But if one were to fail, then they all should, and if one were
> > + * to succeed, then they all should.
> > + */
> > + mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode,
> > + MCOUNT_INSN_SIZE);
> > +
> > +}
> > +
> > +void ftrace_nmi_enter(void)
> > +{
> > + atomic_inc(&in_nmi);
> > + /* Must have in_nmi seen before reading write flag */
> > + smp_mb();
> > + if (mod_code_write)
> > + ftrace_mod_code();
> > +}
> > +
> > +void ftrace_nmi_exit(void)
> > +{
> > + /* Finish all executions before clearing in_nmi */
> > + smp_wmb();
> > + atomic_dec(&in_nmi);
> > +}
> > +
> > +static void wait_for_nmi(void)
> > +{
> > + while (atomic_read(&in_nmi))
> > + cpu_relax();
> > +}
> > +
> > +static int
> > +do_ftrace_mod_code(unsigned long ip, void *new_code)
> > +{
> > + mod_code_ip = (void *)ip;
> > + mod_code_newcode = new_code;
> > +
> > + /* The buffers need to be visible before we let NMIs write them */
> > + smp_wmb();
> > +
> > + mod_code_write = 1;
> > +
> > + /* Make sure write bit is visible before we wait on NMIs */
> > + smp_mb();
> > +
> > + wait_for_nmi();
> > +
> > + /* Make sure all running NMIs have finished before we write the code */
> > + smp_mb();
> > +
> > + ftrace_mod_code();
> > +
> > + /* Make sure the write happens before clearing the bit */
> > + smp_wmb();
> > +
> > + mod_code_write = 0;
> > +
> > + /* make sure NMIs see the cleared bit */
> > + smp_mb();
> > +
> > + wait_for_nmi();
> > +
> > + return mod_code_status;
> > +}
>
> I guess the weakness here is that the code will only allow a single
> contiguous hunk of text to be modified. One could envisage situations
> where two or more separate areas of memory need to be modified
> atomically/together.
>
> I guess we can cross that bridge when we fall off it.
Well the current code (luckily) does not need that. As Ingo has stated,
the simpler this code is the better. There's just too much that can
go wrong if this code is defective.
>
> > --- linux-tip.git.orig/include/linux/hardirq.h 2008-10-30 10:27:07.000000000 -0400
> > +++ linux-tip.git/include/linux/hardirq.h 2008-10-30 10:27:09.000000000 -0400
> > @@ -5,6 +5,7 @@
> > #include <linux/smp_lock.h>
> > #include <linux/lockdep.h>
> > #include <asm/hardirq.h>
> > +#include <asm/ftrace.h>
> > #include <asm/system.h>
> >
> > /*
> > @@ -161,7 +162,17 @@ extern void irq_enter(void);
> > */
> > extern void irq_exit(void);
> >
> > -#define nmi_enter() do { lockdep_off(); __irq_enter(); } while (0)
> > -#define nmi_exit() do { __irq_exit(); lockdep_on(); } while (0)
> > +#define nmi_enter() \
> > + do { \
> > + ftrace_nmi_enter(); \
> > + lockdep_off(); \
> > + __irq_enter(); \
> > + } while (0)
> > +#define nmi_exit() \
> > + do { \
> > + __irq_exit(); \
> > + lockdep_on(); \
> > + ftrace_nmi_exit(); \
> > + } while (0)
> >
>
> <wonders if these needed to be written in cpp>
A clean up patch can follow this. I would not do it here, because it
follows the style of the irq_enter and irq_exit macros just above this
code.
I do not see why this could not be converted to a static inline, but
that should be a separate patch that udpates both this and the
irq_enter/exit macros together.
-- Steve
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/2] ftrace: nmi safe code modification
2008-10-30 20:58 ` Steven Rostedt
@ 2008-10-30 21:10 ` Andrew Morton
2008-10-31 4:03 ` [PATCH] ftrace: nmi safe code clean ups Steven Rostedt
0 siblings, 1 reply; 18+ messages in thread
From: Andrew Morton @ 2008-10-30 21:10 UTC (permalink / raw)
To: Steven Rostedt; +Cc: linux-kernel, mingo, tglx, peterz, torvalds, srostedt
On Thu, 30 Oct 2008 16:58:55 -0400 (EDT)
Steven Rostedt <rostedt@goodmis.org> wrote:
> On Thu, 30 Oct 2008, Andrew Morton wrote:
> >
> > > +#ifndef __ASSEMBLY__
> > > +#define ftrace_nmi_enter() do { } while (0)
> > > +#define ftrace_nmi_exit() do { } while (0)
> > > +#endif
> > > ...
> > > +#ifndef __ASSEMBLY__
> > > +#define ftrace_nmi_enter() do { } while (0)
> > > +#define ftrace_nmi_exit() do { } while (0)
> > > +#endif
> >
> > These could all be written in C. If there's a reson to write them in
> > cpp then the `#ifndef __ASSEMBLY__' isn't really needed.
>
> I could do the C macro, and you are right, I did not need the __ASSEMBLY__
> part. I guess that was me just being over-protective :-/
>
> Which would you prefer? Changing to C or removing the __ASSEMBLY__?
>From a general perspective, C is better. Has typechecking, adds a ref
to the arguments which can prevent unused-var warnings, easier to read
and maintain, more likely to be commented, known about by debug info,
doesn't all get clumped into a single line in debug info, easier/safer
to uninline, blah, blah.
Also it seems a bit weird to do
#ifdef SOMETHING
#define foo(...) ...
#else
extern void foo(...);
#endif
Doing it in C has the downside that more things need to be visible at
the definition site, so more includes might be needed. Often fixable
by uninlining.
I dunno. People seem to instinctively reach for a macro without
thinking, because that's how grandpa did it or something.
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH] ftrace: nmi safe code clean ups
2008-10-30 21:10 ` Andrew Morton
@ 2008-10-31 4:03 ` Steven Rostedt
2008-10-31 4:16 ` [PATCH] hardirq.h clean up Steven Rostedt
2008-10-31 9:28 ` [PATCH] ftrace: nmi safe code clean ups Ingo Molnar
0 siblings, 2 replies; 18+ messages in thread
From: Steven Rostedt @ 2008-10-31 4:03 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, mingo, tglx, peterz, torvalds, srostedt
This patch cleans up the NMI safe code for dynamic ftrace as suggested
by Andrew Morton.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
arch/arm/include/asm/ftrace.h | 4 ++--
arch/powerpc/include/asm/ftrace.h | 4 ++--
arch/sh/include/asm/ftrace.h | 4 ++--
arch/sparc/include/asm/ftrace.h | 4 ++--
arch/x86/include/asm/ftrace.h | 10 +++++-----
arch/x86/kernel/ftrace.c | 16 ++++++++--------
include/linux/ftrace.h | 3 +++
kernel/trace/trace.c | 9 ++++-----
8 files changed, 28 insertions(+), 26 deletions(-)
Index: linux-tip.git/arch/arm/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/arm/include/asm/ftrace.h 2008-10-30 10:27:09.000000000 -0400
+++ linux-tip.git/arch/arm/include/asm/ftrace.h 2008-10-30 23:24:18.000000000 -0400
@@ -2,8 +2,8 @@
#define _ASM_ARM_FTRACE
#ifndef __ASSEMBLY__
-#define ftrace_nmi_enter() do { } while (0)
-#define ftrace_nmi_exit() do { } while (0)
+static inline void ftrace_nmi_enter(void) { }
+static inline void ftrace_nmi_exit(void) { }
#endif
#ifdef CONFIG_FUNCTION_TRACER
Index: linux-tip.git/arch/powerpc/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/powerpc/include/asm/ftrace.h 2008-10-30 10:27:09.000000000 -0400
+++ linux-tip.git/arch/powerpc/include/asm/ftrace.h 2008-10-30 23:24:30.000000000 -0400
@@ -2,8 +2,8 @@
#define _ASM_POWERPC_FTRACE
#ifndef __ASSEMBLY__
-#define ftrace_nmi_enter() do { } while (0)
-#define ftrace_nmi_exit() do { } while (0)
+static inline void ftrace_nmi_enter(void) { }
+static inline void ftrace_nmi_exit(void) { }
#endif
#ifdef CONFIG_FUNCTION_TRACER
Index: linux-tip.git/arch/sh/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/sh/include/asm/ftrace.h 2008-10-30 10:27:09.000000000 -0400
+++ linux-tip.git/arch/sh/include/asm/ftrace.h 2008-10-30 23:24:43.000000000 -0400
@@ -2,8 +2,8 @@
#define __ASM_SH_FTRACE_H
#ifndef __ASSEMBLY__
-#define ftrace_nmi_enter() do { } while (0)
-#define ftrace_nmi_exit() do { } while (0)
+static inline void ftrace_nmi_enter(void) { }
+static inline void ftrace_nmi_exit(void) { }
#endif
#ifndef __ASSEMBLY__
Index: linux-tip.git/arch/sparc/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/sparc/include/asm/ftrace.h 2008-10-30 10:27:09.000000000 -0400
+++ linux-tip.git/arch/sparc/include/asm/ftrace.h 2008-10-30 23:24:50.000000000 -0400
@@ -2,8 +2,8 @@
#define _ASM_SPARC64_FTRACE
#ifndef __ASSEMBLY__
-#define ftrace_nmi_enter() do { } while (0)
-#define ftrace_nmi_exit() do { } while (0)
+static inline void ftrace_nmi_enter(void) { }
+static inline void ftrace_nmi_exit(void) { }
#endif
#ifdef CONFIG_MCOUNT
Index: linux-tip.git/arch/x86/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/x86/include/asm/ftrace.h 2008-10-30 13:16:22.000000000 -0400
+++ linux-tip.git/arch/x86/include/asm/ftrace.h 2008-10-30 23:25:26.000000000 -0400
@@ -22,16 +22,16 @@ static inline unsigned long ftrace_call_
extern void ftrace_nmi_enter(void);
extern void ftrace_nmi_exit(void);
#else
-#define ftrace_nmi_enter() do { } while (0)
-#define ftrace_nmi_exit() do { } while (0)
-#endif
+static inline void ftrace_nmi_enter(void) { }
+static inline void ftrace_nmi_exit(void) { }
#endif
+#endif /* __ASSEMBLY__ */
#else /* CONFIG_FUNCTION_TRACER */
#ifndef __ASSEMBLY__
-#define ftrace_nmi_enter() do { } while (0)
-#define ftrace_nmi_exit() do { } while (0)
+static inline void ftrace_nmi_enter(void) { }
+static inline void ftrace_nmi_exit(void) { }
#endif
#endif /* CONFIG_FUNCTION_TRACER */
Index: linux-tip.git/arch/x86/kernel/ftrace.c
===================================================================
--- linux-tip.git.orig/arch/x86/kernel/ftrace.c 2008-10-30 16:07:05.000000000 -0400
+++ linux-tip.git/arch/x86/kernel/ftrace.c 2008-10-30 23:30:19.000000000 -0400
@@ -67,7 +67,7 @@ unsigned char *ftrace_call_replace(unsig
*
* Two buffers are added: An IP buffer and a "code" buffer.
*
- * 1) Put in the instruction pointer into the IP buffer
+ * 1) Put the instruction pointer into the IP buffer
* and the new code into the "code" buffer.
* 2) Set a flag that says we are modifying code
* 3) Wait for any running NMIs to finish.
@@ -85,14 +85,14 @@ unsigned char *ftrace_call_replace(unsig
* are the same as what exists.
*/
-static atomic_t in_nmi;
-static int mod_code_status;
-static int mod_code_write;
-static void *mod_code_ip;
-static void *mod_code_newcode;
+static atomic_t in_nmi = 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 */
+static void *mod_code_newcode; /* holds the text to write to the IP */
-static int nmi_wait_count;
-static atomic_t nmi_update_count;
+static unsigned nmi_wait_count;
+static atomic_t nmi_update_count = ATOMIC_INIT(0);
int ftrace_arch_read_dyn_info(char *buf, int size)
{
Index: linux-tip.git/include/linux/ftrace.h
===================================================================
--- linux-tip.git.orig/include/linux/ftrace.h 2008-10-30 10:27:07.000000000 -0400
+++ linux-tip.git/include/linux/ftrace.h 2008-10-30 23:31:33.000000000 -0400
@@ -74,6 +74,9 @@ extern void ftrace_caller(void);
extern void ftrace_call(void);
extern void mcount_call(void);
+/* May be defined in arch */
+extern int ftrace_arch_read_dyn_info(char *buf, int size);
+
/**
* ftrace_modify_code - modify code segment
* @ip: the address of the code segment
Index: linux-tip.git/kernel/trace/trace.c
===================================================================
--- linux-tip.git.orig/kernel/trace/trace.c 2008-10-30 16:07:05.000000000 -0400
+++ linux-tip.git/kernel/trace/trace.c 2008-10-30 23:33:41.000000000 -0400
@@ -2837,10 +2837,6 @@ static struct file_operations tracing_ma
#ifdef CONFIG_DYNAMIC_FTRACE
-#define DYN_INFO_BUF_SIZE 1023
-static char ftrace_dyn_info_buffer[DYN_INFO_BUF_SIZE+1];
-static DEFINE_MUTEX(dyn_info_mutex);
-
int __weak ftrace_arch_read_dyn_info(char *buf, int size)
{
return 0;
@@ -2850,14 +2846,17 @@ static ssize_t
tracing_read_dyn_info(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
+ static char ftrace_dyn_info_buffer[1024];
+ static DEFINE_MUTEX(dyn_info_mutex);
unsigned long *p = filp->private_data;
char *buf = ftrace_dyn_info_buffer;
+ int size = ARRAY_SIZE(ftrace_dyn_info_buffer);
int r;
mutex_lock(&dyn_info_mutex);
r = sprintf(buf, "%ld ", *p);
- r += ftrace_arch_read_dyn_info(buf+r, DYN_INFO_BUF_SIZE-r);
+ r += ftrace_arch_read_dyn_info(buf+r, (size-1)-r);
buf[r++] = '\n';
r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH] hardirq.h clean up
2008-10-31 4:03 ` [PATCH] ftrace: nmi safe code clean ups Steven Rostedt
@ 2008-10-31 4:16 ` Steven Rostedt
2008-10-31 9:30 ` Ingo Molnar
2008-10-31 9:28 ` [PATCH] ftrace: nmi safe code clean ups Ingo Molnar
1 sibling, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2008-10-31 4:16 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, mingo, tglx, peterz, torvalds, srostedt
This patch converts the CPP macros of __irq_enter, __irq_exit,
nmi_enter, and nmi_exit into static inlines.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
include/linux/hardirq.h | 53 ++++++++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 26 deletions(-)
Index: linux-tip.git/include/linux/hardirq.h
===================================================================
--- linux-tip.git.orig/include/linux/hardirq.h 2008-10-30 10:27:09.000000000 -0400
+++ linux-tip.git/include/linux/hardirq.h 2008-10-31 00:07:46.000000000 -0400
@@ -133,13 +133,13 @@ extern void rcu_irq_exit(void);
* always balanced, so the interrupted value of ->hardirq_context
* will always be restored.
*/
-#define __irq_enter() \
- do { \
- rcu_irq_enter(); \
- account_system_vtime(current); \
- add_preempt_count(HARDIRQ_OFFSET); \
- trace_hardirq_enter(); \
- } while (0)
+static inline void __irq_enter(void)
+{
+ rcu_irq_enter();
+ account_system_vtime(current);
+ add_preempt_count(HARDIRQ_OFFSET);
+ trace_hardirq_enter();
+}
/*
* Enter irq context (on NO_HZ, update jiffies):
@@ -149,30 +149,31 @@ extern void irq_enter(void);
/*
* Exit irq context without processing softirqs:
*/
-#define __irq_exit() \
- do { \
- trace_hardirq_exit(); \
- account_system_vtime(current); \
- sub_preempt_count(HARDIRQ_OFFSET); \
- rcu_irq_exit(); \
- } while (0)
+static inline void __irq_exit(void)
+{
+ trace_hardirq_exit();
+ account_system_vtime(current);
+ sub_preempt_count(HARDIRQ_OFFSET);
+ rcu_irq_exit();
+}
/*
* Exit irq context and process softirqs if needed:
*/
extern void irq_exit(void);
-#define nmi_enter() \
- do { \
- ftrace_nmi_enter(); \
- lockdep_off(); \
- __irq_enter(); \
- } while (0)
-#define nmi_exit() \
- do { \
- __irq_exit(); \
- lockdep_on(); \
- ftrace_nmi_exit(); \
- } while (0)
+static inline void nmi_enter(void)
+{
+ ftrace_nmi_enter();
+ lockdep_off();
+ __irq_enter();
+}
+
+static inline void nmi_exit(void)
+{
+ __irq_exit();
+ lockdep_on();
+ ftrace_nmi_exit();
+}
#endif /* LINUX_HARDIRQ_H */
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] hardirq.h clean up
2008-10-31 4:16 ` [PATCH] hardirq.h clean up Steven Rostedt
@ 2008-10-31 9:30 ` Ingo Molnar
2008-10-31 13:36 ` [PATCH] ftrace: fix hardirq header for non ftrace archs Steven Rostedt
0 siblings, 1 reply; 18+ messages in thread
From: Ingo Molnar @ 2008-10-31 9:30 UTC (permalink / raw)
To: Steven Rostedt
Cc: Andrew Morton, linux-kernel, tglx, peterz, torvalds, srostedt
* Steven Rostedt <rostedt@goodmis.org> wrote:
>
> This patch converts the CPP macros of __irq_enter, __irq_exit,
> nmi_enter, and nmi_exit into static inlines.
>
> Signed-off-by: Steven Rostedt <srostedt@redhat.com>
> ---
> include/linux/hardirq.h | 53 ++++++++++++++++++++++++------------------------
> 1 file changed, 27 insertions(+), 26 deletions(-)
makes sense, but have you done build-testing (and cross-build-testing)
of this? I remember that this area was include-file-dependencies-hell
in the past.
perhaps with your simulate-old-arch patch on x86 we could tickle some
of the issues that trigger here.
Ingo
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH] ftrace: fix hardirq header for non ftrace archs
2008-10-31 9:30 ` Ingo Molnar
@ 2008-10-31 13:36 ` Steven Rostedt
2008-11-03 10:04 ` Ingo Molnar
0 siblings, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2008-10-31 13:36 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Andrew Morton, linux-kernel, tglx, peterz, torvalds, srostedt
Not all archs implement ftrace, and therefore do not have an asm/ftrace.h.
This patch corrects the problem.
The ftrace_nmi_enter/exit now must be defined for all archs that implement
dynamic ftrace. Currently, only x86 does.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
arch/arm/include/asm/ftrace.h | 5 -----
arch/powerpc/include/asm/ftrace.h | 5 -----
arch/sh/include/asm/ftrace.h | 5 -----
arch/sparc/include/asm/ftrace.h | 5 -----
arch/x86/include/asm/ftrace.h | 16 ----------------
include/linux/ftrace.h | 5 ++++-
include/linux/hardirq.h | 2 +-
7 files changed, 5 insertions(+), 38 deletions(-)
Index: linux-tip.git/arch/arm/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/arm/include/asm/ftrace.h 2008-10-30 23:24:18.000000000 -0400
+++ linux-tip.git/arch/arm/include/asm/ftrace.h 2008-10-31 08:48:47.000000000 -0400
@@ -1,11 +1,6 @@
#ifndef _ASM_ARM_FTRACE
#define _ASM_ARM_FTRACE
-#ifndef __ASSEMBLY__
-static inline void ftrace_nmi_enter(void) { }
-static inline void ftrace_nmi_exit(void) { }
-#endif
-
#ifdef CONFIG_FUNCTION_TRACER
#define MCOUNT_ADDR ((long)(mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Index: linux-tip.git/arch/powerpc/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/powerpc/include/asm/ftrace.h 2008-10-30 23:24:30.000000000 -0400
+++ linux-tip.git/arch/powerpc/include/asm/ftrace.h 2008-10-31 08:48:52.000000000 -0400
@@ -1,11 +1,6 @@
#ifndef _ASM_POWERPC_FTRACE
#define _ASM_POWERPC_FTRACE
-#ifndef __ASSEMBLY__
-static inline void ftrace_nmi_enter(void) { }
-static inline void ftrace_nmi_exit(void) { }
-#endif
-
#ifdef CONFIG_FUNCTION_TRACER
#define MCOUNT_ADDR ((long)(_mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Index: linux-tip.git/arch/sh/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/sh/include/asm/ftrace.h 2008-10-30 23:24:43.000000000 -0400
+++ linux-tip.git/arch/sh/include/asm/ftrace.h 2008-10-31 08:48:58.000000000 -0400
@@ -2,11 +2,6 @@
#define __ASM_SH_FTRACE_H
#ifndef __ASSEMBLY__
-static inline void ftrace_nmi_enter(void) { }
-static inline void ftrace_nmi_exit(void) { }
-#endif
-
-#ifndef __ASSEMBLY__
extern void mcount(void);
#endif
Index: linux-tip.git/arch/sparc/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/sparc/include/asm/ftrace.h 2008-10-30 23:24:50.000000000 -0400
+++ linux-tip.git/arch/sparc/include/asm/ftrace.h 2008-10-31 08:49:01.000000000 -0400
@@ -1,11 +1,6 @@
#ifndef _ASM_SPARC64_FTRACE
#define _ASM_SPARC64_FTRACE
-#ifndef __ASSEMBLY__
-static inline void ftrace_nmi_enter(void) { }
-static inline void ftrace_nmi_exit(void) { }
-#endif
-
#ifdef CONFIG_MCOUNT
#define MCOUNT_ADDR ((long)(_mcount))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
Index: linux-tip.git/arch/x86/include/asm/ftrace.h
===================================================================
--- linux-tip.git.orig/arch/x86/include/asm/ftrace.h 2008-10-30 23:25:26.000000000 -0400
+++ linux-tip.git/arch/x86/include/asm/ftrace.h 2008-10-31 08:52:44.000000000 -0400
@@ -17,23 +17,7 @@ static inline unsigned long ftrace_call_
*/
return addr - 1;
}
-
-#ifdef CONFIG_DYNAMIC_FTRACE
-extern void ftrace_nmi_enter(void);
-extern void ftrace_nmi_exit(void);
-#else
-static inline void ftrace_nmi_enter(void) { }
-static inline void ftrace_nmi_exit(void) { }
-#endif
#endif /* __ASSEMBLY__ */
-
-#else /* CONFIG_FUNCTION_TRACER */
-
-#ifndef __ASSEMBLY__
-static inline void ftrace_nmi_enter(void) { }
-static inline void ftrace_nmi_exit(void) { }
-#endif
-
#endif /* CONFIG_FUNCTION_TRACER */
#endif /* _ASM_X86_FTRACE_H */
Index: linux-tip.git/include/linux/ftrace.h
===================================================================
--- linux-tip.git.orig/include/linux/ftrace.h 2008-10-30 23:31:33.000000000 -0400
+++ linux-tip.git/include/linux/ftrace.h 2008-10-31 08:52:29.000000000 -0400
@@ -44,7 +44,6 @@ static inline void ftrace_kill(void) { }
#endif /* CONFIG_FUNCTION_TRACER */
#ifdef CONFIG_DYNAMIC_FTRACE
-
enum {
FTRACE_FL_FREE = (1 << 0),
FTRACE_FL_FAILED = (1 << 1),
@@ -105,6 +104,8 @@ extern void ftrace_release(void *start,
extern void ftrace_disable_daemon(void);
extern void ftrace_enable_daemon(void);
+extern void ftrace_nmi_enter(void);
+extern void ftrace_nmi_exit(void);
#else
# define skip_trace(ip) ({ 0; })
@@ -113,6 +114,8 @@ extern void ftrace_enable_daemon(void);
# define ftrace_disable_daemon() do { } while (0)
# define ftrace_enable_daemon() do { } while (0)
static inline void ftrace_release(void *start, unsigned long size) { }
+static inline void ftrace_nmi_enter(void) { }
+static inline void ftrace_nmi_exit(void) { }
#endif /* CONFIG_DYNAMIC_FTRACE */
/* totally disable ftrace - can not re-enable after this */
Index: linux-tip.git/include/linux/hardirq.h
===================================================================
--- linux-tip.git.orig/include/linux/hardirq.h 2008-10-31 00:07:46.000000000 -0400
+++ linux-tip.git/include/linux/hardirq.h 2008-10-31 08:53:01.000000000 -0400
@@ -4,8 +4,8 @@
#include <linux/preempt.h>
#include <linux/smp_lock.h>
#include <linux/lockdep.h>
+#include <linux/ftrace.h>
#include <asm/hardirq.h>
-#include <asm/ftrace.h>
#include <asm/system.h>
/*
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ftrace: fix hardirq header for non ftrace archs
2008-10-31 13:36 ` [PATCH] ftrace: fix hardirq header for non ftrace archs Steven Rostedt
@ 2008-11-03 10:04 ` Ingo Molnar
0 siblings, 0 replies; 18+ messages in thread
From: Ingo Molnar @ 2008-11-03 10:04 UTC (permalink / raw)
To: Steven Rostedt
Cc: Andrew Morton, linux-kernel, tglx, peterz, torvalds, srostedt
* Steven Rostedt <rostedt@goodmis.org> wrote:
>
> Not all archs implement ftrace, and therefore do not have an asm/ftrace.h.
> This patch corrects the problem.
>
> The ftrace_nmi_enter/exit now must be defined for all archs that implement
> dynamic ftrace. Currently, only x86 does.
>
> Signed-off-by: Steven Rostedt <srostedt@redhat.com>
> ---
> arch/arm/include/asm/ftrace.h | 5 -----
> arch/powerpc/include/asm/ftrace.h | 5 -----
> arch/sh/include/asm/ftrace.h | 5 -----
> arch/sparc/include/asm/ftrace.h | 5 -----
> arch/x86/include/asm/ftrace.h | 16 ----------------
> include/linux/ftrace.h | 5 ++++-
> include/linux/hardirq.h | 2 +-
> 7 files changed, 5 insertions(+), 38 deletions(-)
applied to tip/tracing/nmisafe, thanks Steve!
Ingo
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] ftrace: nmi safe code clean ups
2008-10-31 4:03 ` [PATCH] ftrace: nmi safe code clean ups Steven Rostedt
2008-10-31 4:16 ` [PATCH] hardirq.h clean up Steven Rostedt
@ 2008-10-31 9:28 ` Ingo Molnar
1 sibling, 0 replies; 18+ messages in thread
From: Ingo Molnar @ 2008-10-31 9:28 UTC (permalink / raw)
To: Steven Rostedt
Cc: Andrew Morton, linux-kernel, tglx, peterz, torvalds, srostedt
* Steven Rostedt <rostedt@goodmis.org> wrote:
>
> This patch cleans up the NMI safe code for dynamic ftrace as suggested
> by Andrew Morton.
>
> Signed-off-by: Steven Rostedt <srostedt@redhat.com>
> ---
> arch/arm/include/asm/ftrace.h | 4 ++--
> arch/powerpc/include/asm/ftrace.h | 4 ++--
> arch/sh/include/asm/ftrace.h | 4 ++--
> arch/sparc/include/asm/ftrace.h | 4 ++--
> arch/x86/include/asm/ftrace.h | 10 +++++-----
> arch/x86/kernel/ftrace.c | 16 ++++++++--------
> include/linux/ftrace.h | 3 +++
> kernel/trace/trace.c | 9 ++++-----
> 8 files changed, 28 insertions(+), 26 deletions(-)
applied to tip/tracing/nmisafe, thanks Steve!
Ingo
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/2] ftrace: nmi update statistics
2008-10-30 20:08 [PATCH 0/2] ftrace: handle NMIs safely Steven Rostedt
2008-10-30 20:08 ` [PATCH 1/2] ftrace: nmi safe code modification Steven Rostedt
@ 2008-10-30 20:08 ` Steven Rostedt
2008-10-30 20:38 ` Andrew Morton
2008-10-30 20:34 ` [PATCH 0/2] ftrace: handle NMIs safely Ingo Molnar
2 siblings, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2008-10-30 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: Ingo Molnar, Thomas Gleixner, Peter Zijlstra, Andrew Morton,
Linus Torvalds, Steven Rostedt
[-- Attachment #1: ftrace-count-nmi-writes.patch --]
[-- Type: text/plain, Size: 3349 bytes --]
This patch adds dynamic ftrace NMI update statistics to the
/debugfs/tracing/dyn_ftrace_total_info stat file.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
arch/x86/kernel/ftrace.c | 26 ++++++++++++++++++++++++--
kernel/trace/trace.c | 31 ++++++++++++++++++++++++-------
2 files changed, 48 insertions(+), 9 deletions(-)
Index: linux-tip.git/arch/x86/kernel/ftrace.c
===================================================================
--- linux-tip.git.orig/arch/x86/kernel/ftrace.c 2008-10-30 15:30:12.000000000 -0400
+++ linux-tip.git/arch/x86/kernel/ftrace.c 2008-10-30 15:51:51.000000000 -0400
@@ -91,6 +91,19 @@ static int mod_code_write;
static void *mod_code_ip;
static void *mod_code_newcode;
+static int nmi_wait_count;
+static atomic_t nmi_update_count;
+
+int ftrace_arch_read_dyn_info(char *buf, int size)
+{
+ int r;
+
+ r = snprintf(buf, size, "%u %u",
+ nmi_wait_count,
+ atomic_read(&nmi_update_count));
+ return r;
+}
+
static void ftrace_mod_code(void)
{
/*
@@ -109,8 +122,10 @@ void ftrace_nmi_enter(void)
atomic_inc(&in_nmi);
/* Must have in_nmi seen before reading write flag */
smp_mb();
- if (mod_code_write)
+ if (mod_code_write) {
ftrace_mod_code();
+ atomic_inc(&nmi_update_count);
+ }
}
void ftrace_nmi_exit(void)
@@ -122,8 +137,15 @@ void ftrace_nmi_exit(void)
static void wait_for_nmi(void)
{
- while (atomic_read(&in_nmi))
+ int waited = 0;
+
+ while (atomic_read(&in_nmi)) {
+ waited = 1;
cpu_relax();
+ }
+
+ if (waited)
+ nmi_wait_count++;
}
static int
Index: linux-tip.git/kernel/trace/trace.c
===================================================================
--- linux-tip.git.orig/kernel/trace/trace.c 2008-10-30 15:18:45.000000000 -0400
+++ linux-tip.git/kernel/trace/trace.c 2008-10-30 15:51:51.000000000 -0400
@@ -2837,22 +2837,39 @@ static struct file_operations tracing_ma
#ifdef CONFIG_DYNAMIC_FTRACE
+#define DYN_INFO_BUF_SIZE 1023
+static char ftrace_dyn_info_buffer[DYN_INFO_BUF_SIZE+1];
+static DEFINE_MUTEX(dyn_info_mutex);
+
+int __weak ftrace_arch_read_dyn_info(char *buf, int size)
+{
+ return 0;
+}
+
static ssize_t
-tracing_read_long(struct file *filp, char __user *ubuf,
+tracing_read_dyn_info(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
unsigned long *p = filp->private_data;
- char buf[64];
+ char *buf = ftrace_dyn_info_buffer;
int r;
- r = sprintf(buf, "%ld\n", *p);
+ mutex_lock(&dyn_info_mutex);
+ r = sprintf(buf, "%ld ", *p);
+
+ r += ftrace_arch_read_dyn_info(buf+r, DYN_INFO_BUF_SIZE-r);
+ buf[r++] = '\n';
+
+ r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+
+ mutex_unlock(&dyn_info_mutex);
- return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
+ return r;
}
-static struct file_operations tracing_read_long_fops = {
+static struct file_operations tracing_dyn_info_fops = {
.open = tracing_open_generic,
- .read = tracing_read_long,
+ .read = tracing_read_dyn_info,
};
#endif
@@ -2961,7 +2978,7 @@ static __init int tracer_init_debugfs(vo
#ifdef CONFIG_DYNAMIC_FTRACE
entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer,
&ftrace_update_tot_cnt,
- &tracing_read_long_fops);
+ &tracing_dyn_info_fops);
if (!entry)
pr_warning("Could not create debugfs "
"'dyn_ftrace_total_info' entry\n");
--
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] ftrace: nmi update statistics
2008-10-30 20:08 ` [PATCH 2/2] ftrace: nmi update statistics Steven Rostedt
@ 2008-10-30 20:38 ` Andrew Morton
2008-10-30 21:14 ` Steven Rostedt
0 siblings, 1 reply; 18+ messages in thread
From: Andrew Morton @ 2008-10-30 20:38 UTC (permalink / raw)
To: Steven Rostedt; +Cc: linux-kernel, mingo, tglx, peterz, torvalds, srostedt
On Thu, 30 Oct 2008 16:08:33 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> This patch adds dynamic ftrace NMI update statistics to the
> /debugfs/tracing/dyn_ftrace_total_info stat file.
>
> Signed-off-by: Steven Rostedt <srostedt@redhat.com>
> ---
> arch/x86/kernel/ftrace.c | 26 ++++++++++++++++++++++++--
> kernel/trace/trace.c | 31 ++++++++++++++++++++++++-------
No header files were modified, but ftrace_arch_read_dyn_info() should
have been declared so that the above two compilation units see the
declaration.
>
> Index: linux-tip.git/arch/x86/kernel/ftrace.c
> ===================================================================
> --- linux-tip.git.orig/arch/x86/kernel/ftrace.c 2008-10-30 15:30:12.000000000 -0400
> +++ linux-tip.git/arch/x86/kernel/ftrace.c 2008-10-30 15:51:51.000000000 -0400
> @@ -91,6 +91,19 @@ static int mod_code_write;
> static void *mod_code_ip;
> static void *mod_code_newcode;
>
> +static int nmi_wait_count;
> +static atomic_t nmi_update_count;
<the ATOMIC_INIT thing>
> +int ftrace_arch_read_dyn_info(char *buf, int size)
> +{
> + int r;
> +
> + r = snprintf(buf, size, "%u %u",
> + nmi_wait_count,
> + atomic_read(&nmi_update_count));
> + return r;
> +}
Yes, nmi_wait_count is an unsigned quantity. Might as well define it
thusly?
> static void ftrace_mod_code(void)
> {
> /*
> @@ -109,8 +122,10 @@ void ftrace_nmi_enter(void)
> atomic_inc(&in_nmi);
> /* Must have in_nmi seen before reading write flag */
> smp_mb();
> - if (mod_code_write)
> + if (mod_code_write) {
> ftrace_mod_code();
> + atomic_inc(&nmi_update_count);
> + }
> }
>
> void ftrace_nmi_exit(void)
> @@ -122,8 +137,15 @@ void ftrace_nmi_exit(void)
>
> static void wait_for_nmi(void)
> {
> - while (atomic_read(&in_nmi))
> + int waited = 0;
> +
> + while (atomic_read(&in_nmi)) {
> + waited = 1;
> cpu_relax();
> + }
> +
> + if (waited)
> + nmi_wait_count++;
> }
>
> static int
> Index: linux-tip.git/kernel/trace/trace.c
> ===================================================================
> --- linux-tip.git.orig/kernel/trace/trace.c 2008-10-30 15:18:45.000000000 -0400
> +++ linux-tip.git/kernel/trace/trace.c 2008-10-30 15:51:51.000000000 -0400
> @@ -2837,22 +2837,39 @@ static struct file_operations tracing_ma
>
> #ifdef CONFIG_DYNAMIC_FTRACE
>
> +#define DYN_INFO_BUF_SIZE 1023
> +static char ftrace_dyn_info_buffer[DYN_INFO_BUF_SIZE+1];
Could be made local to tracing_read_dyn_info().
Could just be
static char ftrace_dyn_info_buffer[1024];
then use sizeof/ARRAY_SIZE elsewhere. I think this is a bit safer and
more readable - the reader doesn't have to run around the code checking
that the correct #define was used in both places.
> +static DEFINE_MUTEX(dyn_info_mutex);
> +
> +int __weak ftrace_arch_read_dyn_info(char *buf, int size)
> +{
> + return 0;
> +}
> +
> static ssize_t
> -tracing_read_long(struct file *filp, char __user *ubuf,
> +tracing_read_dyn_info(struct file *filp, char __user *ubuf,
> size_t cnt, loff_t *ppos)
> {
> unsigned long *p = filp->private_data;
> - char buf[64];
> + char *buf = ftrace_dyn_info_buffer;
> int r;
>
> - r = sprintf(buf, "%ld\n", *p);
> + mutex_lock(&dyn_info_mutex);
> + r = sprintf(buf, "%ld ", *p);
> +
> + r += ftrace_arch_read_dyn_info(buf+r, DYN_INFO_BUF_SIZE-r);
> + buf[r++] = '\n';
> +
> + r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
> +
> + mutex_unlock(&dyn_info_mutex);
>
> - return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
> + return r;
> }
>
> -static struct file_operations tracing_read_long_fops = {
> +static struct file_operations tracing_dyn_info_fops = {
> .open = tracing_open_generic,
> - .read = tracing_read_long,
> + .read = tracing_read_dyn_info,
> };
> #endif
>
> @@ -2961,7 +2978,7 @@ static __init int tracer_init_debugfs(vo
> #ifdef CONFIG_DYNAMIC_FTRACE
> entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer,
> &ftrace_update_tot_cnt,
> - &tracing_read_long_fops);
> + &tracing_dyn_info_fops);
> if (!entry)
> pr_warning("Could not create debugfs "
> "'dyn_ftrace_total_info' entry\n");
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/2] ftrace: nmi update statistics
2008-10-30 20:38 ` Andrew Morton
@ 2008-10-30 21:14 ` Steven Rostedt
0 siblings, 0 replies; 18+ messages in thread
From: Steven Rostedt @ 2008-10-30 21:14 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, mingo, tglx, peterz, torvalds, srostedt
On Thu, 30 Oct 2008, Andrew Morton wrote:
> On Thu, 30 Oct 2008 16:08:33 -0400
> Steven Rostedt <rostedt@goodmis.org> wrote:
>
> > This patch adds dynamic ftrace NMI update statistics to the
> > /debugfs/tracing/dyn_ftrace_total_info stat file.
> >
> > Signed-off-by: Steven Rostedt <srostedt@redhat.com>
> > ---
> > arch/x86/kernel/ftrace.c | 26 ++++++++++++++++++++++++--
> > kernel/trace/trace.c | 31 ++++++++++++++++++++++++-------
>
> No header files were modified, but ftrace_arch_read_dyn_info() should
> have been declared so that the above two compilation units see the
> declaration.
Ah, you caught me being lazy ;-) Since both also define the function, I
figured I'd be OK. But you are right, this would prevent bugs where the
two functions somehow got different parameters.
Will fix.
>
> >
> > Index: linux-tip.git/arch/x86/kernel/ftrace.c
> > ===================================================================
> > --- linux-tip.git.orig/arch/x86/kernel/ftrace.c 2008-10-30 15:30:12.000000000 -0400
> > +++ linux-tip.git/arch/x86/kernel/ftrace.c 2008-10-30 15:51:51.000000000 -0400
> > @@ -91,6 +91,19 @@ static int mod_code_write;
> > static void *mod_code_ip;
> > static void *mod_code_newcode;
> >
> > +static int nmi_wait_count;
> > +static atomic_t nmi_update_count;
>
> <the ATOMIC_INIT thing>
Hmm, this being arch specific code, is there such a thing as "atomic
declared as zero on x86 is OK" rule?
>
> > +int ftrace_arch_read_dyn_info(char *buf, int size)
> > +{
> > + int r;
> > +
> > + r = snprintf(buf, size, "%u %u",
> > + nmi_wait_count,
> > + atomic_read(&nmi_update_count));
> > + return r;
> > +}
>
> Yes, nmi_wait_count is an unsigned quantity. Might as well define it
> thusly?
OK.
>
> > static void ftrace_mod_code(void)
> > {
> > /*
> > @@ -109,8 +122,10 @@ void ftrace_nmi_enter(void)
> > atomic_inc(&in_nmi);
> > /* Must have in_nmi seen before reading write flag */
> > smp_mb();
> > - if (mod_code_write)
> > + if (mod_code_write) {
> > ftrace_mod_code();
> > + atomic_inc(&nmi_update_count);
> > + }
> > }
> >
> > void ftrace_nmi_exit(void)
> > @@ -122,8 +137,15 @@ void ftrace_nmi_exit(void)
> >
> > static void wait_for_nmi(void)
> > {
> > - while (atomic_read(&in_nmi))
> > + int waited = 0;
> > +
> > + while (atomic_read(&in_nmi)) {
> > + waited = 1;
> > cpu_relax();
> > + }
> > +
> > + if (waited)
> > + nmi_wait_count++;
> > }
> >
> > static int
> > Index: linux-tip.git/kernel/trace/trace.c
> > ===================================================================
> > --- linux-tip.git.orig/kernel/trace/trace.c 2008-10-30 15:18:45.000000000 -0400
> > +++ linux-tip.git/kernel/trace/trace.c 2008-10-30 15:51:51.000000000 -0400
> > @@ -2837,22 +2837,39 @@ static struct file_operations tracing_ma
> >
> > #ifdef CONFIG_DYNAMIC_FTRACE
> >
> > +#define DYN_INFO_BUF_SIZE 1023
> > +static char ftrace_dyn_info_buffer[DYN_INFO_BUF_SIZE+1];
>
> Could be made local to tracing_read_dyn_info().
>
>
> Could just be
>
> static char ftrace_dyn_info_buffer[1024];
>
> then use sizeof/ARRAY_SIZE elsewhere. I think this is a bit safer and
I think there's a defined macro for that... (goes look)
Yep! it's called ARRAY_SIZE(arr)
> more readable - the reader doesn't have to run around the code checking
> that the correct #define was used in both places.
Will fix.
Thanks,
-- Steve
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/2] ftrace: handle NMIs safely
2008-10-30 20:08 [PATCH 0/2] ftrace: handle NMIs safely Steven Rostedt
2008-10-30 20:08 ` [PATCH 1/2] ftrace: nmi safe code modification Steven Rostedt
2008-10-30 20:08 ` [PATCH 2/2] ftrace: nmi update statistics Steven Rostedt
@ 2008-10-30 20:34 ` Ingo Molnar
2008-10-30 21:15 ` Steven Rostedt
2 siblings, 1 reply; 18+ messages in thread
From: Ingo Molnar @ 2008-10-30 20:34 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-kernel, Thomas Gleixner, Peter Zijlstra, Andrew Morton,
Linus Torvalds
* Steven Rostedt <rostedt@goodmis.org> wrote:
> The robustness of ftrace has been the focus of the code modification
> in 2.6.28. There is one remaining issue that needed to be addressed.
> This was the case of NMIs.
applied to tip/tracing/nmisafe, thanks Steve!
this looks a lot nicer approach than either putting some sort of lock
into NMI context (yuck) or the disabling of NMIs (not really possible
in a generic way architecturally).
the impact is quite non-trivial, so i dont think this is v2.6.28
material.
Ingo
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/2] ftrace: handle NMIs safely
2008-10-30 20:34 ` [PATCH 0/2] ftrace: handle NMIs safely Ingo Molnar
@ 2008-10-30 21:15 ` Steven Rostedt
2008-10-30 22:26 ` Ingo Molnar
0 siblings, 1 reply; 18+ messages in thread
From: Steven Rostedt @ 2008-10-30 21:15 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Thomas Gleixner, Peter Zijlstra, Andrew Morton,
Linus Torvalds
On Thu, 30 Oct 2008, Ingo Molnar wrote:
>
> * Steven Rostedt <rostedt@goodmis.org> wrote:
>
> > The robustness of ftrace has been the focus of the code modification
> > in 2.6.28. There is one remaining issue that needed to be addressed.
> > This was the case of NMIs.
>
> applied to tip/tracing/nmisafe, thanks Steve!
>
> this looks a lot nicer approach than either putting some sort of lock
> into NMI context (yuck) or the disabling of NMIs (not really possible
> in a generic way architecturally).
>
> the impact is quite non-trivial, so i dont think this is v2.6.28
> material.
Ingo,
Do you want me to send patches on top of these to address Andrew's
comements? Or do you want me to resend these with the updates.
I prefer to send patches on top, that way Andrew can make sure I did his
changes correctly ;-)
-- Steve
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 0/2] ftrace: handle NMIs safely
2008-10-30 21:15 ` Steven Rostedt
@ 2008-10-30 22:26 ` Ingo Molnar
0 siblings, 0 replies; 18+ messages in thread
From: Ingo Molnar @ 2008-10-30 22:26 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-kernel, Thomas Gleixner, Peter Zijlstra, Andrew Morton,
Linus Torvalds
* Steven Rostedt <rostedt@goodmis.org> wrote:
>
> On Thu, 30 Oct 2008, Ingo Molnar wrote:
>
> >
> > * Steven Rostedt <rostedt@goodmis.org> wrote:
> >
> > > The robustness of ftrace has been the focus of the code modification
> > > in 2.6.28. There is one remaining issue that needed to be addressed.
> > > This was the case of NMIs.
> >
> > applied to tip/tracing/nmisafe, thanks Steve!
> >
> > this looks a lot nicer approach than either putting some sort of lock
> > into NMI context (yuck) or the disabling of NMIs (not really possible
> > in a generic way architecturally).
> >
> > the impact is quite non-trivial, so i dont think this is v2.6.28
> > material.
>
> Ingo,
>
> Do you want me to send patches on top of these to address Andrew's
> comements? Or do you want me to resend these with the updates.
>
> I prefer to send patches on top, that way Andrew can make sure I did
> his changes correctly ;-)
yeah, please do it that way. It's a separate topic so we can fold them
back if they are also bugfixes. (and they are all cleanliness related
and i wanted to see the stability impact ASAP)
Ingo
^ permalink raw reply [flat|nested] 18+ messages in thread