aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-10-29 09:34:15 -0400
committerTejun Heo <tj@kernel.org>2009-10-29 09:34:15 -0400
commit545695fb41da117928ab946067a42d9e15fd009d (patch)
tree1ea32c45a6f6efb03a88f99278f065054a5de3e2
parente0fdb0e050eae331046385643618f12452aa7e73 (diff)
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: Tejun Heo <tj@kernel.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--include/asm-generic/percpu.h6
-rw-r--r--include/linux/percpu-defs.h20
-rw-r--r--include/linux/percpu.h2
3 files changed, 24 insertions, 4 deletions
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index fded453fd25c..04f91c2d3f7b 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -42,8 +42,10 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
42 */ 42 */
43#ifndef SHIFT_PERCPU_PTR 43#ifndef SHIFT_PERCPU_PTR
44/* Weird cast keeps both GCC and sparse happy. */ 44/* Weird cast keeps both GCC and sparse happy. */
45#define SHIFT_PERCPU_PTR(__p, __offset) \ 45#define SHIFT_PERCPU_PTR(__p, __offset) ({ \
46 RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)) 46 __verify_pcpu_ptr((__p)); \
47 RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \
48})
47#endif 49#endif
48 50
49/* 51/*
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index 0fa0cb524250..1fa36eb54b6a 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -19,6 +19,16 @@
19 __attribute__((section(".discard"), unused)) 19 __attribute__((section(".discard"), unused))
20 20
21/* 21/*
22 * Macro which verifies @ptr is a percpu pointer without evaluating
23 * @ptr. This is to be used in percpu accessors to verify that the
24 * input parameter is a percpu pointer.
25 */
26#define __verify_pcpu_ptr(ptr) do { \
27 void __percpu *__vpp_verify = (typeof(ptr))NULL; \
28 (void)__vpp_verify; \
29} while (0)
30
31/*
22 * s390 and alpha modules require percpu variables to be defined as 32 * s390 and alpha modules require percpu variables to be defined as
23 * weak to force the compiler to generate GOT based external 33 * weak to force the compiler to generate GOT based external
24 * references for them. This is necessary because percpu sections 34 * references for them. This is necessary because percpu sections
@@ -129,10 +139,16 @@
129 __aligned(PAGE_SIZE) 139 __aligned(PAGE_SIZE)
130 140
131/* 141/*
132 * Intermodule exports for per-CPU variables. 142 * Intermodule exports for per-CPU variables. sparse forgets about
143 * address space across EXPORT_SYMBOL(), change EXPORT_SYMBOL() to
144 * noop if __CHECKER__.
133 */ 145 */
146#ifndef __CHECKER__
134#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var) 147#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var)
135#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var) 148#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var)
136 149#else
150#define EXPORT_PER_CPU_SYMBOL(var)
151#define EXPORT_PER_CPU_SYMBOL_GPL(var)
152#endif
137 153
138#endif /* _LINUX_PERCPU_DEFS_H */ 154#endif /* _LINUX_PERCPU_DEFS_H */
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 2c0d31a3f6b6..42878f0cd0e2 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -237,6 +237,7 @@ extern void __bad_size_call_parameter(void);
237 237
238#define __pcpu_size_call_return(stem, variable) \ 238#define __pcpu_size_call_return(stem, variable) \
239({ typeof(variable) pscr_ret__; \ 239({ typeof(variable) pscr_ret__; \
240 __verify_pcpu_ptr(&(variable)); \
240 switch(sizeof(variable)) { \ 241 switch(sizeof(variable)) { \
241 case 1: pscr_ret__ = stem##1(variable);break; \ 242 case 1: pscr_ret__ = stem##1(variable);break; \
242 case 2: pscr_ret__ = stem##2(variable);break; \ 243 case 2: pscr_ret__ = stem##2(variable);break; \
@@ -250,6 +251,7 @@ extern void __bad_size_call_parameter(void);
250 251
251#define __pcpu_size_call(stem, variable, ...) \ 252#define __pcpu_size_call(stem, variable, ...) \
252do { \ 253do { \
254 __verify_pcpu_ptr(&(variable)); \
253 switch(sizeof(variable)) { \ 255 switch(sizeof(variable)) { \
254 case 1: stem##1(variable, __VA_ARGS__);break; \ 256 case 1: stem##1(variable, __VA_ARGS__);break; \
255 case 2: stem##2(variable, __VA_ARGS__);break; \ 257 case 2: stem##2(variable, __VA_ARGS__);break; \