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

Commit 545695fb authored by Tejun Heo's avatar Tejun Heo
Browse files

percpu: make accessors check for percpu pointer in sparse



The previous patch made sparse warn about percpu variables being used
directly without going through percpu accessors.  This patch
implements the other half - checking whether non percpu variable is
passed into percpu accessors.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Al Viro <viro@zeniv.linux.org.uk>
parent e0fdb0e0
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -42,8 +42,10 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
 */
 */
#ifndef SHIFT_PERCPU_PTR
#ifndef SHIFT_PERCPU_PTR
/* Weird cast keeps both GCC and sparse happy. */
/* Weird cast keeps both GCC and sparse happy. */
#define SHIFT_PERCPU_PTR(__p, __offset)				\
#define SHIFT_PERCPU_PTR(__p, __offset)	({				\
	RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset))
	__verify_pcpu_ptr((__p));					\
	RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
})
#endif
#endif


/*
/*
+18 −2
Original line number Original line Diff line number Diff line
@@ -18,6 +18,16 @@
#define __PCPU_DUMMY_ATTRS						\
#define __PCPU_DUMMY_ATTRS						\
	__attribute__((section(".discard"), unused))
	__attribute__((section(".discard"), unused))


/*
 * Macro which verifies @ptr is a percpu pointer without evaluating
 * @ptr.  This is to be used in percpu accessors to verify that the
 * input parameter is a percpu pointer.
 */
#define __verify_pcpu_ptr(ptr)	do {					\
	void __percpu *__vpp_verify = (typeof(ptr))NULL;		\
	(void)__vpp_verify;						\
} while (0)

/*
/*
 * s390 and alpha modules require percpu variables to be defined as
 * s390 and alpha modules require percpu variables to be defined as
 * weak to force the compiler to generate GOT based external
 * weak to force the compiler to generate GOT based external
@@ -129,10 +139,16 @@
	__aligned(PAGE_SIZE)
	__aligned(PAGE_SIZE)


/*
/*
 * Intermodule exports for per-CPU variables.
 * Intermodule exports for per-CPU variables.  sparse forgets about
 * address space across EXPORT_SYMBOL(), change EXPORT_SYMBOL() to
 * noop if __CHECKER__.
 */
 */
#ifndef __CHECKER__
#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var)
#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var)
#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var)
#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var)

#else
#define EXPORT_PER_CPU_SYMBOL(var)
#define EXPORT_PER_CPU_SYMBOL_GPL(var)
#endif


#endif /* _LINUX_PERCPU_DEFS_H */
#endif /* _LINUX_PERCPU_DEFS_H */
+2 −0
Original line number Original line Diff line number Diff line
@@ -237,6 +237,7 @@ extern void __bad_size_call_parameter(void);


#define __pcpu_size_call_return(stem, variable)				\
#define __pcpu_size_call_return(stem, variable)				\
({	typeof(variable) pscr_ret__;					\
({	typeof(variable) pscr_ret__;					\
	__verify_pcpu_ptr(&(variable));					\
	switch(sizeof(variable)) {					\
	switch(sizeof(variable)) {					\
	case 1: pscr_ret__ = stem##1(variable);break;			\
	case 1: pscr_ret__ = stem##1(variable);break;			\
	case 2: pscr_ret__ = stem##2(variable);break;			\
	case 2: pscr_ret__ = stem##2(variable);break;			\
@@ -250,6 +251,7 @@ extern void __bad_size_call_parameter(void);


#define __pcpu_size_call(stem, variable, ...)				\
#define __pcpu_size_call(stem, variable, ...)				\
do {									\
do {									\
	__verify_pcpu_ptr(&(variable));					\
	switch(sizeof(variable)) {					\
	switch(sizeof(variable)) {					\
		case 1: stem##1(variable, __VA_ARGS__);break;		\
		case 1: stem##1(variable, __VA_ARGS__);break;		\
		case 2: stem##2(variable, __VA_ARGS__);break;		\
		case 2: stem##2(variable, __VA_ARGS__);break;		\