aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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; \