Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f307891 authored by Steven Rostedt's avatar Steven Rostedt Committed by Linus Torvalds
Browse files

locking: add typecheck on irqsave and friends for correct flags



There haave been several areas in the kernel where an int has been used for
flags in local_irq_save() and friends instead of a long.  This can cause some
hard to debug problems on some architectures.

This patch adds a typecheck inside the irqsave and restore functions to flag
these cases.

[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: build fix]
Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent e0deaff4
Loading
Loading
Loading
Loading
+39 −15
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@
#ifndef _LINUX_TRACE_IRQFLAGS_H
#define _LINUX_TRACE_IRQFLAGS_H

#include <linux/typecheck.h>

#ifdef CONFIG_TRACE_IRQFLAGS
  extern void trace_softirqs_on(unsigned long ip);
  extern void trace_softirqs_off(unsigned long ip);
@@ -59,10 +61,16 @@
#define local_irq_disable() \
	do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
#define local_irq_save(flags)				\
	do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0)
	do {						\
		typecheck(unsigned long, flags);	\
		raw_local_irq_save(flags);		\
		trace_hardirqs_off();			\
	} while (0)


#define local_irq_restore(flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		if (raw_irqs_disabled_flags(flags)) {	\
			raw_local_irq_restore(flags);	\
			trace_hardirqs_off();		\
@@ -78,8 +86,16 @@
 */
# define raw_local_irq_disable()	local_irq_disable()
# define raw_local_irq_enable()		local_irq_enable()
# define raw_local_irq_save(flags)	local_irq_save(flags)
# define raw_local_irq_restore(flags)	local_irq_restore(flags)
# 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)
#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */

#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
@@ -89,7 +105,11 @@
		raw_safe_halt();				\
	} while (0)

#define local_save_flags(flags)		raw_local_save_flags(flags)
#define local_save_flags(flags)				\
	do {						\
		typecheck(unsigned long, flags);	\
		raw_local_save_flags(flags);		\
	} while (0)

#define irqs_disabled()						\
({								\
@@ -99,7 +119,11 @@
	raw_irqs_disabled_flags(_flags);			\
})

#define irqs_disabled_flags(flags)	raw_irqs_disabled_flags(flags)
#define irqs_disabled_flags(flags)		\
({						\
	typecheck(unsigned long, flags);	\
	raw_irqs_disabled_flags(flags);		\
})
#endif		/* CONFIG_X86 */

#endif
+56 −16
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
 *  linux/spinlock.h:     builds the final spin_*() APIs.
 */

#include <linux/typecheck.h>
#include <linux/preempt.h>
#include <linux/linkage.h>
#include <linux/compiler.h>
@@ -191,23 +192,53 @@ do { \

#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)

#define spin_lock_irqsave(lock, flags)	flags = _spin_lock_irqsave(lock)
#define read_lock_irqsave(lock, flags)	flags = _read_lock_irqsave(lock)
#define write_lock_irqsave(lock, flags)	flags = _write_lock_irqsave(lock)
#define spin_lock_irqsave(lock, flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		flags = _spin_lock_irqsave(lock);	\
	} while (0)
#define read_lock_irqsave(lock, flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		flags = _read_lock_irqsave(lock);	\
	} while (0)
#define write_lock_irqsave(lock, flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		flags = _write_lock_irqsave(lock);	\
	} while (0)

#ifdef CONFIG_DEBUG_LOCK_ALLOC
#define spin_lock_irqsave_nested(lock, flags, subclass)			\
	flags = _spin_lock_irqsave_nested(lock, subclass)
	do {								\
		typecheck(unsigned long, flags);			\
		flags = _spin_lock_irqsave_nested(lock, subclass);	\
	} while (0)
#else
#define spin_lock_irqsave_nested(lock, flags, subclass)			\
	flags = _spin_lock_irqsave(lock)
	do {								\
		typecheck(unsigned long, flags);			\
		flags = _spin_lock_irqsave(lock);			\
	} while (0)
#endif

#else

#define spin_lock_irqsave(lock, flags)	_spin_lock_irqsave(lock, flags)
#define read_lock_irqsave(lock, flags)	_read_lock_irqsave(lock, flags)
#define write_lock_irqsave(lock, flags)	_write_lock_irqsave(lock, flags)
#define spin_lock_irqsave(lock, flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		_spin_lock_irqsave(lock, flags);	\
	} while (0)
#define read_lock_irqsave(lock, flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		_read_lock_irqsave(lock, flags);	\
	} while (0)
#define write_lock_irqsave(lock, flags)			\
	do {						\
		typecheck(unsigned long, flags);	\
		_write_lock_irqsave(lock, flags);	\
	} while (0)
#define spin_lock_irqsave_nested(lock, flags, subclass)	\
	spin_lock_irqsave(lock, flags)

@@ -261,15 +292,24 @@ do { \
#endif

#define spin_unlock_irqrestore(lock, flags)		\
					_spin_unlock_irqrestore(lock, flags)
	do {						\
		typecheck(unsigned long, flags);	\
		_spin_unlock_irqrestore(lock, flags);	\
	} while (0)
#define spin_unlock_bh(lock)		_spin_unlock_bh(lock)

#define read_unlock_irqrestore(lock, flags)		\
					_read_unlock_irqrestore(lock, flags)
	do {						\
		typecheck(unsigned long, flags);	\
		_read_unlock_irqrestore(lock, flags);	\
	} while (0)
#define read_unlock_bh(lock)		_read_unlock_bh(lock)

#define write_unlock_irqrestore(lock, flags)		\
					_write_unlock_irqrestore(lock, flags)
	do {						\
		typecheck(unsigned long, flags);	\
		_write_unlock_irqrestore(lock, flags);	\
	} while (0)
#define write_unlock_bh(lock)		_write_unlock_bh(lock)

#define spin_trylock_bh(lock)	__cond_lock(lock, _spin_trylock_bh(lock))