Skip to content

Commit

Permalink
percpu: make accessors check for percpu pointer in sparse
Browse files Browse the repository at this point in the history
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: Tejun Heo <tj@kernel.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Tejun Heo committed Oct 29, 2009
1 parent e0fdb0e commit 545695f
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
6 changes: 4 additions & 2 deletions include/asm-generic/percpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
*/
#ifndef SHIFT_PERCPU_PTR
/* Weird cast keeps both GCC and sparse happy. */
#define SHIFT_PERCPU_PTR(__p, __offset) \
RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset))
#define SHIFT_PERCPU_PTR(__p, __offset) ({ \
__verify_pcpu_ptr((__p)); \
RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
})
#endif

/*
Expand Down
20 changes: 18 additions & 2 deletions include/linux/percpu-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
#define __PCPU_DUMMY_ATTRS \
__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
* weak to force the compiler to generate GOT based external
Expand Down Expand Up @@ -129,10 +139,16 @@
__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_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 */
2 changes: 2 additions & 0 deletions include/linux/percpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ extern void __bad_size_call_parameter(void);

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

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

0 comments on commit 545695f

Please sign in to comment.