public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] kernel: local_irq_{save,restore}_nmi()
@ 2010-04-09 23:01 David Miller
  2010-06-04  5:03 ` Paul Mundt
  0 siblings, 1 reply; 3+ messages in thread
From: David Miller @ 2010-04-09 23:01 UTC (permalink / raw)
  To: peterz; +Cc: linux-kernel, linux-arch, sparclinux


Provide local_irq_{save,restore}_nmi() which will allow us to help
architectures that implement NMIs using IRQ priorities like SPARC64
does.

Sparc uses IRQ prio 15 for NMIs and implements local_irq_disable() as
disable <= 14. However if you do that while inside an NMI you re-
enable the NMI priority again, causing all kinds of fun.

A more solid implementation would first check the disable level and
never lower it, however that is more costly and would slow down the
rest of the kernel for no particular reason.

Therefore introduce local_irq_save_nmi() which can implement this
slower but more solid scheme and dis-allow local_irq_save() from NMI
context.

Suggested-by: David Miller <davem@davemloft.net>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/linux/irqflags.h     |   51 +++++++++++++++++++++++++++++++++++++++--
 kernel/lockdep.c             |    7 +++++
 kernel/trace/trace_irqsoff.c |    8 ++++++
 3 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
index 006bf45..91256d4 100644
--- a/include/linux/irqflags.h
+++ b/include/linux/irqflags.h
@@ -18,6 +18,7 @@
   extern void trace_softirqs_off(unsigned long ip);
   extern void trace_hardirqs_on(void);
   extern void trace_hardirqs_off(void);
+  extern void trace_hardirqs_off_no_nmi(void);
 # define trace_hardirq_context(p)	((p)->hardirq_context)
 # define trace_softirq_context(p)	((p)->softirq_context)
 # define trace_hardirqs_enabled(p)	((p)->hardirqs_enabled)
@@ -30,6 +31,7 @@
 #else
 # define trace_hardirqs_on()		do { } while (0)
 # define trace_hardirqs_off()		do { } while (0)
+# define trace_hardirqs_off_no_nmi()	do { } while (0)
 # define trace_softirqs_on(ip)		do { } while (0)
 # define trace_softirqs_off(ip)		do { } while (0)
 # define trace_hardirq_context(p)	0
@@ -59,15 +61,15 @@
 #define local_irq_enable() \
 	do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
 #define local_irq_disable() \
-	do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
+	do { raw_local_irq_disable(); trace_hardirqs_off_no_nmi(); } while (0)
+
 #define local_irq_save(flags)				\
 	do {						\
 		typecheck(unsigned long, flags);	\
 		raw_local_irq_save(flags);		\
-		trace_hardirqs_off();			\
+		trace_hardirqs_off_no_nmi();		\
 	} while (0)
 
-
 #define local_irq_restore(flags)			\
 	do {						\
 		typecheck(unsigned long, flags);	\
@@ -79,6 +81,30 @@
 			raw_local_irq_restore(flags);	\
 		}					\
 	} while (0)
+
+#ifndef local_irq_save_nmi
+# define local_irq_save_nmi(flags) 			\
+	 do {						\
+		 typecheck(unsigned long, flags);	\
+		 raw_local_irq_save(flags);		\
+		 trace_hardirqs_off();			\
+	 } while (0)
+#endif
+
+#ifndef local_irq_restore_nmi
+#define local_irq_restore_nmi(flags)			\
+	do {						\
+		typecheck(unsigned long, flags);	\
+		if (raw_irqs_disabled_flags(flags)) {	\
+			raw_local_irq_restore(flags);	\
+			trace_hardirqs_off();		\
+		} else {				\
+			trace_hardirqs_on();		\
+			raw_local_irq_restore(flags);	\
+		}					\
+	} while (0)
+#endif
+
 #else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */
 /*
  * The local_irq_*() APIs are equal to the raw_local_irq*()
@@ -86,16 +112,35 @@
  */
 # define raw_local_irq_disable()	local_irq_disable()
 # define raw_local_irq_enable()		local_irq_enable()
+
 # define raw_local_irq_save(flags)			\
 	do {						\
 		typecheck(unsigned long, flags);	\
 		local_irq_save(flags);			\
 	} while (0)
+
 # define raw_local_irq_restore(flags)			\
 	do {						\
 		typecheck(unsigned long, flags);	\
 		local_irq_restore(flags);		\
 	} while (0)
+
+#ifndef local_irq_save_nmi
+# define local_irq_save_nmi(flags)			\
+	 do {						\
+		 typecheck(unsigned long, flags);	\
+		 local_irq_save(flags);			\
+	 } while (0)
+#endif
+
+#ifndef local_irq_restore_nmi
+# define local_irq_restore_nmi(flags)			\
+	 do {						\
+		 typecheck(unsigned long, flags);	\
+		 local_irq_restore(flags);		\
+	 } while (0)
+#endif
+
 #endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */
 
 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 2594e1c..c2aae0f 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -2382,6 +2382,13 @@ void trace_hardirqs_off(void)
 }
 EXPORT_SYMBOL(trace_hardirqs_off);
 
+void trace_hardirqs_off_no_nmi(void)
+{
+	WARN_ON_ONCE(in_nmi());
+	trace_hardirqs_off_caller(CALLER_ADDR0);
+}
+EXPORT_SYMBOL(trace_hardirqs_off_no_nmi);
+
 /*
  * Softirqs will be enabled:
  */
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 2974bc7..7596c6f 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -316,6 +316,14 @@ void trace_hardirqs_off(void)
 }
 EXPORT_SYMBOL(trace_hardirqs_off);
 
+void trace_hardirqs_off_no_nmi(void)
+{
+	WARN_ON_ONCE(in_nmi());
+	if (!preempt_trace() && irq_trace())
+		start_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
+}
+EXPORT_SYMBOL(trace_hardirqs_off_no_nmi);
+
 void trace_hardirqs_on_caller(unsigned long caller_addr)
 {
 	if (!preempt_trace() && irq_trace())
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/4] kernel: local_irq_{save,restore}_nmi()
  2010-04-09 23:01 [PATCH 1/4] kernel: local_irq_{save,restore}_nmi() David Miller
@ 2010-06-04  5:03 ` Paul Mundt
  2010-06-04  7:35   ` Peter Zijlstra
  0 siblings, 1 reply; 3+ messages in thread
From: Paul Mundt @ 2010-06-04  5:03 UTC (permalink / raw)
  To: David Miller; +Cc: peterz, linux-kernel, linux-arch, sparclinux

On Fri, Apr 09, 2010 at 04:01:35PM -0700, David Miller wrote:
> 
> Provide local_irq_{save,restore}_nmi() which will allow us to help
> architectures that implement NMIs using IRQ priorities like SPARC64
> does.
> 
> Sparc uses IRQ prio 15 for NMIs and implements local_irq_disable() as
> disable <= 14. However if you do that while inside an NMI you re-
> enable the NMI priority again, causing all kinds of fun.
> 
> A more solid implementation would first check the disable level and
> never lower it, however that is more costly and would slow down the
> rest of the kernel for no particular reason.
> 
> Therefore introduce local_irq_save_nmi() which can implement this
> slower but more solid scheme and dis-allow local_irq_save() from NMI
> context.
> 
> Suggested-by: David Miller <davem@davemloft.net>
> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Signed-off-by: David S. Miller <davem@davemloft.net>

Are there any updates for this patch series? I would like to make use of
this on SH as well, but it seems these haven't hit upstream yet.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/4] kernel: local_irq_{save,restore}_nmi()
  2010-06-04  5:03 ` Paul Mundt
@ 2010-06-04  7:35   ` Peter Zijlstra
  0 siblings, 0 replies; 3+ messages in thread
From: Peter Zijlstra @ 2010-06-04  7:35 UTC (permalink / raw)
  To: Paul Mundt; +Cc: David Miller, linux-kernel, linux-arch, sparclinux

On Fri, 2010-06-04 at 14:03 +0900, Paul Mundt wrote:
> On Fri, Apr 09, 2010 at 04:01:35PM -0700, David Miller wrote:
> > 
> > Provide local_irq_{save,restore}_nmi() which will allow us to help
> > architectures that implement NMIs using IRQ priorities like SPARC64
> > does.
> > 
> > Sparc uses IRQ prio 15 for NMIs and implements local_irq_disable() as
> > disable <= 14. However if you do that while inside an NMI you re-
> > enable the NMI priority again, causing all kinds of fun.
> > 
> > A more solid implementation would first check the disable level and
> > never lower it, however that is more costly and would slow down the
> > rest of the kernel for no particular reason.
> > 
> > Therefore introduce local_irq_save_nmi() which can implement this
> > slower but more solid scheme and dis-allow local_irq_save() from NMI
> > context.
> > 
> > Suggested-by: David Miller <davem@davemloft.net>
> > Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> > Signed-off-by: David S. Miller <davem@davemloft.net>
> 
> Are there any updates for this patch series? I would like to make use of
> this on SH as well, but it seems these haven't hit upstream yet.

Dave found a better solution, see:

  b4f4372f96e0573d752d9e45beda02fabf716cc8
  0c25e9e6cbe7b233bb91d14d0e2c258bf8e6ec83
  c011f80ba0912486fe51dd2b3f71d9b33a151188



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-06-04  7:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-09 23:01 [PATCH 1/4] kernel: local_irq_{save,restore}_nmi() David Miller
2010-06-04  5:03 ` Paul Mundt
2010-06-04  7:35   ` Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox